【发布时间】:2021-06-25 22:14:18
【问题描述】:
我有一个数据框,其中包含跨多年和跨地区的人口数据。有点像这样:
df <- tibble(YEAR = c("2015", "2015", "2016", "2016", "2017", "2017", "2018", "2018"),
LOCATION = c("a", "b", "a", "b", "a", "b", "a", "b"),
POPULATION = c(2, 3, 4, 3, 6, 6, 7, 9))
df
# A tibble: 8 x 3
YEAR LOCATION POPULATION
<chr> <chr> <dbl>
1 2015 a 2
2 2015 b 3
3 2016 a 4
4 2016 b 3
5 2017 a 6
6 2017 b 6
7 2018 a 7
8 2018 b 9
现在,我想计算每个位置相对于第一年的人口(因此 2015 年的人口 = 1)。
实际上,我想将每年的人口除以第一年(或另一个给定年份)的人口。
如果数据只是按年份分组,这将相当简单。我只是打电话给特定的第一年(本报告中的 2015 年)。我会 mutate 并像这样创建我的新变量 RELATIVE_POPULATION = POPULATION/(POPULATION[YEAR == "2015"]) :
df_year <- df %>%
group_by(YEAR) %>%
summarise(POPULATION = sum(POPULATION)) %>%
mutate(RELATIVE_POPULATION = POPULATION/(POPULATION[YEAR == "2015"]))
df_year
# A tibble: 4 x 3
YEAR POPULATION RELATIVE_POPULATION
<chr> <dbl> <dbl>
1 2015 5 1
2 2016 7 1.4
3 2017 12 2.4
4 2018 16 3.2
但我想为每个位置执行此操作,以提供如下所示的输出(因此所有位置 a 的人口除以位置 a 的 2015 年人口,所有位置 b 的人口除以位置 b 的 2015 年人口)
YEAR LOCATION POPULATION RELATIVE_POPULATION
<chr> <chr> <dbl> <dbl>
1 2015 a 2 1
2 2015 b 3 1
3 2016 a 4 2
4 2016 b 3 1
5 2017 a 6 3
6 2017 b 6 2
7 2018 a 7 3.5
8 2018 b 9 3
我想我可以使用case_when 对每年进行子集计算,但我不知道如何根据其他两个维度为操作指定一个值。我试过了
df_relative <- df %>%
mutate(
RELATIVE_POPULATION = case_when(
LOCATION == "a" ~ POPULATION/(POPULATION[YEAR == "2015", LOCATION == "a"]),
LOCATION == "b" ~ POPULATION/(POPULATION[YEAR == "2015", LOCATION == "b"])
))
但这会返回错误 Error in POPULATION[YEAR == "2015", LOCATION == "a"] : incorrect number of dimensions
那么这里是否可以指定两个维度,如果可以,如何指定?
一位乐于助人的人(推特上的@MikeMahoney218)巧妙地建议我创建第二个 tibble,其中包含每个位置的 2015 年值,然后我将两者连接在一起,如下所示:
original_pop <- df %>%
group_by(LOCATION) %>%
filter(YEAR == 2015) %>%
select(LOCATION, INITIAL_POP = POPULATION)
df %>%
left_join(original_pop) %>%
mutate(RELATIVE_POP = POPULATION / INITIAL_POP)
df
# A tibble: 8 x 5
YEAR LOCATION POPULATION INITIAL_POP RELATIVE_POP
<chr> <chr> <dbl> <dbl> <dbl>
1 2015 a 2 2 1
2 2015 b 3 3 1
3 2016 a 4 2 2
4 2016 b 3 3 1
5 2017 a 6 2 3
6 2017 b 6 3 2
7 2018 a 7 2 3.5
8 2018 b 9 3 3
这可行(耶),但有没有办法在不创建第二个数据框的情况下做到这一点?我可以看到随着代码的增加,这可能会变得复杂。
【问题讨论】: