微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在保留部分数据的同时对 dplyr 中的分组元素应用函数 使用的包:

如何解决如何在保留部分数据的同时对 dplyr 中的分组元素应用函数 使用的包:

问题总结

目前,我正在尝试应用一个以某种方式计算滞后数据的函数,这个函数必须应用于各种组,我似乎无法理解如何做到这一点dplyr。

预期结果

例如,数据如下所示:

   date group value
1 Jan 1     A     0
2 Feb 1     A     1
3 Mar 1     A     0
4 Jan 1     B     2
5 Feb 1     B     4
6 Mar 1     B     0

我们的想法是获得这样的输出,例如 2 个月的滚动平均值:

   date group value roll_mean
1 Feb 1     A     1       0.5
2 Mar 1     A     0       0.5
3 Feb 1     B     4         3
4 Mar 1     B     0         2

可重现的示例

为了示例,我准备了一个示例,可在 R 中使用,包含数据和函数

data <- data.frame(
  date = as.yearmon(
    as.Date(
        c("01/01/2020","01/02/2020","01/03/2020","01/01/2020","01/03/2020"),origin = "1970-01-01")
    ),group = c("A","A","B","B"),value = c(0,1,2,4,0)
)

computing_function <- function(data) {
  output_data <- data %>% 
    mutate(
      roll_mean = rollmean(data$value,k = 2,fill = NA,align="right")
    ) %>% 
    drop_na(roll_mean)
  return (output_data)
}

问题

我知道如何用循环来做这件事,但这会很耗时、不可靠并且维护起来很痛苦。例如,组的输出有效。但是我不能让它在 dplyr 中工作,即使使用 summarise()。我在逻辑中遗漏了一些东西,我无法确定它是什么。

computing_function(data %>% filter(group == "B"))
#    date group value roll_mean
# 1 Feb 1     B     4         3
# 2 Mar 1     B     0         2

data %>%
  group_by(group) %>% 
  summarise(computing_function(.))
# Error

是否有一种方法可以在 dplyr 明智的情况下做到这一点?

函数的逻辑应该留在里面,思想不是把它偏移到dplyr表达式。

使用的包:

  • dplyr
  • 动物园

解决方法

summarise 不是正确的函数,因为它每组返回一行。 此外,您的函数获取一个 data.frame 作为输入,这在 summarisemutate 中不起作用。你要么想要这样的东西,它需要一个向量作为输入:

computing_function1 <- function(values) {
    rollmean(values,k = 2,fill = NA,align="right")
}

data %>%
  group_by(group) %>% 
  mutate(roll_mean = computing_function1(value)) %>% 
  filter(!is.na(roll_mean))

或者,如果您真的想保持相同的结构,则必须拆分数据集,将函数应用于“组”并重新组装数据集:

data %>%
  split(.$group) %>% 
  map_dfr( computing_function ) 
,

可以在 Dplyr 文档中使用函数 modify_by 找到这种情况的答案。这是一个 purrr 风格的函数,可以在数据帧(以及扩展名)上使用函数。

此函数允许输入为 tibble,输出为分组的 tibble。 这是 Dplyr 代码和逻辑的答案:

data %>%
  group_by(group) %>% 
  group_modify(~computing_function(.x))

# # A tibble: 4 x 4
# # Groups:   group [2]
#   group date      value roll_mean
#   <chr> <yearmon> <dbl>     <dbl>
# 1 A     Feb 1         1       0.5
# 2 A     Mar 1         0       0.5
# 3 B     Feb 1         4       3  
# 4 B     Mar 1         0       2 

如果需要,您可以在 ungroup() 表达式之后使用 group_modify() 来输出未分组的小标题以传递给其他函数。

,

1) 使用 read.zoodata 转换为宽格式动物园对象,其中每个日期都有一行,每个组都有一列。然后使用 rollmeanr(与 rollmean 相同,但默认为 align="right")并创建一个由原始值作为实部和平均值作为虚部的复杂对象。使用 fortify.zoo 将其融化回长格式数据框并提取实部和虚部。这仅使用 magrittr 管道和动物园。

data %>%
  read.zoo(split = "group") %>%
  { fortify.zoo(. + rollmeanr(.,2) * 1i,melt = TRUE,names = names(data)) } %>%
  transform(value = Re(value),rollmean = Im(value))

给予:

      date group value rollmean
1 Feb 0001     A     1      0.5
2 Mar 0001     A     0      0.5
3 Feb 0001     B     4      3.0
4 Mar 0001     B     0      2.0

2) 上面的变体如下。它计算均值的宽动物园对象,然后将其转换回长格式数据框并将值列合并回。如果您真的不需要结果中的值列,则可以省略最后一行代码并且如果手段的动物园对象就足够了,倒数第二个可以省略。

data %>%
   read.zoo(split = "group") %>%
   rollmeanr(2) %>%
   fortify.zoo(melt = TRUE,names = c(names(data)[1:2],"rollmean")) %>%
   merge(data,.,by = 2:1)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。