使用其他列中的值跨多个列进行条件变异 - 在 tidyverse 中寻找有效的解决方案

mar*_*aab 2 r dplyr purrr tidyverse

如果满足特定条件,我喜欢将一列的值替换为另一列的值。下面是一个玩具示例,我首先手动实现此目标,然后针对该问题起草一个有点笨拙的编程解决方案。(当然,我的真实数据包含更多变量,并且还需要更复杂的条件替换值)

\n
library(dplyr)\nlibrary(purrr)\n\n# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n## example data\nset.seed(123)\ndf <- tibble(\n  x = sample(0:1, 10, replace = T),\n  x_99 = sample(3:4, 10, replace = T),\n  y = sample(0:1, 10, replace = T),\n  y_99 = sample(3:4, 10, replace = T)\n)\n\ndf\n#> # A tibble: 10 \xc3\x97 4\n#>        x  x_99     y  y_99\n#>    <int> <int> <int> <int>\n#>  1     0     4     0     3\n#>  2     0     4     1     4\n#>  3     0     4     0     3\n#>  4     1     3     0     4\n#>  5     0     4     0     4\n#>  6     1     3     0     3\n#>  7     1     4     1     3\n#>  8     1     3     1     3\n#>  9     0     3     0     3\n#> 10     0     3     1     4\n\n# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n# manual mutate\n\ndf |>\n  transmute(\n    x = ifelse(x == 0, x_99, x),\n    y = ifelse(y == 0, y_99, y)\n  )\n#> # A tibble: 10 \xc3\x97 2\n#>        x     y\n#>    <int> <int>\n#>  1     4     3\n#>  2     4     1\n#>  3     4     3\n#>  4     1     4\n#>  5     4     4\n#>  6     1     3\n#>  7     1     1\n#>  8     1     1\n#>  9     3     3\n#> 10     3     1\n\n# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n# verbose programmatic solution\n\nhelper <- function(df, x, xnew) {\n  df[df[x] == 0, ][, x] <- df[df[x] == 0, ][, xnew]\n  return(tibble(df[x]))\n}\n\ncol.vec1 <- c("x", "y")\ncol.vec2 <- paste0(col.vec1, "_99")\n\nmap2(\n  col.vec1, col.vec2,\n  ~ helper(df, .x, .y)\n) |>\n  bind_cols()\n#> # A tibble: 10 \xc3\x97 2\n#>        x     y\n#>    <int> <int>\n#>  1     4     3\n#>  2     4     1\n#>  3     4     3\n#>  4     1     4\n#>  5     4     4\n#>  6     1     3\n#>  7     1     1\n#>  8     1     1\n#>  9     3     3\n#> 10     3     1\n
Run Code Online (Sandbox Code Playgroud)\n

由reprex 包于 2022 年 9 月 11 日创建(v2.0.1)

\n

我实际上主要使用 tidyverse 工具进行数据清理。但在这种情况下,这绝对超出了我的能力范围。我仍然找到了一个解决方案,但我很确定有一个更优雅且更简洁的解决方案。我非常感谢您的建议。

\n

r2e*_*ans 5

我想看across一下cur_column()会对你有用。您真正需要更改的唯一一件事是c(x, y)采用某种清晰整洁的方式来识别列。

df %>%
  mutate(
    across(c(x, y), ~ if_else(. == 0L, get(paste0(cur_column(), "_99")), .))
  )
# # A tibble: 10 x 4
#        x  x_99     y  y_99
#    <int> <int> <int> <int>
#  1     4     4     3     3
#  2     4     4     1     4
#  3     4     4     3     3
#  4     1     3     4     4
#  5     4     4     4     4
#  6     1     3     3     3
#  7     1     4     1     3
#  8     1     3     1     3
#  9     3     3     3     3
# 10     3     3     1     4
Run Code Online (Sandbox Code Playgroud)