将列表列中的值分配到单独的列

时间:2019-10-30 17:04:48

标签: r list data.table

我有一个带有list列“ c”的data.table:

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)]

预期数据表为:

> 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

2 个答案:

答案 0 :(得分: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

如果我们想要零而不是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 :(得分: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()混淆。