Суммируйте столбец на основе значения ячейки в другом столбце той же строки в R - PullRequest
0 голосов
/ 31 марта 2020

У меня есть этот фрейм данных:

names <- c("george","fred","bill","george",'fred',"bill")
val1  <- c(2,3,4,6,7,8)
val2  <- c(3,4,5,6,8,7)
ch    <- c("yes","no","yes","no","yes","no")
tot   <- data.frame(names,val1,val2,ch)


names val1 val2  ch
1 george    2    3 yes
2   fred    3    4  no
3   bill    4    5 yes
4 george    6    6  no
5   fred    7    8 yes
6   bill    8    7  no

И я хочу суммировать val1 и val2 для каждого names, когда значение ch равно yes, чтобы получить новый фрейм данных вот так:

names val1 val2
1 george    2    3
2   fred    7    8
3   bill    4    5

Ответы [ 3 ]

2 голосов
/ 31 марта 2020

Кроме использования пакета tidyverse, вы можете использовать base r функцию aggregate, такую ​​как:

aggregate(tot[ch == "yes",2:3], by = list(tot[ch=="yes","names"]), sum)

  Group.1 val1 val2
1    bill    4    5
2    fred    7    8
3  george    2    3

Благодаря предложению @ akrun мы можем использовать aggregate и его аргумент subset, чтобы избежать двойного поднабора:

aggregate(. ~ names, tot, FUN = sum, subset= c(ch == 'yes'))
# or
aggregate(.~names, subset(tot, ch == "yes"), sum)

   names val1 val2 ch
1   bill    4    5  2
2   fred    7    8  2
3 george    2    3  2
2 голосов
/ 31 марта 2020

Это должно быть довольно быстро:

inds <- tot$ch=="yes"
rowsum(tot[inds, c("val1", "val2")], tot$names[inds])

       val1 val2
bill      4    5
fred      7    8
george    2    3
2 голосов
/ 31 марта 2020

Мы можем сделать группу по «именам» и сделать команду «==» в пределах summarise_at, чтобы получить sum из столбцов «val», которые соответствуют «ch» как «да»

library(dplyr)
tot %>%
    group_by(names) %>%
    summarise_at(vars(starts_with('val')), ~ sum(.[ch == 'yes']))

Или filter сначала «ch», но это может привести к удалению некоторых «имён», которые не имеют «да», поэтому complete в конце будет лучше

library(tidyr)
tot %>%
    filter(ch == 'yes') %>%
    group_by(names) %>%
    summarise_at(vars(starts_with('val')), sum) %>%
    complete(names = unique(tot$names))
...