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

Rus*_*oua 7 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
Run Code Online (Sandbox Code Playgroud)

我想为“ 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
Run Code Online (Sandbox Code Playgroud)

我想像这样将“ 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
Run Code Online (Sandbox Code Playgroud)

我尝试过的

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)]
Run Code Online (Sandbox Code Playgroud)

预期的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
Run Code Online (Sandbox Code Playgroud)

小智 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])
        }
      })
  )
}
Run Code Online (Sandbox Code Playgroud)

说明

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

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
Run Code Online (Sandbox Code Playgroud)

我们看到,如果没有值,我们就有一个NA.
我们需要一个迭代器来提取位置 处的所有值idx。为此,我们将找到df$c(列表)每个元素中的值的数量并保留最大值。

max(sapply(df$c, length))
[1] 3
Run Code Online (Sandbox Code Playgroud)

如果我们想要零而不是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
Run Code Online (Sandbox Code Playgroud)