首页 > 解决方案 > 如何在 dplyr 中进行跨行计算?

问题描述

有一个包含嵌套信息的数据框。假设每所学校的学生人数,A班学生人数和B班学生人数。所以学生 = n.pupilsA + n.pupilsB + other_pupils

a <- data.frame(
  city = c(rep('New York',3), rep('Washington',3)),
  n = c(5, 2, 1, 5, 2, 1),
  name = c(
    'pupils',
    'classA',
    'classB',
    'pupils',
    'classA',
    'classB'
  )
)

输出:

        city n   name
1   New York 5 pupils
2   New York 2 classA
3   New York 1 classB
4 Washington 5 pupils
5 Washington 2 classA
6 Washington 1 classB

是否有一种聪明的方法(大概使用 dplyr)进行组操作,该操作将添加到每个组中的“其他”,这将是“学生”和“学生 - A 级”+“学生 - B 级”之间的差异。所以结果会是这样的:

        city   type npupils
1   New York classA       2
2   New York classB       1
3   New York pupils       5
4   New York  other       2
5 Washington classA       2
6 Washington classB       1
7 Washington pupils       5
8 Washington  other       2

我认为可能可行的唯一方法是传播它,计算列之间的差异,然后使用以下方法将其收集回来tidyr

a %>%
  spread(name, n) %>%
  mutate(other = pupils - classA - classB) %>%
  gather(type, npupils, c('classA', 'classB', 'pupils', 'other')) %>%
  arrange(city)

哪个有效,但我想知道是否有更好的方法?

标签: rdplyrtidyr

解决方案


我们可以创建一个汇总数据框并将其绑定到原始数​​据框。对于每一个city,我们通过组中的剩余值n减去nwhere的值来计算,并创建一列作为“其他”,然后使用 .将这些行添加到原始数据框中。name == 'pupils'namebind_rows

library(dplyr)

bind_rows(a, a %>%
              group_by(city)%>%
              summarise(n = n[name == 'pupils'] - sum(n[name != 'pupils']), 
                       name = "Other")) %>%
arrange(city)


#        city n   name
#1   New York 5 pupils
#2   New York 2 classA
#3   New York 1 classB
#4   New York 2  Other
#5 Washington 5 pupils
#6 Washington 2 classA
#7 Washington 1 classB
#8 Washington 2  Other

注意 - 在这里我假设您只有一个“学生”条目,city否则我们可以which.max用来获取第一个条目。


推荐阅读