如何在不使用dcast的情况下将类型列表的列嵌套为宽格式

问题描述

我有一个data.table,其列的类型为list。我想将此列表列转换为宽格式的新列。我可以使用unlist首先创建长格式的表格,然后使用dcast将其转换为宽格式(尽管我在此过程中使用了原始列表列,因为dcast表示Columns specified in formula can not be of type list

示例:

我有一个数据表,如下所示:

dt = data.table(
  list_col = list(c(404,444),c(404,c(444,484),c(364,404)),other_col = c('A','B','D','E','A'))

我可以做到:

# create a row id
dt[,row_id := .I]

# cast to wide
dcast(
  # replicate the data table,so that rows are matched properly when unlisting
  dt[
    rep(dt[,.I],lengths(list_col))
    ][,# unlist the list column
      unlist_col := unlist(dt$list_col)
      ][,# crate a row id per group so that we kNow how to cast to wide
        group_row_id := rowid(row_id)
        ][],# here i lose the original list_col,because i can't put the column of type list to the formula
  other_col + row_id ~ group_row_id,value.var = 'unlist_col')

这给出了预期的结果,我什至可以通过加入row_id或通过按row_id对结果表进行排序并将新列添加到原始表中来修复丢失列表列的事实,但这确实是如果此操作有更简单的方法,那就很好。

解决方法

使用data.table::transpose()

dt[,c("col1","col2") := transpose(list_col)]

#    list_col other_col col1 col2
# 1:  404,444         A  404  444
# 2:  404,444         B  404  444
# 3:  444,484         D  444  484
# 4:  444,484         E  444  484
# 5:  364,404         A  364  404
,

如果list_col中的项目数相同,则可以尝试以下代码:

> dt = cbind(dt,t(matrix(unlist(dt$list_col),ncol=nrow(dt))))
> dt
   list_col other_col  V1  V2
1:  404,444         A 404 444
2:  404,444         B 404 444
3:  444,484         D 444 484
4:  444,484         E 444 484
5:  364,404         A 364 404

然后,您可以更改新添加的列的名称。