r - 如何在 R 中使用 dplyr 有条件地总结不同的数据列?
问题描述
我需要在 R 中聚合数据。我有 8 列,其中 3 列是分类的,其中 5 列是数字的,需要根据来自 2 个分类变量的条件组合有条件地求和。我的数据如下所示:
df <- structure(list(Color = c("Red", "Blue", "Blue", "Red", "Yellow"
), Weekend = c(1L, 0L, 1L, 0L, 1L), LeapYear = c(1L, 1L, 0L,
0L, 0L), Length = c(15L, 20L, 10L, 15L, 15L), Height = c(50L,
70L, 35L, 28L, 80L), Weight = c(120L, 130L, 120L, 105L, 140L),
Cost = c(25L, 50L, 55L, 65L, 80L), Purchases = c(5L, 10L,
5L, 10L, 15L)), class = "data.frame", row.names = c(NA, -5L
))
> df
Color Weekend LeapYear Length Height Weight Cost Purchases
1 Red 1 1 15 50 120 25 5
2 Blue 0 1 20 70 130 50 10
3 Blue 1 0 10 35 120 55 5
4 Red 0 0 15 28 105 65 10
5 Yellow 1 0 15 80 140 80 15
我想用条件总和聚合这个表,
例如,总长度和高度,但仅适用于闰年,总和高度和成本,但仅适用于闰年和周末。
我希望这些按颜色分组的条件总和如下所示:
颜色 | 长度 | 高度 | 重量 | 成本 | 购买 | Length_LeapYear | 身高_闰年 | 身高_闰年_周末 | 成本_闰年_周末 | 采购_周末 |
---|---|---|---|---|---|---|---|---|---|---|
红色的 | 30 | 78 | 225 | 90 | 15 | 15 | 50 | 50 | 25 | 5 |
蓝色的 | 30 | 105 | 250 | 105 | 15 | 20 | 70 | 0 | 0 | 5 |
黄色 | 15 | 80 | 140 | 80 | 15 | 0 | 0 | 0 | 0 | 15 |
我在 dplyr 工作,并有以下工作使用 summarise_at() 在相同条件下对多个字段求和:
df %>%
group_by(Color, Weekend, LeapYear) %>%
summarise_at(c(Length_LeapYear == "Length", Height_LeapYear == "Height"), ~sum(.[LeapYear==1]))
但是当我尝试为剩余的条件求和变量添加条件时,这会删除我之前的总结。这是我想象代码如何工作的想法。
df %>%
group_by(Color, Weekend, LeapYear) %>%
summarise_at(c("Length", "Height", "Weight", "Cost", "Purchases"), sum) %>%
summarise_at(c(Length_LeapYear == "Length", Height_LeapYear == "Height"), ~sum(.[LeapYear==1])) %>%
summarise_at(c(Height_LeapYear_Weekend == "Height", Cost_LeapYear_Weekend == "Cost"), ~sum(.[LeapYear==1 & Weekend ==1])) %>%
summarise(Purchases_Weekend = sum(Purchases)) %>%
group_by(Color)
最终,我觉得必须有一种方法可以将这些不同条件的总和中的每一个都放入一个 summarise_at() 调用中。我也不确定对列(周末和闰年)进行有条件求和然后从最终表格中省略这些列的最佳实践。因此,我们也将不胜感激。
作为记录,我确实知道我可以通过对 summarise() 的一次长时间调用来执行这些操作,其中我单独调整每个派生列。然而,在实践中,我的数据集比这要广泛得多,尝试通过对类似条件进行分组来压缩数据操作更有意义。
解决方案
更新再三考虑,我知道您需要立即执行此操作。我认为下面的语法将完成通过四种类型的聚合一次汇总整个数据集(在示例 cols 3 到 col7 中)的工作
df %>% group_by(Color) %>%
summarise(across(3:7, ~sum(.))) %>%
left_join(df %>% group_by(Color) %>% summarise(across(3:7, ~sum(.*LeapYear), .names= "{.col}_LeapYear"))) %>%
left_join(df %>% group_by(Color) %>% summarise(across(3:7, ~sum(.*Weekend), .names= "{.col}_Weekend"))) %>%
left_join(df %>% group_by(Color) %>% summarise(across(3:7, ~sum(.*LeapYear*Weekend), .names= "{.col}_LeapYear_Weekend")))
# A tibble: 3 x 21
Color Length Height Weight Cost Purchases Length_LeapYear Height_LeapYear Weight_LeapYear Cost_LeapYear
<chr> <int> <int> <int> <int> <int> <int> <int> <int> <int>
1 Blue 30 105 250 105 15 20 70 130 50
2 Red 30 78 225 90 15 15 50 120 25
3 Yell~ 15 80 140 80 15 0 0 0 0
# ... with 11 more variables: Purchases_LeapYear <int>, Length_Weekend <int>, Height_Weekend <int>,
# Weight_Weekend <int>, Cost_Weekend <int>, Purchases_Weekend <int>, Length_LeapYear_Weekend <int>,
# Height_LeapYear_Weekend <int>, Weight_LeapYear_Weekend <int>, Cost_LeapYear_Weekend <int>,
# Purchases_LeapYear_Weekend <int>
您也可以像这样在列表中传递完整的功能(这将进一步缩短您的代码)
df %>% group_by(Color) %>%
summarise(across(3:7, list(sum= ~sum(.),
leapyear = ~sum(.*LeapYear),
weekend = ~sum(.*Weekend),
leapyear_weekend = ~sum(.*Weekend*LeapYear))))
# A tibble: 3 x 21
Color Length_sum Length_leapyear Length_weekend Length_leapyear~ Height_sum Height_leapyear Height_weekend
<chr> <int> <int> <int> <int> <int> <int> <int>
1 Blue 30 20 10 0 105 70 35
2 Red 30 15 15 15 78 50 50
3 Yell~ 15 0 15 0 80 0 80
# ... with 13 more variables: Height_leapyear_weekend <int>, Weight_sum <int>, Weight_leapyear <int>,
# Weight_weekend <int>, Weight_leapyear_weekend <int>, Cost_sum <int>, Cost_leapyear <int>,
# Cost_weekend <int>, Cost_leapyear_weekend <int>, Purchases_sum <int>, Purchases_leapyear <int>,
# Purchases_weekend <int>, Purchases_leapyear_weekend <int>
dput(df)
我已包含在您的问题中的示例。
旧答案这样做
df %>%
group_by(Color) %>%
summarise(Length_s = sum(Length),
Height_s = sum(Height),
Weight_s = sum(Weight),
Cost_s = sum(Cost),
Purchases_s = sum(Purchases),
Length_Leap_year = sum(Length * LeapYear),
Height_Leap_year = sum(Height * LeapYear),
Height_Leap_year_Weekend = sum(Height * LeapYear * Weekend),
Purchases_Weekend = sum(Purchases * Weekend))
# A tibble: 3 x 10
Color Length_s Height_s Weight_s Cost_s Purchases_s Length_Leap_year Height_Leap_year Height_Leap_year_Weekend Purchases_Weeke~
<chr> <int> <int> <int> <int> <int> <int> <int> <int> <int>
1 Blue 30 105 250 105 15 20 70 0 5
2 Red 30 78 225 90 15 15 50 50 5
3 Yellow 15 80 140 80 15 0 0 0 15
推荐阅读
- php - Laravel 5.7:尚未设置外观根
- firebase - Flutter 依赖于 firebase_analytics 0.0.4,需要 SDK 版本 >=1.8.0 <2.0.0,版本解析失败
- c - 除非我调用 printf() 函数,否则 C 代码会卡住
- python - 在 linux 中从 selenium 启动 chromium 的路径是什么?
- amazon-web-services - 将数据传递给 step 函数 catch
- swift - 如何在 Swift 中将垂直对齐应用于 UIBarButtonItem
- tensorflow - Q 关于“超网络”tape.gradient 来自 F. Chollet 为研究人员编写的 tf.keras:速成课程
- python - pandas 系列 groupby 与一组
- python - 使用 Spacy 自定义空间标记化
- java - MySQL Java Prepared Statement 如果不存在则插入