Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
library(tidyverse)
first_year <- tibble(year = 2010, z = 1, x = 2, y = 3)
all_years <- first_year %>%
bind_rows(tibble(year = 2011:2015))
all_years
#> # A tibble: 6 x 4
#> year z x y
#> <dbl> <dbl> <dbl> <dbl>
#> 1 2010 1 2 3
#> 2 2011 NA NA NA
#> 3 2012 NA NA NA
#> 4 2013 NA NA NA
#> 5 2014 NA NA NA
#> 6 2015 NA NA NA
# Panel data relationships:
# - Z is caused by previous X
# - X is caused by current Z and previous Y
# - Y is caused by previous X
# z = (β * lag(x))
# x = (β * z) + (β * lag(y))
# y = (β * lag(x))
# Sadly doesn't work
all_years %>%
mutate(z = 0.5 * lag(x)) %>%
mutate(x = 0.5 * z + 0.5 * lag(y)) %>%
mutate(y = 0.25 * lag(x))
#> # A tibble: 6 x 4
#> year z x y
#> <dbl> <dbl> <dbl> <dbl>
#> 1 2010 NA NA NA
#> 2 2011 1 2 NA
#> 3 2012 NA NA 0.5
#> 4 2013 NA NA NA
#> 5 2014 NA NA NA
#> 6 2015 NA NA NA
# This works, but it is ew
for (i in 2:nrow(all_years)) {
all_years[i, "z"] <- 0.5 * all_years[i - 1, "x"]
all_years[i, "x"] <- (0.5 * all_years[i, "z"]) + (0.5 * all_years[i - 1, "y"])
all_years[i, "y"] <- 0.25 * all_years[i - 1, "x"]
}
all_years
#> # A tibble: 6 x 4
#> year z x y
#> <dbl> <dbl> <dbl> <dbl>
#> 1 2010 1 2 3
#> 2 2011 1 2 0.5
#> 3 2012 1 0.75 0.5
#> 4 2013 0.375 0.438 0.188
#> 5 2014 0.219 0.203 0.109
#> 6 2015 0.102 0.105 0.0508
@MilesMcBain
Copy link

MilesMcBain commented Jan 9, 2021

An accumulate based approach:

library(tidyverse)

first_year <- tibble(year = 2010, z = 1, x = 2, y = 3)

all_years <- first_year %>%
    bind_rows(tibble(year = 2011:2015))

all_years %>%
    mutate(
        params = accumulate(
            .init = tibble(
                x = first(all_years$x),
                y = first(all_years$y),
                z = first(all_years$z)
            ),
            .x = seq(length(z) - 1), # because we're supplying 1 row in init - tripped me up
            .f = function(inputs, x_ignored) {
                tibble(
                    z = 0.5 * inputs$x,
                    x = 0.5 * z + 0.5 * inputs$y,
                    y = 0.25 * inputs$x
                )
            }
        )
    ) %>%
    select(year, params) %>%
    unnest(params)
#> # A tibble: 6 x 4
#>    year     x      y     z
#>   <dbl> <dbl>  <dbl> <dbl>
#> 1  2010 2     3      1    
#> 2  2011 2     0.5    1    
#> 3  2012 0.75  0.5    1    
#> 4  2013 0.438 0.188  0.375
#> 5  2014 0.203 0.109  0.219
#> 6  2015 0.105 0.0508 0.102

Created on 2021-01-09 by the reprex package (v0.3.0)

Edit: The select step would not be required if we didn't have the x, y, z, columns. You'd just supply your init values of those params direct to accumulate.

@MilesMcBain
Copy link

MilesMcBain commented Jan 9, 2021

I cracked the summarise approach, making the unnest unnecessary:

library(tidyverse)

first_year <- tibble(year = 2010, z = 1, x = 2, y = 3)

all_years <- first_year %>%
    bind_rows(tibble(year = 2011:2015))

all_years %>%
    summarise(
        year = year,
        accumulate(
            .init = tibble(
                x = first(all_years$x),
                y = first(all_years$y),
                z = first(all_years$z)
            ),
            .x = seq(length(z) - 1), # because we're supplying 1 row in init - tripped me up
            .f = function(inputs, x_ignored) {
                tibble(
                    z = 0.5 * inputs$x,
                    x = 0.5 * z + 0.5 * inputs$y,
                    y = 0.25 * inputs$x
                )
            }
        ) %>%
        bind_rows()
    )
#> # A tibble: 6 x 4
#>    year     x      y     z
#>   <dbl> <dbl>  <dbl> <dbl>
#> 1  2010 2     3      1    
#> 2  2011 2     0.5    1    
#> 3  2012 0.75  0.5    1    
#> 4  2013 0.438 0.188  0.375
#> 5  2014 0.203 0.109  0.219
#> 6  2015 0.105 0.0508 0.102

Created on 2021-01-09 by the reprex package (v0.3.0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment