使用 dplyr mutate 函数根据当前行有条件地创建新变量

Posted

技术标签:

【中文标题】使用 dplyr mutate 函数根据当前行有条件地创建新变量【英文标题】:Using dplyr mutate function to create new variable conditionally based on current row 【发布时间】:2020-09-21 08:11:55 【问题描述】:

我正在为一个大型数据集创建条件平均值,该数据集涉及几年内一周内出现的流感病例数。数据组织如下:

我想做的是创建一个新列,将前几年同一周的平均病例数制成表格。例如,对于 Week.Number 为 1 且 Flu.Year 为 2017 的行,我希望新行给出 Week.Number==1 & Flu.Year

   mutate(average = case_when(
    Flu.Year==2016 ~ mean(chcc$count[chcc$Flu.Year==2016]),
    Flu.Year==2017 ~ mean(chcc$count[chcc$Flu.Year==2017]),
    Flu.Year==2018 ~ mean(chcc$count[chcc$Flu.Year==2018]),
    Flu.Year==2019 ~ mean(chcc$count[chcc$Flu.Year==2019]),
  ),

但是,由于有 4 年的数据 * 52 周,因此需要大量迭代才能阐明条件。有没有办法在 dplyr 中优雅地编码?我一直遇到的问题是我想根据 Week.Number 和 Flu.Year 的当前值在其他行中根据 Week.Number 和 Flu.Year 值调用计数列中的值,我不知道如何做到这一点。如果我可以提供更多信息/详细信息,请告诉我。

谢谢, 史蒂文

dat <- tibble( Flu.Year = rep(2016:2019,each = 52), Week.Number = rep(1:52,4), count = sample(1000, size=52*4, replace=TRUE) ) 

【问题讨论】:

请不要发布代码/数据/错误的图像:它不能被复制或搜索 (SEO),它会破坏屏幕阅读器,并且它可能不适合某些移动设备。参考:meta.***.com/a/285557(和xkcd.com/2116)。请直接包含代码、控制台输出或数据(例如,dput(head(x))data.frame(...))。 这里有一些很好的参考资料,可以提供一个独立的、可重复的问题:***.com/q/5963269、minimal reproducible example 和 ***.com/tags/r/info。 【参考方案1】:

这是错误的格式,在某些情况下,当您在 dplyr 动词中使用 $-indexing 时会出错。 我认为获得average 字段的更好方法是group_by(Flu.Year) 并直接计算它。

library(dplyr)
set.seed(42)
dat <- tibble(
  Flu.Year = sample(2016:2020, size=100, replace=TRUE),
  count = sample(1000, size=100, replace=TRUE)
)

dat %>%
  group_by(Flu.Year) %>%
  mutate(average = mean(count)) %>%
  # just to show a quick summary
  slice(1:3) %>%
  ungroup()
# # A tibble: 15 x 3
#    Flu.Year count average
#       <int> <int>   <dbl>
#  1     2016   734    578.
#  2     2016   356    578.
#  3     2016   411    578.
#  4     2017   217    436.
#  5     2017   453    436.
#  6     2017   920    436.
#  7     2018   963    558 
#  8     2018   609    558 
#  9     2018   536    558 
# 10     2019   943    543.
# 11     2019   740    543.
# 12     2019   536    543.
# 13     2020   627    494.
# 14     2020   218    494.
# 15     2020   389    494.

另一种方法是生成一个汇总表(每年仅一行)并将其重新连接到原始数据中。

dat %>%
  group_by(Flu.Year) %>%
  summarize(average = mean(count))
# # A tibble: 5 x 2
#   Flu.Year average
#      <int>   <dbl>
# 1     2016    578.
# 2     2017    436.
# 3     2018    558 
# 4     2019    543.
# 5     2020    494.

dat %>%
  group_by(Flu.Year) %>%
  summarize(average = mean(count)) %>%
  full_join(dat, by = "Flu.Year")
# # A tibble: 100 x 3
#    Flu.Year average count
#       <int>   <dbl> <int>
#  1     2016    578.   734
#  2     2016    578.   356
#  3     2016    578.   411
#  4     2016    578.   720
#  5     2016    578.   851
#  6     2016    578.   822
#  7     2016    578.   465
#  8     2016    578.   679
#  9     2016    578.    30
# 10     2016    578.   180
# # ... with 90 more rows

chat之后的结果:

tibble( Flu.Year = rep(2016:2018,each = 3), Week.Number = rep(1:3,3), count = 1:9 )  %>%
  arrange(Flu.Year, Week.Number) %>%
  group_by(Week.Number) %>%
  mutate(year_week.average = lag(cumsum(count) / seq_along(count)))
# # A tibble: 9 x 4
# # Groups:   Week.Number [3]
#   Flu.Year Week.Number count year_week.average
#      <int>       <int> <int>             <dbl>
# 1     2016           1     1              NA  
# 2     2016           2     2              NA  
# 3     2016           3     3              NA  
# 4     2017           1     4               1  
# 5     2017           2     5               2  
# 6     2017           3     6               3  
# 7     2018           1     7               2.5
# 8     2018           2     8               3.5
# 9     2018           3     9               4.5

【讨论】:

感谢您的建议 - 但是,我仍然不确定如何根据前几年的同一周计算每周的平均值(例如,2016 年第 1 周的平均交易量, 2017 年等) 你以前用过group_by吗?这可能就像更改此代码以使用 group_by(Flu.Year, Week) 来获得一年中每周的平均值一样简单。如果没有,在您的问题中包含可用的样本数据会很有用。 我考虑过使用 group_by 函数,因为汇总表可以让我获得多年来平均每周的数据,但这仍然是我所寻找的。我需要前几年每周的平均值。因此,每一列都有不同的值。仍然需要一些条件,其中 Flu.Year 好的。更重要的是...请提供示例数据,并在给定示例数据的情况下添加预期输出 设置方法如下: dat 【参考方案2】:

我们可以从base R使用aggregate

aggregate(count ~ Flu.Year, data, FUN = mean)

【讨论】:

以上是关于使用 dplyr mutate 函数根据当前行有条件地创建新变量的主要内容,如果未能解决你的问题,请参考以下文章

R语言dplyr包使用mutate函数生成新的数据列(不改变原数据列)实战

R语言dplyr包mutate_at函数通过名称修改指定数据列的内容(使用统一的函数)实战

在 dplyr mutate_at 调用中使用多列的函数

在 R 中:将列名作为参数传递,并在 dplyr::mutate() 和 lazyeval::interp() 的函数中使用它

R语言dplyr包mutate_all函数一次性处理所有的数据列的内容(使用统一的函数)实战

dplyr包实用总结之mutate系列