如何绑定行而不丢失带有字符(0)的行?

How to bind rows without losing those with character(0)?

我有一个类似 L 的列表(来自向量拆分)。

L <- strsplit(c("1 5 9", "", "3 7 11", ""), " ")

# [[1]]
# [1] "1" "5" "9"
# 
# [[2]]
# character(0)
# 
# [[3]]
# [1] "3"  "7"  "11"
# 
# [[4]]
# character(0)

当我按如下方式执行普通 rbind 时,我丢失了所有 character(0) 行。

do.call(rbind, L)
#      [,1] [,2] [,3]
# [1,] "1"  "5"  "9" 
# [2,] "3"  "7"  "11"

我是否总是需要像下面那样做 lapply 还是我错过了什么?

do.call(rbind, lapply(L, function(x) 
    if (length(x) == 0)  rep("", 3) else x))
#      [,1] [,2] [,3]
# [1,] "1"  "5"  "9" 
# [2,] ""   ""   ""  
# [3,] "3"  "7"  "11"
# [4,] ""   ""   ""  

首选 R 基础答案。

也许这个使用 data.table 的环岛适合你:

L <- data.table::tstrsplit(c("1 5 9", "", "3 7 11", ""), " ", fill="")
t(do.call(rbind,L))

plyr然后进行替换。由于 OP 要求使用基础 R,请参见下文。

 plyr::ldply(L,rbind)
     1    2    3
1    1    5    9
2 <NA> <NA> <NA>
3    3    7   11
4 <NA> <NA> <NA>

一种效率较低的基础 R 方式:

 L <- strsplit(c("1 5 9", "", "3 7 11", ""), " ")
 L[lapply(L,length)==0]<-"Miss"
 res<-Reduce(rbind,L)
 res[res=="Miss"]<-""

结果:

     [,1] [,2] [,3]
init "1"  "5"  "9" 
     ""   ""   ""  
     "3"  "7"  "11"
     ""   ""   ""  

如果您使用 lapply,则不必担心长度,因此您可以跳过 rep 部分,它将自动跨列回收。

do.call(rbind, lapply(L, function(x) if (length(x) == 0)  "" else x))

#    [,1] [,2] [,3]
#[1,] "1"  "5"  "9" 
#[2,] ""   ""   ""  
#[3,] "3"  "7"  "11"
#[4,] ""   ""   ""  

另一个选项使用与@NelsonGon 相同的逻辑,我们可以用空白替换空列表,然后 rbind

L[lengths(L) == 0] <- ""
do.call(rbind, L)

#    [,1] [,2] [,3]
#[1,] "1"  "5"  "9" 
#[2,] ""   ""   ""  
#[3,] "3"  "7"  "11"
#[4,] ""   ""   ""  

这是为此类场景定义的行为。如 ?rbind 中所写:

For cbind (rbind), vectors of zero length (including NULL) are ignored unless the result would have zero rows (columns), for S compatibility. (Zero-extent matrices do not occur in S3 and are not ignored in R.)

当您检查元素时,您发现它是真的:

length(L[[1]])

[1] 3

length(L[[2]])

[1] 0

但是,如您所见,有多种解决方法。

我们可以简单的使用stri_list2matrix

library(stringi)
stri_list2matrix(L, byrow = TRUE, fill = "")
#   [,1] [,2] [,3]
#[1,] "1"  "5"  "9" 
#[2,] ""   ""   ""  
#[3,] "3"  "7"  "11"
#[4,] ""   ""   ""