【问题标题】:How to summarize two different rows with different values to a single row with that sum using dplyr?如何使用 dplyr 将具有不同值的两个不同行汇总为具有该总和的单行?
【发布时间】:2021-07-29 00:24:51
【问题描述】:

我有以下数据框,但当然规模更大:

country year strain num_cases
mex 1996 sp_m014 412
mex 1996 sp_f014 214
mex 1998 sp_m014 150
mex 1998 sp_f014 200
usa 1996 sp_m014 200
usa 1996 sp_f014 180
usa 1997 sp_m014 190
usa 1997 sp_f014 150

我想得到以下结果,即分别为 mex 和 usa 的 sp_m014(男性)和 sp_f014(女性)的总和:

country year strain num_cases
mex 1996 sp 626
mex 1998 sp 350
usa 1996 sp 380
usa 1997 sp 340

在我的真实数据框中,我有更多的年龄范围,这里我只显示男性和女性的 014。但我想以这种方式对每个年龄段和性别进行总结。

谢谢!

【问题讨论】:

  • 是的,抱歉。这就是为什么我将它还原为我认为的原始版本。
  • 真的很抱歉,我的错!我感到困惑并开始改变一些事情,我想我已经恢复到原来的样子了。

标签: r dplyr tidyverse


【解决方案1】:

更新: 要使用年龄范围,您可以parse_number

df1 %>% 
  mutate(age_range=parse_number(strain)) %>% 
  group_by(country, year, age_range) %>% 
  summarise(num_cases=sum(num_cases))

输出:

  country  year age_range num_cases
  <chr>   <int>     <dbl>     <int>
1 mex      1996        14       626
2 mex      1998        14       350
3 usa      1996        14       380
4 usa      1997        14       340

第一个答案: 感谢 akrun 提供的数据:

library(tidyverse)
df1 %>% 
  group_by(country, year, strain) %>% 
  mutate(strain=str_extract(strain, "^.{2}")) %>% 
  summarise(num_cases=sum(num_cases))

输出:

  country  year strain num_cases
  <chr>   <int> <chr>      <int>
1 mex      1996 sp           626
2 mex      1998 sp           350
3 usa      1996 sp           380
4 usa      1997 sp           340

【讨论】:

  • 您好,谢谢!如果不是 sp 怎么办?我想对年龄范围进行排序。正如我提到的,sp_014 根据性别和年龄在我的数据中。我们生成一个名为“age_range”的列,而不是列“strain”,然后我们看到相同的 num_cases,但针对的是 age_range。 014 只是一个例子,我的真实数据中有 014、1524、2534,直到 65。
  • 请看我的编辑。在我的第一个答案中我没有意识到这一点。
【解决方案2】:

这是tidyr::extract 的一种方法:

library(tidyr);library(dplyr)
df1 %>%
  extract(strain, into = c("strain","sex","age"), "(\\w+)_([mf])(.*)") %>%
  group_by(country,year,strain) %>% 
  summarise(across(num_cases,sum))
# A tibble: 4 x 4
# Groups:   country, year [4]
  country  year strain num_cases
  <chr>   <int> <chr>      <int>
1 mex      1996 sp           626
2 mex      1998 sp           350
3 usa      1996 sp           380
4 usa      1997 sp           340

现在您已经完全解析了菌株,您可以轻松地按性别或年龄进行分组。感谢@akrun 提供数据。

【讨论】:

  • 我认为您不希望正则表达式中出现问号。否则age 列为空
【解决方案3】:

按“国家”、“年份”summarise 分组以将“应变”更新为“sp”并获取“num_cases”的sum

library(dplyr)
df1 %>%
   group_by(country, year) %>%
   summarise(strain = 'sp', num_cases = sum(num_cases), .groups = 'drop')

-输出

# A tibble: 4 x 4
#  country  year strain num_cases
#* <chr>   <int> <chr>      <int>
#1 mex      1996 sp           626
#2 mex      1998 sp           350
#3 usa      1996 sp           380
#4 usa      1997 sp           340

数据

df1 <- structure(list(country = c("mex", "mex", "mex", "mex", "usa", 
"usa", "usa", "usa"), year = c(1996L, 1996L, 1998L, 1998L, 1996L, 
1996L, 1997L, 1997L), strain = c("sp_m014", "sp_f014", "sp_m014", 
"sp_f014", "sp_m014", "sp_f014", "sp_m014", "sp_f014"), num_cases = c(412L, 
214L, 150L, 200L, 200L, 180L, 190L, 150L)), 
class = "data.frame", row.names = c(NA, 
-8L))

【讨论】:

  • 谢谢!这解决了我的问题。顺便说一句,我在“总结”文档中找不到 .group("drop") 参数。你能指出我可以看到它是如何工作的地方吗?
  • @Jvet 在?summarise中有提到。您使用的是当前版本的dplyr。另外,你能检查一下here
猜你喜欢
  • 2021-08-05
  • 2021-03-12
  • 2021-09-05
  • 1970-01-01
  • 2014-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多