我有这个表:
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模式。
使用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
我们可以使用{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-03-30 with reprex v2.0.2
下面是一个使用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