为了随着时间的推移操纵/汇总数据,我通常使用SQL ROW_NUMBER()OVER(PARTITION by ...)。我是R的新手,所以我试图重新创建我在SQL中创建的表。包sqldf不允许OVER子句。示例表:
ID Day Person Cost
1 1 A 50
2 1 B 25
3 2 A 30
4 3 B 75
5 4 A 35
6 4 B 100
7 6 B 65
8 7 A 20
我希望我的最终表能够包括第二个实例之后每天的前两个实例的平均值(两者都是第4天):
ID Day Person Cost Prev2
5 4 A 35 40
6 4 B 100 50
7 6 B 65 90
8 7 A 20 35
我一直试图使用aggregate
,但我不确定如何对该功能进行分区或限定。理想情况下,我不希望使用id
与日期相关的事实来形成我的答案(即原始表格可以按照随机日期顺序重新排列,代码仍然有效)。如果您需要更多详细信息,请告诉我,谢谢您的帮助!
答案 0 :(得分:0)
宽度为2时,您可能会滞后zoo::rollapplyr
。在dplyr中,
library(dplyr)
df %>% arrange(Day) %>% # sort
group_by(Person) %>% # set grouping
mutate(Prev2 = lag(zoo::rollapplyr(Cost, width = 2, FUN = mean, fill = NA)))
#> Source: local data frame [8 x 5]
#> Groups: Person [2]
#>
#> ID Day Person Cost Prev2
#> <int> <int> <fctr> <int> <dbl>
#> 1 1 1 A 50 NA
#> 2 2 1 B 25 NA
#> 3 3 2 A 30 NA
#> 4 4 3 B 75 NA
#> 5 5 4 A 35 40.0
#> 6 6 4 B 100 50.0
#> 7 7 6 B 65 87.5
#> 8 8 7 A 20 32.5
或全部在dplyr中,
df %>% arrange(Day) %>% group_by(Person) %>% mutate(Prev2 = (lag(Cost) + lag(Cost, 2)) / 2)
返回相同的东西。在基地,
df <- df[order(df$Day), ]
df$Prev2 <- ave(df$Cost, df$Person, FUN = function(x){
c(NA, zoo::rollapplyr(x, width = 2, FUN = mean, fill = NA)[-length(x)])
})
df
#> ID Day Person Cost Prev2
#> 1 1 1 A 50 NA
#> 2 2 1 B 25 NA
#> 3 3 2 A 30 NA
#> 4 4 3 B 75 NA
#> 5 5 4 A 35 40.0
#> 6 6 4 B 100 50.0
#> 7 7 6 B 65 87.5
#> 8 8 7 A 20 32.5
或没有动物园,
df$Prev2 <- ave(df$Cost, df$Person, FUN = function(x){
(c(NA, x[-length(x)]) + c(NA, NA, x[-(length(x) - 1):-length(x)])) / 2
})
做同样的事情。如果您要删除NA
行,请点击tidyr::drop_na(Prev2)
或na.omit
。