按唯一变量对求和

时间:2019-05-31 06:58:09

标签: r data.table

我正在寻找一种方法,最好是在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的总和。但是,每个StateSA2对都有多个条目,例如,我有两对State == A & SA2 == x,但是当我对Population_SA2求和时,两次计算304是不正确的,同样,三次计算79是不正确的。 State A的总数应为383(304 + 79)。

这是我当前的解决方案:

1)找到唯一的StateSA2对:

> 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_SA2State相加:

> 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>)

1 个答案:

答案 0 :(得分:4)

一个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