【问题标题】:create a new column which is the sum of specific columns (selected by their names) in dplyr创建一个新列,它是 dplyr 中特定列(按名称选择)的总和
【发布时间】:2018-05-25 08:31:18
【问题描述】:

我的问题是如何创建一个新列,该列是 dplyr 中某些特定列(按名称选择)的总和。 例如,对于 iris 数据集,我创建了一个名为 Petal 的新列,它是 Petal.Length 和 Petal.Width 的总和。

iris %>% mutate(Petal = Petal.Length+Petal.Width)

现在想象一下,我有一个包含 20 列的数据集,其名称中包含“花瓣”。我想创建一个汇总所有这些列的“花瓣”列。我绝对不想在我的代码中键入所有列名。感觉应该可以用 dplyr 中的一行代码来实现。 如果有人可以提供帮助,请不胜感激。

【问题讨论】:

  • 听起来您的数据格式不整齐。最好将gather() 转换为长格式和summarize()。关于“从宽到长”的重塑存在许多现有问题。

标签: r dplyr tidyverse


【解决方案1】:

我同意 MrFlick 的观点,即整理您的数据是可取的——尤其是如果您想做任何事情而不是对这些列求和——但这里有一个选择:

iris %>% mutate(
   Petal = rowSums(select(., starts_with("Petal")))
)

    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species Petal
1            5.1         3.5          1.4         0.2     setosa   1.6
2            4.9         3.0          1.4         0.2     setosa   1.6
3            4.7         3.2          1.3         0.2     setosa   1.5
4            4.6         3.1          1.5         0.2     setosa   1.7
5            5.0         3.6          1.4         0.2     setosa   1.6
...

请参阅?select 以外的starts_with() 辅助选项来选择列。

【讨论】:

    【解决方案2】:

    更一般地,为每个观察创建一个键(例如,行号使用下面的mutate),将感兴趣的列移动到两列,一列保存列名,另一列保存值(使用melt下面),group_by 观察,并做任何你想做的计算。下面,我使用mutate 添加一列,对包含单词“Petal”的所有列求和,最后删除我不想要的任何变量(使用select)。

    require(dplyr)
    require(reshape2)
    
    iris %>%
      mutate(observation = 1:nrow(iris)) %>% 
      melt(
        measure.vars = grep("Petal", colnames(iris)), 
        variable.name = 'variable', 
        value.name = 'value') %>% 
      group_by(observation) %>%
      mutate(Petal = sum(value)) %>% 
      select(-observation, -variable, -value)
    

    虽然上面可以缩短,但我认为这个版本会提供一些指导。

    【讨论】:

      【解决方案3】:

      使用purrr 中的reduce()rowSums 稍快,并且肯定比apply 快,因为您避免遍历所有行,而只需利用矢量化操作:

      library(purrr)
      library(dplyr)
      iris %>% mutate(Petal = reduce(select(., starts_with("Petal")), `+`))
      

      请参阅this 了解时间

      【讨论】:

        【解决方案4】:
        iris %>% mutate(Petal = rowSums(.[grep("Petal", names(.))], na.rm = T))
        

        这应该可行。

        names(.) 从您的数据框中选择名称,grep 搜索这些名称以找到与正则表达式(“花瓣”)匹配的名称,rowSums 添加每列的值,将它们分配给您的新变量 @ 987654325@。 ".[]" 语法是 dplyr 传递列名的一种变通方法。

        【讨论】:

          【解决方案5】:

          我给出了类似的答案herehere,但是你可以使用c_acrossrowwise

          iris %>% 
            rowwise() %>% 
            mutate(Petal = sum(c_across(starts_with("Petal")))) %>% 
            ungroup()
          

          最大的好处是你可以使用除sum之外的其他功能。 rowSums 是一个更好的选择,因为它更快,但如果您想应用除 sum 之外的其他功能,这是一个不错的选择。

          此外,您可以使用任何 tidyselect 选项按名称、位置、类、一系列连续列等选择列。

          输出

            Sepal.Length Sepal.Width Petal.Length Petal.Width Species Petal
                    <dbl>       <dbl>        <dbl>       <dbl> <fct>   <dbl>
           1          5.1         3.5          1.4         0.2 setosa    1.6
           2          4.9         3            1.4         0.2 setosa    1.6
           3          4.7         3.2          1.3         0.2 setosa    1.5
           4          4.6         3.1          1.5         0.2 setosa    1.7
           5          5           3.6          1.4         0.2 setosa    1.6
           6          5.4         3.9          1.7         0.4 setosa    2.1
           7          4.6         3.4          1.4         0.3 setosa    1.7
           8          5           3.4          1.5         0.2 setosa    1.7
           9          4.4         2.9          1.4         0.2 setosa    1.6
          10          4.9         3.1          1.5         0.1 setosa    1.6
          # ... with 140 more rows
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-02-13
            • 1970-01-01
            • 2023-03-29
            • 1970-01-01
            • 2020-08-21
            相关资源
            最近更新 更多