在 R 中的自定义 ifelse() 中调用数据变量
Calling a data variable within a custom ifelse() in R
我正在尝试编写一个我想传递给 dplyr::mutate(across())
的专用 ifelse()
函数。该函数应将 across()
中指定的列中的 NA 值替换为类似名称的列中的值。
例如在下面的虚构数据中,我想用y_var1
替换缺失的x_var1
,用y_var2
替换缺失的x_var2
:
x <- tribble(~x_var1, ~x_var2, ~y_var1, ~y_var2,
5, 2, 0, 0,
NA, 10, 8, 0,
3, NA, 0, 5,
NA, NA, 7, 9)
我试过构建以下函数:
ifelse_spec <- function(var) {
new_var = paste("y_", str_remove(cur_column(), "x_"), sep = "")
# print(new_var) # just to check new_var is correct
ifelse(is.na(var), !!sym(new_var) , var) # how to call new_var?
}
x %>%
mutate(across(c(x_var1, x_var2),
~ ifelse_spec(.)))
但是好像不行。
但是,如果我 运行 这个单变量案例直接使用 ifelse
,我会得到预期的结果。
x %>%
mutate(across(c(x_var1),
~ifelse(is.na(.), !!sym("y_var1"), .)))
如何构建允许我调用数据变量的自定义 ifelse 语句?
编辑:我得到了以下适用于多变量情况的方法,但仍在使用 ifelse
而不是其他函数。
x %>%
mutate(across(c(x_var1, x_var2),
~ifelse(is.na(.), eval(sym(paste("y_", str_remove(cur_column(), "x_"), sep = ""))), . )))
coalesce()
就是针对这个问题设计的(从其他列中填充缺失值)。您可以通过使用它而不是 ifelse
:
来简化单变量案例
library(dplyr, warn.conflicts = FALSE)
library(stringr)
library(purrr)
x <- tribble(~x_var1, ~x_var2, ~y_var1, ~y_var2,
5, 2, 0, 0,
NA, 10, 8, 0,
3, NA, 0, 5,
NA, NA, 7, 9)
x %>%
mutate(x_var1 = coalesce(x_var1, y_var1))
#> # A tibble: 4 x 4
#> x_var1 x_var2 y_var1 y_var2
#> <dbl> <dbl> <dbl> <dbl>
#> 1 5 2 0 0
#> 2 8 10 8 0
#> 3 3 NA 0 5
#> 4 7 NA 7 9
然后您可以使用 select()
将其概括为合并具有相似名称的列:
x %>%
mutate(x_var1 = do.call(coalesce, select(., ends_with("var1"))))
#> # A tibble: 4 x 4
#> x_var1 x_var2 y_var1 y_var2
#> <dbl> <dbl> <dbl> <dbl>
#> 1 5 2 0 0
#> 2 8 10 8 0
#> 3 3 NA 0 5
#> 4 7 NA 7 9
最后,使用map_dfc
将这个函数应用到每一列,使用模式匹配提取它所属的“列组”:
x %>%
colnames() %>%
str_extract("var[0-9]") %>%
set_names(colnames(x)) %>%
map_dfc(~do.call(coalesce, select(x, ends_with(.))))
#> # A tibble: 4 x 4
#> x_var1 x_var2 y_var1 y_var2
#> <dbl> <dbl> <dbl> <dbl>
#> 1 5 2 5 2
#> 2 8 10 8 10
#> 3 3 5 3 5
#> 4 7 9 7 9
您需要调整 str_extract()
和 ends_with()
以适应您的真实数据中的列名称,但我认为这应该推广到任何合理的命名方案。如果将自定义函数应用于您的真实数据而不是 coalesce()
很重要,那么也应该可以重写 map_dfc()
来使用它。
我正在尝试编写一个我想传递给 dplyr::mutate(across())
的专用 ifelse()
函数。该函数应将 across()
中指定的列中的 NA 值替换为类似名称的列中的值。
例如在下面的虚构数据中,我想用y_var1
替换缺失的x_var1
,用y_var2
替换缺失的x_var2
:
x <- tribble(~x_var1, ~x_var2, ~y_var1, ~y_var2,
5, 2, 0, 0,
NA, 10, 8, 0,
3, NA, 0, 5,
NA, NA, 7, 9)
我试过构建以下函数:
ifelse_spec <- function(var) {
new_var = paste("y_", str_remove(cur_column(), "x_"), sep = "")
# print(new_var) # just to check new_var is correct
ifelse(is.na(var), !!sym(new_var) , var) # how to call new_var?
}
x %>%
mutate(across(c(x_var1, x_var2),
~ ifelse_spec(.)))
但是好像不行。
但是,如果我 运行 这个单变量案例直接使用 ifelse
,我会得到预期的结果。
x %>%
mutate(across(c(x_var1),
~ifelse(is.na(.), !!sym("y_var1"), .)))
如何构建允许我调用数据变量的自定义 ifelse 语句?
编辑:我得到了以下适用于多变量情况的方法,但仍在使用 ifelse
而不是其他函数。
x %>%
mutate(across(c(x_var1, x_var2),
~ifelse(is.na(.), eval(sym(paste("y_", str_remove(cur_column(), "x_"), sep = ""))), . )))
coalesce()
就是针对这个问题设计的(从其他列中填充缺失值)。您可以通过使用它而不是 ifelse
:
library(dplyr, warn.conflicts = FALSE)
library(stringr)
library(purrr)
x <- tribble(~x_var1, ~x_var2, ~y_var1, ~y_var2,
5, 2, 0, 0,
NA, 10, 8, 0,
3, NA, 0, 5,
NA, NA, 7, 9)
x %>%
mutate(x_var1 = coalesce(x_var1, y_var1))
#> # A tibble: 4 x 4
#> x_var1 x_var2 y_var1 y_var2
#> <dbl> <dbl> <dbl> <dbl>
#> 1 5 2 0 0
#> 2 8 10 8 0
#> 3 3 NA 0 5
#> 4 7 NA 7 9
然后您可以使用 select()
将其概括为合并具有相似名称的列:
x %>%
mutate(x_var1 = do.call(coalesce, select(., ends_with("var1"))))
#> # A tibble: 4 x 4
#> x_var1 x_var2 y_var1 y_var2
#> <dbl> <dbl> <dbl> <dbl>
#> 1 5 2 0 0
#> 2 8 10 8 0
#> 3 3 NA 0 5
#> 4 7 NA 7 9
最后,使用map_dfc
将这个函数应用到每一列,使用模式匹配提取它所属的“列组”:
x %>%
colnames() %>%
str_extract("var[0-9]") %>%
set_names(colnames(x)) %>%
map_dfc(~do.call(coalesce, select(x, ends_with(.))))
#> # A tibble: 4 x 4
#> x_var1 x_var2 y_var1 y_var2
#> <dbl> <dbl> <dbl> <dbl>
#> 1 5 2 5 2
#> 2 8 10 8 10
#> 3 3 5 3 5
#> 4 7 9 7 9
您需要调整 str_extract()
和 ends_with()
以适应您的真实数据中的列名称,但我认为这应该推广到任何合理的命名方案。如果将自定义函数应用于您的真实数据而不是 coalesce()
很重要,那么也应该可以重写 map_dfc()
来使用它。