I'm hoping there is a simple solution to this, but I'm having trouble working it out.
I have population sizes for some cities, like:
df <- data.frame(city = c("A","B","C","D","E","F","G"), start_pop = c(100,200,300,400,500,600,700))
start_pop
is the population in January 2019. Assuming that the population increases by 0.022% each month, I would like to calculate monthly population estimates for each city through 2019, 2020 and 2021, saved as Jan19
, Feb19
etc., which relies on the input of the previous calculation.
I can do it with mutate
, something like:
increase <- 1.00022
df <- data.frame(city = c("A","B","C","D","E","F","G"), start_pop = c(100,200,300,400,500,600,700)) %>%
mutate(Feb19 = start_pop * increase) %>%
mutate(Mar19 = Feb19 * increase) %>%
mutate(Apr19 = Mar19 * increase)
...
But is there a more succinct way of getting the same result, perhaps through a loop or an apply function?
Will this do?
increase <- 0.00022
df %>% mutate(mon = as.Date("2019-01-01")) %>%
group_by(city) %>%
complete(mon = seq.Date(from = as.Date("2019-01-01"), to = as.Date("2021-12-01"), by = "month")) %>%
mutate(start_pop = if_else(is.na(start_pop), increase+1, start_pop),
start_pop = cumprod(start_pop)) %>%
pivot_wider(names_from = mon, values_from = start_pop)
# A tibble: 7 x 37
# Groups: city [7]
city `2019-01-01` `2019-02-01` `2019-03-01` `2019-04-01` `2019-05-01` `2019-06-01`
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 A 100 100. 100. 100. 100. 100.
2 B 200 200. 200. 200. 200. 200.
3 C 300 300. 300. 300. 300. 300.
4 D 400 400. 400. 400. 400. 400.
5 E 500 500. 500. 500. 500. 501.
6 F 600 600. 600. 600. 601. 601.
7 G 700 700. 700. 700. 701. 701.
# ... with 30 more variables: `2019-07-01` <dbl>, `2019-08-01` <dbl>, `2019-09-01` <dbl>,
# `2019-10-01` <dbl>, `2019-11-01` <dbl>, `2019-12-01` <dbl>, `2020-01-01` <dbl>,
# `2020-02-01` <dbl>, `2020-03-01` <dbl>, `2020-04-01` <dbl>, `2020-05-01` <dbl>,
# `2020-06-01` <dbl>, `2020-07-01` <dbl>, `2020-08-01` <dbl>, `2020-09-01` <dbl>,
# `2020-10-01` <dbl>, `2020-11-01` <dbl>, `2020-12-01` <dbl>, `2021-01-01` <dbl>,
# `2021-02-01` <dbl>, `2021-03-01` <dbl>, `2021-04-01` <dbl>, `2021-05-01` <dbl>,
# `2021-06-01` <dbl>, `2021-07-01` <dbl>, `2021-08-01` <dbl>, `2021-09-01` <dbl>,
# `2021-10-01` <dbl>, `2021-11-01` <dbl>, `2021-12-01` <dbl>
Additional solution. Using the approach @AnilGoyal
library(tidyverse)
df <- data.frame(city = c("A","B","C","D","E","F","G"), start_pop = c(100,200,300,400,500,600,700))
n <- 36
increase <- 1.00022
seq_increase <- cumprod(rep(increase, n))
seq_date <- seq.Date(from = as.Date("2019-02-01"), length.out = n, by = "month")
bind_cols(df,
map2_dfc(
.x = seq_increase,
.y = seq_date,
.f = ~transmute(df, !!paste0(.y) := start_pop * .x)))
#> city start_pop 2019-02-01 2019-03-01 2019-04-01 2019-05-01 2019-06-01
#> 1 A 100 100.022 100.044 100.0660 100.0880 100.1100
#> 2 B 200 200.044 200.088 200.1320 200.1761 200.2201
#> 3 C 300 300.066 300.132 300.1980 300.2641 300.3301
#> 4 D 400 400.088 400.176 400.2641 400.3521 400.4402
#> 5 E 500 500.110 500.220 500.3301 500.4401 500.5502
#> 6 F 600 600.132 600.264 600.3961 600.5282 600.6603
#> 7 G 700 700.154 700.308 700.4621 700.6162 700.7703
#> 2019-07-01 2019-08-01 2019-09-01 2019-10-01 2019-11-01 2019-12-01 2020-01-01
#> 1 100.1321 100.1541 100.1761 100.1982 100.2202 100.2423 100.2643
#> 2 200.2641 200.3082 200.3523 200.3963 200.4404 200.4845 200.5286
#> 3 300.3962 300.4623 300.5284 300.5945 300.6607 300.7268 300.7930
#> 4 400.5283 400.6164 400.7045 400.7927 400.8809 400.9691 401.0573
#> 5 500.6604 500.7705 500.8807 500.9909 501.1011 501.2113 501.3216
#> 6 600.7924 600.9246 601.0568 601.1890 601.3213 601.4536 601.5859
#> 7 700.9245 701.0787 701.2329 701.3872 701.5415 701.6959 701.8502
#> 2020-02-01 2020-03-01 2020-04-01 2020-05-01 2020-06-01 2020-07-01 2020-08-01
#> 1 100.2864 100.3084 100.3305 100.3526 100.3747 100.3967 100.4188
#> 2 200.5728 200.6169 200.6610 200.7052 200.7493 200.7935 200.8377
#> 3 300.8591 300.9253 300.9915 301.0577 301.1240 301.1902 301.2565
#> 4 401.1455 401.2338 401.3220 401.4103 401.4986 401.5870 401.6753
#> 5 501.4319 501.5422 501.6525 501.7629 501.8733 501.9837 502.0941
#> 6 601.7183 601.8506 601.9831 602.1155 602.2480 602.3804 602.5130
#> 7 702.0046 702.1591 702.3136 702.4681 702.6226 702.7772 702.9318
#> 2020-09-01 2020-10-01 2020-11-01 2020-12-01 2021-01-01 2021-02-01 2021-03-01
#> 1 100.4409 100.4630 100.4851 100.5072 100.5293 100.5515 100.5736
#> 2 200.8818 200.9260 200.9702 201.0145 201.0587 201.1029 201.1472
#> 3 301.3228 301.3891 301.4554 301.5217 301.5880 301.6544 301.7207
#> 4 401.7637 401.8521 401.9405 402.0289 402.1174 402.2058 402.2943
#> 5 502.2046 502.3151 502.4256 502.5361 502.6467 502.7573 502.8679
#> 6 602.6455 602.7781 602.9107 603.0434 603.1760 603.3087 603.4415
#> 7 703.0864 703.2411 703.3958 703.5506 703.7054 703.8602 704.0150
#> 2021-04-01 2021-05-01 2021-06-01 2021-07-01 2021-08-01 2021-09-01 2021-10-01
#> 1 100.5957 100.6178 100.6400 100.6621 100.6843 100.7064 100.7286
#> 2 201.1914 201.2357 201.2799 201.3242 201.3685 201.4128 201.4571
#> 3 301.7871 301.8535 301.9199 301.9863 302.0528 302.1192 302.1857
#> 4 402.3828 402.4713 402.5599 402.6484 402.7370 402.8256 402.9142
#> 5 502.9785 503.0892 503.1998 503.3105 503.4213 503.5320 503.6428
#> 6 603.5742 603.7070 603.8398 603.9727 604.1055 604.2384 604.3714
#> 7 704.1699 704.3248 704.4798 704.6348 704.7898 704.9448 705.0999
#> 2021-11-01 2021-12-01 2022-01-01
#> 1 100.7507 100.7729 100.7951
#> 2 201.5014 201.5458 201.5901
#> 3 302.2522 302.3187 302.3852
#> 4 403.0029 403.0915 403.1802
#> 5 503.7536 503.8644 503.9753
#> 6 604.5043 604.6373 604.7703
#> 7 705.2551 705.4102 705.5654
Created on 2021-01-31 by the reprex package (v1.0.0)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.