【问题标题】:[R]Split a character vector into data frame rows by set number of columns[R]按设定的列数将字符向量拆分为数据框行
【发布时间】:2018-07-05 21:19:54
【问题描述】:

我似乎无法专门找到这个(我看过这里:How to split a character vector into data frame?)和其他一些地方。

我正在尝试将 R 中的字符向量拆分为具有一定列数的数据帧,为任何额外或缺失填充 NA。如下(可重现):

###Reproduce column vector
cv <- c("a1", "b1", "c1", "d1", "e1", "f1", "aa2", "bb2", "cc2", "dd2", "ee2", "ff2", "x1", "x2", "x3", "x4", "x5", "x6", "rr2", "tt3", "bb4")

###Desired data frame separating 6 columns
df.desired <- data.frame(col1=c("a1","aa2","x1","rr2"),col2=c("b1","bb2","x2","tt3"),col3=c("c1","cc2","x3","bb4"),col4=c("d1","dd2","x4",NA),col5=c("e1","ee2","x5",NA),col6=c("f1","ff2","x6",NA),stringsAsFactors = F)

提前致谢!

【问题讨论】:

  • 您能否更明确地说明将NA 分配给不同列的规则。干杯

标签: r dataframe vector multiple-columns


【解决方案1】:

1) 基数 创建一个包含所需维度的 NA 值的矩阵,然后用cv 填充到它的长度。转置并转换为数据框。

mat <- t(replace(matrix(NA, 6, ceiling(length(cv) / 6)), seq_along(cv), cv))
as.data.frame(mat, stringsAsFactors = FALSE)

2) 另一个基本解决方案 使用 cv2cv 副本将其长度扩展到所需的长度,然后将其重新整形为矩阵。我们使用cv2 以保留原始cv,但如果您不介意在cv 末尾添加NA,那么您可以使用它而不是创建cv2,将代码减少一行(两个如果我们可以使用mat 而不是需要数据框,则为行)。该解决方案通过使用matrixbyrow 参数来避免需要使用转置。

cv2 <- cv
length(cv2) <- 6 * ceiling(length(cv) / 6)
mat <- matrix(cv2,, 6, byrow = TRUE)
as.data.frame(mat, stringsAsFactors = FALSE)

3) 使用 ts 的基本解决方案 此方法通过从 ts 对象的时间中提取行和列索引来获取行索引和列索引,而不是通过数值计算来计算维度。为此,从cv 中创建ts 对象的时间tttt 本身是一个 ts 对象,其中 as.integer(tt) 是行索引号,cycle(tt) 是列索引号。最后使用tapply

tt <- time(ts(cv, frequency = 6))
mat <- tapply(cv, list(as.integer(tt), cycle(tt)), c)
as.data.frame(mat, stringsAsFactors = FALSE)

4) rollapply 像(3)这个没有明确计算mat的维度。它使用 zoo 包中的 rollapply 和一个简单的函数 Fillr 来避免这种情况。 Fill 函数返回它的参数x,在右边用 NA 填充到长度为 6。

library(zoo)

Fill <- function(x) { length(x) <- 6; x }
mat <- rollapplyr(cv, 6, by = 6, Fill, align = "left", partial = TRUE)
as.data.frame(mat, stringsAsFactors = FALSE)

如果矩阵mat 作为结果足够,则在上述所有备选方案中省略最后一行。

添加

从 R 4.0 开始,stringsAsFaactors=FALSE 是默认值,因此可以在上面省略。

【讨论】:

    【解决方案2】:

    1) base R - split vector 使用gl 创建的分组变量,然后在末尾附加NA length&lt;-

    lst <- split(cv, as.integer(gl(length(cv), 6, length(cv))))
    as.data.frame(do.call(rbind, lapply(lst, `length<-`, max(lengths(lst)))))
    #  V1  V2  V3   V4   V5   V6
    #1  a1  b1  c1   d1   e1   f1
    #2 aa2 bb2 cc2  dd2  ee2  ff2
    #3  x1  x2  x3   x4   x5   x6
    #4 rr2 tt3 bb4 <NA> <NA> <NA>
    

    【讨论】:

      猜你喜欢
      • 2021-12-29
      • 2014-04-22
      • 1970-01-01
      • 2021-06-18
      • 2016-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多