【问题标题】:Mutate value based on first row above that satisfies a condition根据上面满足条件的第一行改变值
【发布时间】:2019-07-12 05:53:41
【问题描述】:

我有数据,其简化版本如下所示:

 df_current <- data.frame(
  start = c('yes', rep('no', 5), 'yes', rep('no', 3)),
  season = c('banana', rep('to update', 5), 'apple', rep('to update', 3)),
  stringsAsFactors = F
)

假设“开始”变量表示新季节的开始时间,我可以将它与日期变量(不包括在内)结合使用来表示苹果和香蕉季节的开始时间。完成此操作后,我想更新“季节”列中的其余行。当前具有“要更新”值的所有行都应更新为具有最近开始季节的水果类型的值(行按日期排列)。换句话说,我希望数据看起来像这样:

 df_desired <- data.frame(
  start = c('yes', rep('no', 5), 'yes', rep('no', 3)),
  season = c(rep('banana', 6), rep('apple', 4)),
  stringsAsFactors = F
)

我曾认为类似以下的方法会起作用:

  updated <- df_current %>% 
  rowwise() %>% 
  mutate(season = case_when(
    season != 'to update' ~ season,
    season == 'to update' ~ lag(season)
  ))

但是,这会在所有“更新”值处生成 NA。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    一个简单的方法是replace "to update"NA 然后使用fill

    library(dplyr)
    library(tidyr)
    
    df_current %>%
      mutate(season = replace(season, season == "to update", NA)) %>%
      fill(season)
    
    #   start season
    #1    yes banana
    #2     no banana
    #3     no banana
    #4     no banana
    #5     no banana
    #6     no banana
    #7    yes  apple
    #8     no  apple
    #9     no  apple
    #10    no  apple
    

    使用相同的逻辑,您还可以使用zoo::na.locf 用最新的非缺失值填充缺失值。

    【讨论】:

      【解决方案2】:

      生成一堆NAs 的原因是season 在每个case_when 评估中只包含一个值,因此lag(season) 总是产生NA。这是另一个使用 rle 的基本 R 解决方案:

      x <- rle(df_current$season)
      x
      #> Run Length Encoding
      #>   lengths: int [1:4] 1 5 1 3
      #>   values : chr [1:4] "banana" "to update" "apple" "to update"
      
      x$values[x$values == "to update"] <- x$values[which(x$values == "to update") - 1]
      x
      #> Run Length Encoding
      #>   lengths: int [1:4] 1 5 1 3
      #>   values : chr [1:4] "banana" "banana" "apple" "apple"
      
      df_current$season <- inverse.rle(x)
      
      df_current
      #>    start season
      #> 1    yes banana
      #> 2     no banana
      #> 3     no banana
      #> 4     no banana
      #> 5     no banana
      #> 6     no banana
      #> 7    yes  apple
      #> 8     no  apple
      #> 9     no  apple
      #> 10    no  apple
      

      【讨论】:

      • 感谢您的解释。您提到每个 case_when() 评估中只有一个值 - 我认为这是因为调用 rowwise() 而不是 case_when() 本身?
      • @userLL: 是的,没有rowwise 你仍然会遇到问题,因为lag(season)season 列中的每次更新后不会以迭代方式重新计算
      【解决方案3】:

      我们可以使用na_if

      library(dplyr)
      library(tidyr)
      df_current %>%
          mutate(season = na_if(season, "to update")) %>%
          fill(season)
      #   start season
      #1    yes banana
      #2     no banana
      #3     no banana
      #4     no banana
      #5     no banana
      #6     no banana
      #7    yes  apple
      #8     no  apple
      #9     no  apple
      #10    no  apple
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-30
        • 2020-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-02
        • 1970-01-01
        相关资源
        最近更新 更多