Я ищу способ аккуратно суммировать уникальные пары моих двух переменных, предпочтительно в data.table
.
Вот мои данные:
> x_base
State SA2 Population_SA2
1: A x 304
2: A x 304
3: A y 79
4: A y 79
5: A y 79
6: B z 961
7: B z 961
8: B z 961
9: B z 961
10: B w 90
11: B w 90
12: B u 550
13: C v 113
14: C v 113
15: C t 425
16: C t 425
17: C t 425
Что я хочу сделать, так это вычислить сумму Population_SA2
на State
. Однако у меня есть несколько записей для каждой пары State
и SA2
, например, у меня есть две пары State == A & SA2 == x
, но когда я суммирую по Population_SA2
, было бы неправильно считать 304 дважды, также было бы неправильно считать 79 три раза. Население для State
A должно быть 383 (304 + 79).
Вот мое текущее решение:
1) Найдите уникальные пары State
и SA2
:
> x_unique <- unique(x_base)
> x_unique
State SA2 Population_SA2
1: A x 304
2: A y 79
3: B z 961
4: B w 90
5: B u 550
6: C v 113
7: C t 425
2) Сумма Population_SA2
на State
:
> x_unique <- x_unique[,.(sum_by_state = sum(Population_SA2)), by = State]
> x_unique
State sum_by_state
1: A 383
2: B 1601
3: C 538
3) Соедините обратно с начальным data.table
:
> x_final <- merge(x_base, x_unique[,.(State,sum_by_state)], by = "State")
> x_final
State SA2 Population_SA2 sum_by_state
1: A x 304 383
2: A x 304 383
3: A y 79 383
4: A y 79 383
5: A y 79 383
6: B z 961 1601
7: B z 961 1601
8: B z 961 1601
9: B z 961 1601
10: B w 90 1601
11: B w 90 1601
12: B u 550 1601
13: C v 113 538
14: C v 113 538
15: C t 425 538
16: C t 425 538
17: C t 425 538
Мне бы очень хотелось узнать, можно ли это сделать более чистым и лаконичным способом, когда мне не нужно создавать какие-либо промежуточные объекты.
Очень признателен!
Не уверен, что нужно, но вот dput()
structure(list(State = c("A", "A", "A", "A", "A", "B", "B", "B",
"B", "B", "B", "B", "C", "C", "C", "C", "C"), SA2 = c("x", "x",
"y", "y", "y", "z", "z", "z", "z", "w", "w", "u", "v", "v", "t",
"t", "t"), Population_SA2 = c(304L, 304L, 79L, 79L, 79L, 961L,
961L, 961L, 961L, 90L, 90L, 550L, 113L, 113L, 425L, 425L, 425L
)), row.names = c(NA, -17L), class = c("data.table", "data.frame"
), .internal.selfref = <pointer: 0x0000000000121ef0>)
data.table
решение
x_base[, sum_by_state := sum(Population_SA2[!duplicated(SA2)]), by = State]
x_base
# State SA2 Population_SA2 sum_by_state
# 1: A x 304 383
# 2: A x 304 383
# 3: A y 79 383
# 4: A y 79 383
# 5: A y 79 383
# 6: B z 961 1601
# 7: B z 961 1601
# 8: B z 961 1601
# 9: B z 961 1601
# 10: B w 90 1601
# 11: B w 90 1601
# 12: B u 550 1601
# 13: C v 113 538
# 14: C v 113 538
# 15: C t 425 538
# 16: C t 425 538
# 17: C t 425 538
dplyr
-решение будет:
library(dplyr)
x_base %>%
group_by(State) %>%
mutate(sum_by_state = sum(Population_SA2[!duplicated(SA2)]))
# A tibble: 17 x 4
# Groups: State [3]
# State SA2 Population_SA2 sum_by_state
# <chr> <chr> <int> <int>
# 1 A x 304 383
# 2 A x 304 383
# 3 A y 79 383
# 4 A y 79 383
# 5 A y 79 383
# 6 B z 961 1601
# 7 B z 961 1601
# 8 B z 961 1601
# 9 B z 961 1601
# 10 B w 90 1601
# 11 B w 90 1601
# 12 B u 550 1601
# 13 C v 113 538
# 14 C v 113 538
# 15 C t 425 538
# 16 C t 425 538
# 17 C t 425 538
Если вас интересует более чистый способ обработки таких данных, я бы предложил использовать несколько нормализованных/опрятных таблиц (а не одну со сложной структурой, приводящей к повторяющимся/избыточным значениям). Статья Хэдли — хорошее руководство: jstatsoft.org/article/view/v059i10