在dplyr中创建一个新的列,它是特定列的总和(通过它们的名字选择)

qaxu7uf2  于 2023-04-27  发布在  其他
关注(0)|答案(5)|浏览(100)

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

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

现在想象一下,我有一个数据集,其中有20个列的名称中有'Petal'。我想创建一个列'Petal',将所有这些列相加。我绝对不想在代码中键入所有列的名称。感觉应该可以在dplyr中用一行代码实现。感谢任何人的帮助。

hjzp0vay

hjzp0vay1#

我同意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()除外)以选择列。

prdp8dxp

prdp8dxp2#

purrr使用reduce()rowSums稍微快一点,而且肯定比apply快,因为你避免了迭代所有的行,只利用了向量化操作:

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

请参阅此计时

cgvd09ve

cgvd09ve3#

我给出了类似的答案herehere。如果聚合函数是sum,rowSums是最佳选择:

iris %>% 
  mutate(Petal = rowSums(pick(starts_with("Petal"))))

但是你可以使用c_acrossrowwise

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

最大的好处是你可以使用sum之外的其他函数。rowSums是一个更好的选择,因为它更快,但如果你想应用sum之外的其他函数,这是一个很好的选择。
您可以使用c_acrosspick中的任何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
i2byvkas

i2byvkas4#

iris %>% mutate(Petal = rowSums(.[grep("Petal", names(.))], na.rm = T))

这个应该能用
names(.)从数据框中选择名称,grep搜索这些名称以找到匹配regex(“Petal”)的名称,rowSums添加每个列的值,并将其分配给新变量Petal。“.[]”语法是dplyr传递列名方式的解决方案。

fgw7neuy

fgw7neuy5#

更一般地说,为每个观测创建一个关键点(例如,下面使用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)

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

相关问题