【问题标题】:Conduct a mutate based on lagged rows not yet calculated根据尚未计算的滞后行进行变异
【发布时间】:2023-02-22 16:38:10
【问题描述】:

在 R 中,我想执行一个 mutate 来填充多列(x 和 y)的 NA 值。

data <- data.table(year = c(2010, 2011, 2012, 2013, 2014), x=c(1, 3, NA, NA, NA), y=c(2, 4, NA, NA, NA))
year x y
2010 1 2
2011 3 4
2012 NA NA
2013 NA NA
2014 NA NA

然而,这些计算取决于另一列的滞后值。对于年份大于 2011 的值,x = x(上一行)+ y(上一行)和 y = x(前 2 行)+ y(前 2 行)

那么预期的输出将是

year x y
2010 1 2
2011 3 4
2012 7 3
2013 10 7
2014 17 10

这是我运行的代码:

data %>% 
 mutate(
   x = case_when(
     year > 2011 ~ lag(x, 1) + lag(y, 1),
     TRUE ~ x),
   y = case_when(
     year > 2011 ~ lag(x, 2) + lag(y, 2),
     TRUE ~ y))

但是,这不起作用,因为无论它们的计算顺序如何,每个变量的变异都取决于尚未计算的 NA 值(因此无法计算 2013 年 x 的值,因为 y 的变异计算2012 年的值尚未执行,但情况相反,y 需要 2012 年的 x 值)。我的数据集比这大得多,并且有一个更复杂的计算涉及第三个变量,该变量也以类似的方式相互依赖。

有没有办法同时运行这些变异或任何其他解决方案来解决这个问题?

【问题讨论】:

    标签: r dplyr tidyverse mutate


    【解决方案1】:

    您的方法的问题是 lag() 是向量化的,但每一行都取决于前一行的结果,因此我们不能在这里使用向量化方法,而是需要逐行计算。

    一种方法是使用递归函数,将 data.frame 作为输入,并在多次迭代后返回填充的 data.frame

    library(dplyr)
    
    dat <- tibble(year = c(2010, 2011, 2012, 2013, 2014), x=c(1, 3, NA, NA, NA), y=c(2, 4, NA, NA, NA))
    
    calc_row <- function(dat, run = nrow(dat)) {
    
      omit_na_dat <- na.omit(dat)
      
      if (nrow(omit_na_dat) == run) {
        return(dat)
      }
      
      row_idx <- nrow(omit_na_dat)
      
      new_x = omit_na_dat[row_idx, ][["x"]] + omit_na_dat[row_idx, ][["y"]]
      new_y = omit_na_dat[row_idx - 1, ][["x"]] + omit_na_dat[row_idx - 1, ][["y"]]
      new_year = omit_na_dat[row_idx, ][["year"]] + 1
      
      dat <- rows_update(dat, tibble(year = new_year,
                                     x = new_x,
                                     y = new_y),
                         by = "year"
                         )
      calc_row(dat, run = run)
    }
    
    calc_row(dat)
    #> # A tibble: 5 x 3
    #>    year     x     y
    #>   <dbl> <dbl> <dbl>
    #> 1  2010     1     2
    #> 2  2011     3     4
    #> 3  2012     7     3
    #> 4  2013    10     7
    #> 5  2014    17    10
    

    reprex package (v2.0.1) 创建于 2023-02-22

    【讨论】:

      【解决方案2】:

      x 的计算就像一个斐波那契数列. y 只是滞后的 x

      fib <- function(a1, a2, len){
        seq <- c(a1, a2)
        for(i in 3:len) {
          seq[i] <- seq[i-1] + seq[i-2]
        }
        return(seq)
      }
      
      fib(1, 2, 5)
      # [1] 1 2 3 5 8
      
      df %>%
        mutate(x = ifelse(is.na(x), fib(y[2], x[2], n()), x),
               y = ifelse(is.na(y), lag(x), y))
      
      # # A tibble: 5 × 3
      #    year     x     y
      #   <dbl> <dbl> <dbl>
      # 1  2010     1     2
      # 2  2011     3     4
      # 3  2012     7     3
      # 4  2013    10     7
      # 5  2014    17    10
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-04
        • 2019-09-05
        • 2017-12-02
        • 2020-02-19
        • 1970-01-01
        • 2021-11-14
        • 1970-01-01
        相关资源
        最近更新 更多