【问题标题】:how do I search for columns with same name, add the column values and replace these columns with same name by their sum? Using R如何搜索具有相同名称的列,添加列值并用它们的总和替换这些具有相同名称的列?使用 R
【发布时间】:2011-05-16 19:49:44
【问题描述】:

我有一个数据框,其中一些连续的列具有相同的名称。我需要搜索这些,为每一行添加它们的值,删除一列并用它们的总和替换另一列。 在之前不知道哪些模式重复的情况下,可能不得不将一个列名与以下列名进行比较以查看是否匹配。

有人可以帮忙吗?

提前致谢。

【问题讨论】:

    标签: r


    【解决方案1】:
    > dfrm <- data.frame(a = 1:10, b= 1:10, cc= 1:10, dd=1:10, ee=1:10)
    > names(dfrm) <- c("a", "a", "b", "b", "b")
    > sapply(unique(names(dfrm)[duplicated(names(dfrm))]), 
          function(x) Reduce("+", dfrm[ , grep(x, names(dfrm))]) )
           a  b
     [1,]  2  3
     [2,]  4  6
     [3,]  6  9
     [4,]  8 12
     [5,] 10 15
     [6,] 12 18
     [7,] 14 21
     [8,] 16 24
     [9,] 18 27
    [10,] 20 30
    

    编辑 2:使用 rowSums 可以将第一个 sapply 参数简化为 unique(names(dfrm)),但需要记住在 "[" 中包含 drop=FALSE:

    sapply(unique(names(dfrm)), 
           function(x) rowSums( dfrm[ , grep(x, names(dfrm)), drop=FALSE]) )
    

    处理 NA 的问题:

    sapply(unique(names(dfrm)), 
          function(x) apply(dfrm[grep(x, names(dfrm))], 1, 
                  function(y) if ( all(is.na(y)) ) {NA} else { sum(y, na.rm=TRUE) }
           )               )
    

    (编辑说明:通过在 names(.)[.] 结构周围加上 unique 来解决 Tommy 的反例。 错误代码是:

    sapply(names(dfrm)[unique(duplicated(names(dfrm)))], 
         function(x) Reduce("+", dfrm[ , grep(x, names(dfrm))]) )
    

    【讨论】:

    • 不适用于dfrm=data.frame(a=1:10, b=20:29, a=101:110, b=200:209, a=1001:1010, check.names=F)
    • @Tommy。谢谢。指出我应该将唯一性包裹在名称(dfrm)[重复...]固定。
    • 谢谢,虽然我怀疑 rowSums 会更快。
    • 我的数据有缺失值。如何更改此函数以给我:1)如果一组变量中的所有列值都丢失,则为 NA;2)如果至少有一个值,则为值。我尝试使用条件并使用 is.na() 检查 NA,但失败了。不能使用 na.rm=FALSE 或 TRUE。
    【解决方案2】:

    这是我的一个班轮

    # transpose data frame, sum by group = rowname, transpose back.
    t(rowsum(t(dfrm), group = rownames(t(dfrm))))
    

    【讨论】:

    • +1。非常整洁,但值得注意的是,如果需要的话,这需要as.data.frame()
    • @Henry。是的。很容易将此输出操作为 OP 想要的任何格式。由于它使用调用 C 函数的rowsum,因此速度很快,并且在示例数据集上运行速度提高了 1.5 倍。我怀疑在更大的数据帧上它会更快。
    【解决方案3】:

    一些示例数据。

    dfr <- data.frame(
      foo = rnorm(20),
      bar = 1:20,
      bar = runif(20),
      check.names = FALSE
    )
    

    方法:循环遍历唯一的列名;如果只有一个该名称,则选择具有该 NME 的所有列将返回一个向量,但如果有重复,它也将是一个数据框。使用rowSums 对行求和。 (Duh. 编辑:不像以前想象的那么“duh”!) lapply 返回一个列表,我们需要将其重新转换为数据框,最后我们修复名称。 编辑:sapply 避免了最后一步的需要。

    unique_col_names <- unique(colnames(dfr))
    new_dfr <- sapply(unique_col_names, function(name)
    {
      subs <- dfr[, colnames(dfr) == name]
      if(is.data.frame(subs))
        rowSums(subs)
      else
        subs
    })
    

    【讨论】:

    • 关于 'Duh':rowSums 确实对行求和,但 rowsum 对列求和 ;-)
    • 感谢您的回复。我曾使用 rowSums “Duh”,这不是我的问题的主要问题!另外,如果我可以这么说的话,我认为“Duh”不是一个合适的“功能”在这个论坛上发帖!;)
    【解决方案4】:

    一种方法是使用(惊喜)duplicated 函数来识别重复项,然后遍历它们以计算总和。这是一个例子:

    dat.dup <- data.frame(x=1:10, x=1:10, x=1:10, y=1:10, y=1:10, z=1:10, check.names=FALSE)
    dups <- unique(names(dat.dup)[duplicated(names(dat.dup))])
    for (i in dups) {
    dat.dup[[i]] <- rowSums(dat.dup[names(dat.dup) == i])
    }
    dat <- dat.dup[!duplicated(names(dat.dup))]
    

    【讨论】:

    • 谢谢,这是我最初的想法,但我没有编写代码。我也不熟悉“独特”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    相关资源
    最近更新 更多