将列表列中的分派值分别放入各自的列中

7

我有一个带有list列“c”的数据表:

df <- data.table(a = 1:3, c = list(1L, 1:2, 1:3))
df
   a     c
1: 1     1
2: 2   1,2
3: 3 1,2,3

我希望为“c”中的值创建单独的列。

我创建了一组新的列F_1,F_2,F_3:

mmax <- max(df$a)
flux <- paste("F", 1:mmax, sep = "_")
df[, (flux) := 0]

df
   a     c F_1 F_2 F_3
1: 1     1   0   0   0
2: 2   1,2   0   0   0
3: 3 1,2,3   0   0   0

我想把"c"中的值分派到F_1、F_2、F_3这三列中,具体做法如下:

df

   a     c F_1 F_2 F_3
1: 1     1   1   0   0
2: 2   1,2   1   2   0
3: 3 1,2,3   1   2   3

我已尝试过的方法:
comp_vect <- function(vec, mmax){
  vec   <- vec %>% unlist()
  n     <- length(vec)
  answr <- c(vec, rep(0, l = mmax -n)) 
}


df[ , ..flux := mapply(comp_vect, c, mmax)]

期望的 data.table 如下:
> df

   a     c F_1 F_2 F_3
1: 1     1   1   0   0
2: 2   1,2   1   2   0
3: 3 1,2,3   1   2   3

3
d[ , (cols) := transpose(c, fill = 0)] - Henrik
@Henrik,你应该把这个作为答案发布吗?df[, paste("F_", 1:3) := transpose(d, fill = 0L)] - s_baldur
1
你也可以使用 lengths 来确定要创建的列名数量;paste0("f_", seq_len(max(lengths(df$c)))) - Henrik
2个回答

1
解决方案:

for(idx in seq(max(sapply(df$c, length)))){  # maximum number of values according to all the elements of the list
  set(x = df,
      i = NULL,
      j = paste0("F_",idx),  # column's name
      value = sapply(df$c, function(x){
        if(is.na(x[idx])){
          return(0)  # 0 instead of NA
        } else {
          return(x[idx])
        }
      })
  )
}

说明

我们可以像这样从列表中提取值:

sapply(df$c, function(ll) return(ll[1])) # first value
[1] 1 1 1
sapply(df$c, function(ll) return(ll[2])) # second value
[1] NA  2  2
sapply(df$c, function(ll) return(ll[3])) # third value
[1] NA NA  3

我们可以看到,如果没有值,就会出现NA
我们需要一个迭代器来提取在位置idx的所有值。为此,我们将找到df$c(列表)中每个元素中的值数量,并保留最大值。
max(sapply(df$c, length))
[1] 3

如果我们想要0替代NAs,我们需要在sapply中创建一个函数来进行转换:
vec <- c(NA, 5, 1, NA)
> sapply(vec, function(x) if(is.na(x)) return(0) else return(x))
[1] 0 5 1 0

1
我采用了一个完全不同的方法。我将列表列进行了rbind,然后进行了dcast,获得了所需的结果。最后一步是设置名称。
library(data.table)
df <- data.table(a = 1:3, d = list(1L, c(1L, 2L), c(1L, 2L, 3L)))

df2 <- df[, rbind(d), by = a][, dcast(.SD, a ~ V1, fill = 0)]

setnames(df2, 2:4, flux)[]
   a F_1 F_2 F_3
1: 1   1   0   0
2: 2   1   2   0
3: 3   1   2   3

这里的 flux 是你在问题中定义的变量名称。

请注意避免使用列名 c,因为它可能会与函数 c() 混淆。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接