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

标签 r dplyr tidyverse purrr

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

library(dplyr)
library(purrr)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

## example data
set.seed(123)
df <- tibble(
  x = sample(0:1, 10, replace = T),
  x_99 = sample(3:4, 10, replace = T),
  y = sample(0:1, 10, replace = T),
  y_99 = sample(3:4, 10, replace = T)
)

df
#> # A tibble: 10 × 4
#>        x  x_99     y  y_99
#>    <int> <int> <int> <int>
#>  1     0     4     0     3
#>  2     0     4     1     4
#>  3     0     4     0     3
#>  4     1     3     0     4
#>  5     0     4     0     4
#>  6     1     3     0     3
#>  7     1     4     1     3
#>  8     1     3     1     3
#>  9     0     3     0     3
#> 10     0     3     1     4

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# manual mutate

df |>
  transmute(
    x = ifelse(x == 0, x_99, x),
    y = ifelse(y == 0, y_99, y)
  )
#> # A tibble: 10 × 2
#>        x     y
#>    <int> <int>
#>  1     4     3
#>  2     4     1
#>  3     4     3
#>  4     1     4
#>  5     4     4
#>  6     1     3
#>  7     1     1
#>  8     1     1
#>  9     3     3
#> 10     3     1

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# verbose programmatic solution

helper <- function(df, x, xnew) {
  df[df[x] == 0, ][, x] <- df[df[x] == 0, ][, xnew]
  return(tibble(df[x]))
}

col.vec1 <- c("x", "y")
col.vec2 <- paste0(col.vec1, "_99")

map2(
  col.vec1, col.vec2,
  ~ helper(df, .x, .y)
) |>
  bind_cols()
#> # A tibble: 10 × 2
#>        x     y
#>    <int> <int>
#>  1     4     3
#>  2     4     1
#>  3     4     3
#>  4     1     4
#>  5     4     4
#>  6     1     3
#>  7     1     1
#>  8     1     1
#>  9     3     3
#> 10     3     1

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

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

最佳答案

我认为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

关于r - 使用其他列中的值跨多个列进行条件变异 - 在 tidyverse 中寻找有效的解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73681041/

相关文章:

反转某些数据框列的顺序

performance - 将使用 S3 的包转换为 S4 类,性能会下降吗?

r - 在gt表的不同列中选择不同类型的脚注标记

r - 控制 R 中枢轴的细节级别 (tidyverse)

r - 使用 dplyr 减去几个不同列的最有效方法是什么

使用 tidyr/data.table 与 data.frames 复制 `expand.grid()` 行为

python - 使用 rpy2 将 R ListVector 转换为 Python 列表

r - 在 R 中的多列中选择具有 complete.case 的行

r - 在 dplyr 中跨选定数量的列添加行

R 代码无法根据相同的值合并列中的数据(不重复)