dplyr across中源列和替换列的动态if else

kyxcudwk  于 2023-04-03  发布在  其他
关注(0)|答案(3)|浏览(128)

我有这张table:

df <- data.frame(value_2022 = c(1, NA, 3), 
               volume_2022 = c(NA, 2, 3), 
               value_2022_replacement = c(1.5, 2.5, 3.5),
               volume_2022_replacement = c(0.5, 1.5, 2.5))
df
#>   value_2022 volume_2022 value_2022_replacement volume_2022_replacement
#> 1          1          NA                    1.5                     0.5
#> 2         NA           2                    2.5                     1.5
#> 3          3           3                    3.5                     2.5

我想通过across以编程方式将每个2022列的NA值替换为其对应的_replacement列,我的代码如下所示:

df %>% 
  mutate(across(matches("^v.+2022$"), \(x) ifelse(is.na(x), 
                                                  {replacewithcorresponding "_replacement" variable}, 
                                                  x)))

我想知道是否有任何方法可以将{replacewithcorresponding "_replacement" variable}替换为允许我对匹配{same name}_2022_replacement模式的无限数量的列执行此操作的东西。

cpjpxq1n

cpjpxq1n1#

我们可以使用{dplyover}软件包来实现这一点。免责声明:我是维护者,软件包不在CRAN上。
简单的方法是across2,它要求列按照相应的顺序排列:

library(dplyr)
library(dplyover)

df %>% 
  mutate(across2(ends_with("_2022"), # below .x
                 ends_with("_2022_replacement"), # below .y
                 ~ ifelse(is.na(.x), .y, .x),
                 .names = "{xcol}"
                 )
         )
#>   value_2022 volume_2022 value_2022_replacement volume_2022_replacement
#> 1        1.0         0.5                    1.5                     0.5
#> 2        2.5         2.0                    2.5                     1.5
#> 3        3.0         3.0                    3.5                     2.5

dplyover::over()是一个更安全但更冗长的选项。这里我们首先使用cut_names()提取变量的词干,然后使用.("").fns中构造和计算函数中的字符串变量名:

df %>% 
  mutate(over(cut_names("_replacement"), # extracts c("value_2022","volume_2022")
                 ~ ifelse(is.na(.("{.x}")),
                          .("{.x}_replacement"),
                          .("{.x}")),
                 .names = "{x}"
                 )
         )
#>   value_2022 volume_2022 value_2022_replacement volume_2022_replacement
#> 1        1.0         0.5                    1.5                     0.5
#> 2        2.5         2.0                    2.5                     1.5
#> 3        3.0         3.0                    3.5                     2.5

数据来自OP

df <- data.frame(value_2022 = c(1, NA, 3), 
                 volume_2022 = c(NA, 2, 3), 
                 value_2022_replacement = c(1.5, 2.5, 3.5),
                 volume_2022_replacement = c(0.5, 1.5, 2.5))

创建于2023年3月30日,使用reprex v2.0.2

rn0zuynd

rn0zuynd2#

下面是一个使用cur_data()cur_column()函数的dplyr解决方案。我的mutate语句的间距通常不是我格式化它的方式,但我认为这使它更容易阅读以用于演示目的。

df <- data.frame(value_2022 = c(1, NA, 3), 
                 volume_2022 = c(NA, 2, 3), 
                 value_2022_replacement = c(1.5, 2.5, 3.5),
                 volume_2022_replacement = c(0.5, 1.5, 2.5))

df %>% 
  mutate(
    across(
      matches("^v.+2022$"),
      \(x) ifelse(is.na(x), cur_data()[[paste(cur_column(), 'replacement', sep = '_')]], x)
    )
  )

  value_2022 volume_2022 value_2022_replacement volume_2022_replacement
1        1.0         0.5                    1.5                     0.5
2        2.5         2.0                    2.5                     1.5
3        3.0         3.0                    3.5                     2.5
n6lpvg4x

n6lpvg4x3#

使用coalesce

library(dplyr) # version >= 1.1.0
library(stringr)
df %>%
  mutate((across(matches("\\d{4}$"), ~ coalesce(.x,
    pick(str_c(cur_column(), '_replacement'))[[1]]))))
  • 输出
value_2022 volume_2022 value_2022_replacement volume_2022_replacement
1        1.0         0.5                    1.5                     0.5
2        2.5         2.0                    2.5                     1.5
3        3.0         3.0                    3.5                     2.5

相关问题