通过将列与缺少数据的列表组合来制作数据框,strsplit,没有索引

making dataframe by combining columns with lists with missing data, strsplit, without an index

抱歉,如果这很明显,我已经找到了一些用于有索引或缺少列的东西。但我认为这两者都不适用。

示例数据:

df.test=data.frame( A=c("n,n,y,n"  ,"t", "j,k,k")
                   ,B=c("n,y,y,n"  ,"" , "k,k,k")
                   ,C=c("n,y,y,n,n","t", "j,k,j")
                   ,D=c(""         ,"" , "k,k,j")
                     )

df.test=lapply(df.test, function(x) as.character(x))
str(df.test)   # looks similar to my data

List of 4
 $ A: chr [1:3] "n,n,y,n" "t" "j,k,k"
 $ B: chr [1:3] "n,y,y,n" "" "k,k,k"
 $ C: chr [1:3] "n,y,y,n,n" "t" "j,k,j"
 $ D: chr [1:3] "" "" "k,k,j"

我的目标是数据框:

A B C D
n n n NA
n y y NA
y y y NA
n n n NA
t NA t NA
j k j k
k k k k
k k j j

我希望 A 列作为参考,但它没有唯一值。但是,它具有每个列表允许的最大数量的值(我希望这是有道理的)。因此,应该删除C 列表1 中的第五个值,即n y y n n -> n y y n。 此外,还需要添加缺失值(根据第 A 列缺失)。 C 中的额外值是其他软件的错误(我对此没有影响)。除了那些额外的值,它们相互对应,例如 t 应该在同一行(如果存在)。

到目前为止我做的最好的就是制作一个向量列表,列表有不同的长度,所以我不能把它们放在一起而且它们不对应。

df3=lapply(df.test, function(x) unlist(strsplit(x,',')))
str(df3)

List of 4
 $ A: chr [1:8] "n" "n" "y" "n" ...
 $ B: chr [1:7] "n" "y" "y" "n" ...
 $ C: chr [1:9] "n" "y" "y" "n" ...
 $ D: chr [1:3] "k" "k" "j"

由于您要控制 A 列,我们可以先预先计算 A 列中字符串元素的字段长度。这可以通过对 df.test[[1L]] 的初始 strsplit() 调用来完成,然后参加 lengths().

然后,我们可以使用lapply()遍历所有列并用strsplit()拆分它们。为了确保我们根据 A 列的控制长度来限制每个拆分字符串向量,我们必须将每个拆分字符串向量从 1 索引到 A 列的长度,并通过 seq_len() 计算索引向量。这可以使用 Map() 并行迭代拆分字符串向量和预计算长度向量来完成。索引拆分字符串向量可以方便地完成两件事:(1) 限制长度,以及 (2) returns NA 用于当前列的拆分字符串向量中未表示的尾部索引。我们最终可以 unlist() 拆分字符串向量的结果列表以获得单个列向量,并将整个内容包装在 as.data.frame() 中以将列表强制为 data.frame.

ls1 <- lengths(strsplit(df.test[[1L]],','));
as.data.frame(lapply(df.test,function(x)
    unlist(Map(function(ss,l) ss[seq_len(l)],strsplit(x,','),ls1))
),stringsAsFactors=F);
##   A    B C    D
## 1 n    n n <NA>
## 2 n    y y <NA>
## 3 y    y y <NA>
## 4 n    n n <NA>
## 5 t <NA> t <NA>
## 6 j    k j    k
## 7 k    k k    k
## 8 k    k j    j

见上面bgoldst的回答。

以下是我想出的,以防万一它对任何人都有用。它适用于示例数据,但不适用于实际数据,只是在研究为什么发布了更好的答案。

再次感谢。

df6=lapply(df.test, function(x) strsplit(x,','))

  df7=data.frame()
  df7=lapply(df7, function(x) as.character(x))

  for (i in 1:length(df6$A)){
    for (ii in 1:length(df6$A[[i]])){
      df7=rbind(df7,sapply(df6,function(x) x[[i]][ii]))
    }
  }

  str(df7)

  print(df7)