每组'n'行数的组平均值 - R



我有一个包含三列的数据帧;entity, date, value.

首先,我必须根据每个实体的"DATE"的降序对"value"进行排序。

然后,要求根据用户定义的行数,每个实体获得两种类型的平均值。例如,如果用户输入3和6;这意味着">给我每个实体前3个值的平均值,然后接下来6个值的均值"。

对于给定的数据集,结果将是一个数据帧:

Entity    Avg3 Avg6
A     110   65 
B     220  130

我可以使用"aggregate"函数按实体获取"mean",但无法提取每个实体的特定行数据。此外,基于实体和"日期"的ordering数据帧似乎不起作用。

#order data based on date (tried adding entity here but it does not work)
df_new <- df[rev(order(as.Date(df$Date)))),]

这是dput:

structure(list(Wells = c("A", "A", "A", "A", "A", "A", "A", "A", 
"A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "B", "B", "B", 
"B", "B", "B"), Date = structure(c(1577836800, 1577923200, 1578009600, 
1578096000, 1578182400, 1578268800, 1578355200, 1578441600, 1578528000, 
1578614400, 1578700800, 1578787200, 1577836800, 1577923200, 1578009600, 
1578096000, 1578182400, 1578268800, 1578355200, 1578441600, 1578528000, 
1578614400, 1578700800, 1578787200), class = c("POSIXct", "POSIXt"
), tzone = "UTC"), Index = c(10, 20, 30, 40, 50, 60, 70, 80, 
90, 100, 110, 120, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 
220, 240)), row.names = c(NA, -24L), class = c("tbl_df", "tbl", 
"data.frame"))

这里有一个tidyverse选项。假设我们有动态输入('n1','n2'(,arrange按'Wells'排列数据,按'Date'的desc结束顺序,group_by为'Well',使用slice_head获得第一行(n1 + n2(,然后summarise通过分别基于'n1''和'n2'的取'Index'的headtail来创建'Avg'mean

library(dplyr)
library(stringr)
n1 <- 3
n2 <- 6
df %>%
arrange(Wells, desc(Date)) %>% 
group_by(Wells) %>%
slice_head(n = n1 + n2) %>%
summarise(!! str_c('Avg', n1) := mean(head(Index, n1)), 
!! str_c('Avg', n2)  := mean(tail(Index, n2)), .groups = 'drop')

-输出

# A tibble: 2 x 3
#  Wells  Avg3  Avg6
#  <chr> <dbl> <dbl>
#1 A       110    65
#2 B       220   130

或使用base R

df1 <- df[order(df$Wells, -as.numeric(df$Date)),]
out <- do.call(data.frame, aggregate(Index ~ Wells, 
subset(df1, ave(seq_along(Wells), 
Wells, FUN = seq_along) <= (n1 + n2)), FUN = function(x)
c(Avg3 = mean(head(x, n1)), Avg6 = mean(tail(x, n2)))))

您可以使用cut/findInterval将数据分组,取每组的mean,并使用pivot_wider获得宽格式的数据。

library(dplyr)
n <- c(3, 6)
df %>%
arrange(Wells, desc(Date)) %>%
group_by(Wells) %>%
group_by(grp = findInterval(row_number(), cumsum(n), left.open = TRUE), .add = TRUE) %>%
#For older dplyr version use add = TRUE
#group_by(grp = findInterval(row_number(), cumsum(n), left.open = TRUE), add = TRUE) %>%
summarise(Index = mean(Index)) %>%
slice(seq_along(n)) %>%
mutate(grp = paste0('avg', n)) %>%
tidyr::pivot_wider(names_from = grp, values_from = Index)
#  Wells  avg3  avg6
#  <chr> <dbl> <dbl>
#1 A       110    65
#2 B       220   130

最新更新