【问题标题】:Sum columns row-wise with similar names对具有相似名称的列按行求和
【发布时间】:2018-09-26 07:03:30
【问题描述】:

我有一个 dataframe,其中有很多类似这样的列:

data <- data.frame (a.1 = 1:5, a.2b = 3:7, a.5 = 5:9, bt.16 = 4:8, bt.12342 = 7:11)

我想要一个包含对具有相同前缀的变量求和的列的结果。在这个例子中,我想返回一个数据框: a = (9:13), bt = (11:15)

我的真实数据集相当复杂(我想结合具有不同 utm 参数的网页的页面查看次数),但这种情况的解决方案应该让我走上正轨。

【问题讨论】:

  • “具有相同前缀的变量”是什么意思?
  • 这行得通吗? library(magrittr); lapply(c("a","bt"), function(x) rowSums(data[, grepl(x, names(data))])) %&gt;% setNames(., c("a","bt")) %&gt;% data.frame
  • 您是否尝试过 select(data, starts_with("prefix")) 之类的 tidyverse 函数?
  • 要添加到迈克的答案,您可能需要startsWith(names(data), x)] 而不是grepl(x, names(data))

标签: r dataframe sum rowwise


【解决方案1】:

这里有一个基于 R 的解决方案:

> prefixes = unique(sub("\\..*", "", colnames(data)))
> sapply(prefixes, function(x)rowSums(data[,startsWith(colnames(data), x)]))
      a bt
[1,]  9 11
[2,] 12 13
[3,] 15 15
[4,] 18 17
[5,] 21 19

【讨论】:

    【解决方案2】:

    你可以试试

    library(tidyverse)
    data.frame (a.1 = 1:5, a.2b = 3:7, a.5 = 5:9, bt.16 = 4:8, bt.12342 = 7:11) %>% 
      rownames_to_column() %>% 
      gather(k, v, -rowname) %>% 
      separate(k, letters[1:2]) %>% 
      group_by(rowname, a) %>% 
      summarise(Sum=sum(v)) %>% 
      spread(a, Sum)
    #> # A tibble: 5 x 3
    #> # Groups:   rowname [5]
    #>   rowname     a    bt
    #>   <chr>   <int> <int>
    #> 1 1           9    11
    #> 2 2          12    13
    #> 3 3          15    15
    #> 4 4          18    17
    #> 5 5          21    19
    

    由reprex package (v0.2.0) 于 2018 年 4 月 16 日创建。

    你也可以这样做:

    data.frame (a.1 = 1:5, a.2b = 3:7, a.5 = 5:9, bt.16 = 4:8, bt.12342 = 7:11) %>% 
      rownames_to_column() %>% 
      pivot_longer(-1, names_to = c(".value", "set"), names_sep = "[.]") %>% 
      group_by(rowname) %>% 
      summarise(across(a:bt,sum, na.rm=T))
    # A tibble: 5 x 3
      rowname     a    bt
      <chr>   <int> <int>
    1 1           9    11
    2 2          12    13
    3 3          15    15
    4 4          18    17
    5 5          21    19
    

    【讨论】:

      【解决方案3】:

      这是另一个tidyverse 解决方案:

      library(tidyverse)
      
      t(data) %>%
        data.frame() %>%
        group_by(., id = gsub('\\..*', '', rownames(.))) %>%
        summarise_all(sum) %>%
        data.frame() %>%
        column_to_rownames(var = 'id') %>%
        t()
      

      结果:

          a bt
      X1  9 11
      X2 12 13
      X3 15 15
      X4 18 17
      X5 21 19
      

      【讨论】:

        【解决方案4】:
        data <- data.frame (a.1 = 1:5, a.2b = 3:7, a.5 = 5:9, bt.16 = 4:8, bt.12342 = 7:11)
        i <- grepl("a.", names(data), fixed = TRUE)
        result <- data.frame(a=rowSums(data[, i]), bt=rowSums(data[, !i]))
        result
        # > result
        #    a bt
        # 1  9 11
        # 2 12 13
        # 3 15 15
        # 4 18 17
        # 5 21 19
        

        如果你有两个以上的前缀,你可以这样做:

        prefs <- c("a.", "bt.")
        as.data.frame(lapply(prefs, function(p) rowSums(data[, grepl(p, names(data), fixed = TRUE)]) ))
        

        【讨论】:

          【解决方案5】:

          使用基本 R 的 rowsum 函数的单线方法怎么样:

          > t(rowsum(t(data), group = sub("\\..*", "", colnames(data))))
                a bt
          [1,]  9 11
          [2,] 12 13
          [3,] 15 15
          [4,] 18 17
          [5,] 21 19
          

          这个想法是转置数据,使列成为行,然后应用rowsum 函数来汇总由相同组标签索引的这些行。再次转置将数据返回到其原始形式,现在汇总了具有相同标签的列。

          【讨论】:

            猜你喜欢
            • 2021-08-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-08-03
            • 1970-01-01
            • 1970-01-01
            • 2020-10-25
            相关资源
            最近更新 更多