#r #dataframe #dplyr
Вопрос:
У меня есть фрейм данных, подобный этому:
df = data.frame(
x = 1:100,
y = rep(1:10, times = 10, each = 10)
) %>%
group_by(y)
И я хотел бы вычислить сумму x
от 3-й до 6-й строки каждой группы y
.
Я думаю, что это должно быть легко, но я просто не могу понять это в данный момент.
В псевдокоде я представляю себе что-то вроде этого:
df %>%
mutate(
sum(x, ifelse(between(row_number(), 3,6)))
)
Но это, конечно, не работает. Я хотел бы решить эту проблему с помощью какой dplyr
-либо функции, но и в базе R я не могу придумать быстрого решения.
Для первой группы сумма будет равна 3 4 5 6
….
Комментарии:
1.
df %>% summarise(x = sum(x[3:6]))
2. Классно! Но почему я могу использовать обычную индексацию здесь?
3. Что вы подразумеваете под нормальной индексацией?
4. Я имел в виду индексацию base-r с квадратными скобками
Ответ №1:
Одним из вариантов может быть:
df %>%
group_by(y) %>%
mutate(z = sum(x[row_number() %in% 3:6]))
x y z
<int> <int> <int>
1 1 1 18
2 2 1 18
3 3 1 18
4 4 1 18
5 5 1 18
6 6 1 18
7 7 1 18
8 8 1 18
9 9 1 18
10 10 1 18
Комментарии:
1. о, как это мило! Большое спасибо!
2. Я часто действительно путаюсь в том, какие методы подмножества разрешены, а какие нет (например, объединение base-R и dplyr, как вы сделали здесь). Так что большое вам спасибо за это:)
Ответ №2:
Вы также можете сделать это с filter()
помощью и summarise()
и получить групповое резюме:
df %>%
group_by(y) %>%
mutate(rn = 1:n()) %>%
filter(rn %in% 3:6) %>%
summarise(x_sum = sum(x))
# A tibble: 10 x 2
y x_sum
<int> <int>
1 1 18
2 2 58
3 3 98
4 4 138
5 5 178
6 6 218
7 7 258
8 8 298
9 9 338
10 10 378
Комментарии:
1. Это, безусловно, один из вариантов. Немного представьте, если я хочу сделать это для двух разных комбинаций строк. Например, строка 3-6 и строка 1-4. Фильтрация допускает только одну комбинацию, не так ли?
2. Это правда! Кроме того, использование подхода
slice()
ТарДжи несколько более элегантно!
Ответ №3:
Обновление: Если вы хотите суммировать несколько последовательностей из x, то вы можете sum
по индексу:
df %>%
group_by(y) %>%
mutate(sum_row3to6 = sum(x[3:6]),
sum_row1to4 = sum(x[1:4])
)
Выход:
x y sum_row3to6 sum_row1to4
<int> <int> <int> <int>
1 1 1 18 10
2 2 1 18 10
3 3 1 18 10
4 4 1 18 10
5 5 1 18 10
6 6 1 18 10
7 7 1 18 10
8 8 1 18 10
9 9 1 18 10
10 10 1 18 10
Первый ответ:
Мы могли бы использовать slice
summarise
library(dplyr)
df %>%
group_by(y) %>%
slice(3:6) %>%
summarise(sum = sum(x))
Выход:
y sum
<int> <int>
1 1 18
2 2 58
3 3 98
4 4 138
5 5 178
6 6 218
7 7 258
8 8 298
9 9 338
10 10 378
Ответ №4:
данные.таблица
library(data.table)
df = data.frame(
x = 1:100,
y = rep(1:10, times = 10, each = 10)
)
setDT(df)[rowid(y) %in% 3:6, list(sum_x = sum(x)), by = y][]
#> y sum_x
#> 1: 1 18
#> 2: 2 58
#> 3: 3 98
#> 4: 4 138
#> 5: 5 178
#> 6: 6 218
#> 7: 7 258
#> 8: 8 298
#> 9: 9 338
#> 10: 10 378
Создано 2021-05-21 пакетом reprex (v2.0.0)