[英]R reshaping melted data.table with list column
我有一個大的(數百萬行)熔化的data.table
與通常的melt
樣式展開variable
和value
列。 我需要以寬泛的形式轉換表(滾動變量)。 問題是數據表還有一個名為data
的列表列,我需要保留它。 這使得無法使用reshape2
因為dcast
無法處理非原子列。 因此,我需要自己卷起來。
由於列表列,上一個關於使用熔化數據表的問題的答案在這里不適用。
我對我提出的解決方案不滿意。 我正在尋找更簡單/更快實現的建議。
x <- LETTERS[1:3]
dt <- data.table(
x=rep(x, each=2),
y='d',
data=list(list(), list(), list(), list(), list(), list()),
variable=rep(c('var.1', 'var.2'), 3),
value=seq(1,6)
)
# Column template set up
list_template <- Reduce(
function(l, col) { l[[col]] <- col; l },
unique(dt$variable),
list())
# Expression set up
q <- substitute({
l <- lapply(
list_template,
function(col) .SD[variable==as.character(col)]$value)
l$data = .SD[1,]$data
l
}, list(list_template=list_template))
# Roll up
dt[, eval(q), by=list(x, y)]
x y var.1 var.2 data
1: A d 1 2 <list>
2: B d 3 4 <list>
3: C d 5 6 <list>
我有一些欺騙方法可能會做到這一點 - 重要的是,我認為每個x,y,列表組合都是獨一無二的! 如果沒有,請忽略。
我將創建兩個單獨的數據表,第一個是沒有數據列表對象的數據,第二個只有唯一的數據列表對象和一個鍵。 然后將它們合並在一起以獲得所需的結果。
require(data.table)
require(stringr)
require(reshape2)
x <- LETTERS[1:3]
dt <- data.table(
x=rep(x, each=2),
y='d',
data=list(list("a","b"), list("c","d")),
variable=rep(c('var.1', 'var.2'), 3),
value=seq(1,6)
)
# First create the dcasted datatable without the pesky list objects:
dt_nolist <- dt[,list(x,y,variable,value)]
dt_dcast <- data.table(dcast(dt_nolist,x+y~variable,value.var="value")
,key=c("x","y"))
# Second: create a datatable with only unique "groups" of x,y, list
dt_list <- dt[,list(x,y,data)]
# Rows are duplicated so I'd like to use unique() to get rid of them, but
# unique() doesn't work when there's list objects in the data.table.
# Instead so I cheat by applying a value to each row within an x,y "group"
# that is unique within EACH group, but present within EVERY group.
# Then just simply subselect based on that unique value.
# I've chosen rank(), but no doubt there's other options
dt_list <- dt_list[,rank:=rank(str_c(x,y),ties.method="first"),by=str_c(x,y)]
# now keep only one row per x,y "group"
dt_list <- dt_list[rank==1]
setkeyv(dt_list,c("x","y"))
# drop the rank since we no longer need it
dt_list[,rank:=NULL]
# Finally just merge back together
dt_final <- merge(dt_dcast,dt_list)
這個古老的問題激起了我的好奇心,因為自2013年以來,數據data.table
已經大大改善。
但是,即使使用data.table
版本1.11.4
dcast(dt, x + y + data ~ variable)
仍然會返回錯誤
公式中指定的列不能是類型列表
解決方法遵循jonsedar的答案的大致輪廓:
x
和y
分組的列表列data
x
和y
上加入兩個部分結果 但使用實際data.table
語法的功能,例如on
參數:
dcast(dt, x + y ~ variable)[
dt[, .(data = .(first(data))), by = .(x, y)], on = .(x, y)]
xy var.1 var.2 data 1: A d 1 2 <list> 2: B d 3 4 <list> 3: C d 5 6 <list>
通過獲取第一個元素來聚合列表列data
。 這符合OP的代碼行
l$data = .SD[1,]$data
這也選擇了第一個元素。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.