У меня есть фрейм данных с тремя столбцами; entity, date, value.
Сначала я должен упорядочить «значение» на основе «Убывающего порядка« ДАТА »» для каждого объекта.
Затем требуется получить 2 типа средних значений для каждого объекта на основе заданного пользователем количества строк. Например, если пользователь вводит 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)))),]
вот вывод:
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
данные по «колодцам» и в desc
конечном порядке «Дата», group_by
«колодец», используйте slice_head
, чтобы получить первые (n1 + n2
) строки, затем summarise
создать столбцы «Среднее» mean
, взяв head
и tail
«Индекса» на основе «n1» и «n2» соответственно.
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)))))
это именно то, что я хотел. Спасибо. Также спасибо за предоставление ответа, отличного от dpylr. Мне пришлось использовать «slice» вместо «slice_head». Моя версия dplyr не смогла найти эту функцию.
@CodeMaster Я думаю, что это из новой версии. Вы можете изменить его на slice(seq_len(n1 + 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
Я не понимаю, что вы пытаетесь сделать, но похоже, что, расчесывая функцию длины и функцию строк, вы можете туда попасть.