如何解决如何在保留部分数据的同时对 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
- 动物园
解决方法
summarise
不是正确的函数,因为它每组返回一行。
此外,您的函数获取一个 data.frame 作为输入,这在 summarise
或 mutate
中不起作用。你要么想要这样的东西,它需要一个向量作为输入:
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.zoo
将 data
转换为宽格式动物园对象,其中每个日期都有一行,每个组都有一列。然后使用 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 举报,一经查实,本站将立刻删除。