问题总结
目前,我正试图应用一个以某种方式计算滞后数据的函数,这个函数必须应用于各种组集,我似乎无法用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/02/2020", "01/03/2020"),
origin = "1970-01-01")
),
group = c("A", "A", "A", "B", "B", "B"),
value = c(0, 1, 0, 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
不是正确的函数,因为它每组返回一行。此外,你的函数得到一个数据帧作为输入,这将不会在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风格的函数,允许在数据帧上使用函数(通过扩展可以使用标题)。
这个函数允许输入是一个点状图,输出是一个分组点状图。下面是用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
您可以在group_modify()
表达式之后使用ungroup()
来输出一个非分组的标题,以便在需要时传递给其他函数。
1)使用read.zoo
将data
转换为一个宽窗体动物园对象,其中每个日期有一行,每个组有一列。然后使用rollmeanr
(与rollmean
相同,默认为align="right"
),创建一个以原始值为实部,均值为虚部的复杂对象。使用增强。把它融回一个长形式的数据框架并提取出实部和虚部。这里只使用磁力管道和动物园。
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)上述内容的一个变体如下。它计算均值的宽范围对象,然后将其转换回长格式数据帧,并将值列合并回去。如果不需要结果中的value列,可以省略最后一行代码;如果使用一个zoo object of means就足够了,可以省略最后第二行代码。
data %>%
read.zoo(split = "group") %>%
rollmeanr(2) %>%
fortify.zoo(melt = TRUE, names = c(names(data)[1:2], "rollmean")) %>%
merge(data, ., by = 2:1)