【问题标题】:Combine matrices of different length and keep column names组合不同长度的矩阵并保留列名
【发布时间】:2019-09-14 15:56:05
【问题描述】:

关于组合不同长度的向量有一个类似的问题here,但所有答案(@Ronak Shah 的答案除外)都会丢失名称/列名。

我的问题是我需要保留列名,这似乎可以使用rowr 包和cbind.fills。

我想留在 base-R 或使用 stringi 并且输出应保持为矩阵。

测试数据:

inp <- list(structure(c("1", "2"), .Dim = 2:1, .Dimnames = list(NULL,"D1")), 
            structure(c("3", "4", "5"), .Dim = c(3L, 1L), .Dimnames = list(NULL, "D2")))

我知道我可以事先获取列名,然后在创建矩阵后重新分配它们,例如:

## Using stringi
colnam <- unlist(lapply(inp, colnames))
out <- stri_list2matrix(inp)
colnames(out) <- colnam
out    

## Using base-R
colnam <- unlist(lapply(inp, colnames))
max_length <- max(lengths(inp))
nm_filled <- lapply(inp, function(x) {
  ans <- rep(NA, length = max_length)
  ans[1:length(x)]<- x
  ans
})
out <- do.call(cbind, nm_filled)
colnames(out) <- colnam
out

还有其他选项可以保留列名吗?

【问题讨论】:

  • 在那个问题中它是向量列表,但在这里你有矩阵列表。这是故意的吗?
  • 是的,我知道,但它仍然适用于矩阵。是的,它也可以有多个列,而不仅仅是 2 个。
  • 如何处理不同的列?例如,更改 inp[[1]] &lt;- cbind(inp[[1]], "D3" = 4) 后,inp 的预期输出是什么?
  • 应该填写NA。所以这应该导致cbind(inp[[1]], "D3" = c(4,NA))

标签: r cbind stringi


【解决方案1】:

既然stringi你可以使用,你可以使用函数stri_list2matrix(),即

setNames(as.data.frame(stringi::stri_list2matrix(inp)), sapply(inp, colnames))
#    D1 D2
#1    1  3
#2    2  4
#3 <NA>  5

【讨论】:

    【解决方案2】:

    这是一个稍微简洁的基础 R 变体

    len <- max(lengths(inp))
    nms <- sapply(inp, colnames)
    do.call(cbind, setNames(lapply(inp, function(x)
        replace(rep(NA, len), 1:length(x), x)), nms))
    #      D1  D2
    #[1,] "1" "3"
    #[2,] "2" "4"
    #[3,] NA  "5"
    

    不确定这是否构成与您已经发布的解决方案完全不同的解决方案。如果认为太相似将删除。


    更新

    或者merge怎么样?

    Reduce(
        function(x, y) merge(x, y, all = T, by = 0),
        lapply(inp, as.data.frame))[, -1]
    #    D1 D2
    #1    1  3
    #2    2  4
    #3 <NA>  5
    

    这里的想法是将list条目转换为data.frames,然后添加一个row数字和merge by row和merge通过设置逐行by = 0(感谢@Henrik)。请注意,这将返回 data.frame 而不是 matrix。

    【讨论】:

    • 您可以将sapply(inp, length)替换为lengths(inp)
    • 没有绝对值得回答的,因为它确实比我的 base-R 方法更紧凑。不幸的是,还需要先获取名称并重新分配它们。
    • @Sotos 啊,谢谢,我总是忘记lengths。进行了编辑。
    • @SeGa 我使用merge 添加了另一种方法。唯一的区别是它返回 data.frame 而不是 matrix。
    • 如果你在merge中指定by = 0(合并行名),lapply(inp, as.data.frame)就足够了。
    【解决方案3】:

    这里使用base:

    do.call(cbind,
            lapply(inp, function(i){
              x <- data.frame(i, stringsAsFactors = FALSE)
              as.matrix( x[ seq(max(lengths(inp))), , drop = FALSE ] ) 
              #if we matrices have more than 1 column use:
              #as.matrix( x[ seq(max(sapply(inp, nrow))), , drop = FALSE ] )
            }
            ))
    
    
    #    D1  D2 
    # 1  "1" "3"
    # 2  "2" "4"
    # NA NA  "5"
    

    这个想法是使所有矩阵具有相同的行数。当我们按索引对dataframe进行子集化时,不存在的行将作为NA返回,然后我们转换回矩阵和cbind。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-31
      • 1970-01-01
      • 2013-03-25
      • 2021-02-27
      • 2020-10-08
      • 2014-08-08
      • 2015-08-22
      相关资源
      最近更新 更多