Как вернуть среднее значение из последних n строк из другой группы (указано переменной)
У меня есть данные, как показано ниже:
data <- structure(list(seq = c(1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L,
4L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L,
6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L,
7L, 7L, 8L, 8L, 9L, 9L, 9L, 10L, 10L, 10L), new_seq = c(2, 2,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
2, 2, 2, 2, NA, NA, NA, NA, NA, 4, 4, 4, 4, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, 6, 6, 6, 6, 6, NA, NA, 8, 8, 8, NA, NA, NA), value = c(2L,
0L, 0L, 1L, 0L, 5L, 5L, 3L, 0L, 3L, 2L, 3L, 2L, 3L, 4L, 1L, 0L,
0L, 0L, 1L, 1L, 0L, 2L, 5L, 3L, 0L, 1L, 0L, 0L, 0L, 1L, 1L, 3L,
5L, 3L, 1L, 1L, 1L, 0L, 1L, 0L, 4L, 3L, 0L, 3L, 1L, 3L, 0L, 0L,
1L, 0L, 0L, 3L, 4L, 5L, 3L, 5L, 3L, 5L, 0L, 1L, 1L, 3L, 2L, 1L,
0L, 0L, 0L, 0L, 5L, 1L, 1L, 0L, 4L, 1L, 5L, 0L, 3L, 1L, 2L, 1L,
0L, 3L, 0L, 1L, 1L, 3L, 0L, 1L, 1L, 2L, 2L, 1L, 0L, 4L, 0L, 0L,
3L, 0L, 0L)), row.names = c(NA, -100L), class = c("tbl_df", "tbl",
"data.frame"))
колонка new_seq
относится к стоимости seq
, Для каждого значения в new_seq
который не NA
Я хотел бы рассчитать среднее значение за последний 2
ряды value
от соответствующих seq
, Так, например, строки 1:2
нового столбца должен иметь значение 0.5
(среднее число строк 49:50
), строки 51:54
также должен иметь значение 0.5
(среднее число строк 49:50
как хорошо) но строки 60:63
должен иметь значение 4
(среднее число строк 58:59
). Как я могу сделать это с tidyverse
?
2 ответа
Что-то вроде этого?
# calculate the mean value based on the last two rows of each seq
lookup <- data %>%
group_by(seq) %>%
mutate(rank = seq(n(), 1)) %>%
filter(rank <= 2) %>%
summarise(new_column = mean(value)) %>%
ungroup()
# match back to original dataset (only non-NA values of new_seq can be matched)
left_join(data, lookup, by = c("new_seq" = "seq"))
Результаты в:
# A tibble: 100 x 4
seq new_seq value new.column
<int> <dbl> <int> <dbl>
1 1 2 2 0.5
2 1 2 0 0.5
3 2 NA 0 NA
4 2 NA 1 NA
...
Ну это только половина tidyverse
и я уверен, что кто-то может сделать лучше, но вот попытка.
group_by
а также mutate
облегчить вычисление среднего значения для последних 2 строк группы, но я не мог понять, как получить связь между seq
а также new_seq
так что я сделал это в базе R.
dat2 <- dat %>%
group_by(seq) %>%
mutate(end_val = (nth(value, -1L) + nth(value, -2L))/2)
dat3$result <- apply(dat2, 1, function(x) {
dat2[dat2$seq == x['new_seq'], 'end_val'][[1]][1]
})
Вот результат. Я выделил соответствующие строки (так как в противном случае это было бы слишком долго, чтобы увидеть на экране сразу), но добавил исходные номера строк в качестве rowid
колонка:
dat3 %>% tibble::rowid_to_column() %>% .[c(1:3,50:55,59:64),]
# A tibble: 15 x 6
# Groups: seq [6]
rowid seq new_seq value end_val result
<int> <int> <dbl> <int> <dbl> <dbl>
1 1 1 2 2 1 0.5
2 2 1 2 0 1 0.5
3 3 2 NA 0 0.5 NA
4 50 2 NA 1 0.5 NA
5 51 3 2 0 3.5 0.5
6 52 3 2 0 3.5 0.5
7 53 3 2 3 3.5 0.5
8 54 3 2 4 3.5 0.5
9 55 4 NA 5 4 NA
10 59 4 NA 5 4 NA
11 60 5 4 0 2 4
12 61 5 4 1 2 4
13 62 5 4 1 2 4
14 63 5 4 3 2 4
15 64 6 NA 2 2 NA