【问题标题】:Replace values in multiple columns with NA based on value in a different column根据不同列中的值将多列中的值替换为 NA
【发布时间】:2020-06-15 11:54:37
【问题描述】:

我有一个小玩意...

# A tibble: 20 x 6
      id   X_1   Y_1 number   X_2   Y_2
   <int> <dbl> <dbl>  <dbl> <dbl> <dbl>
 1     1     1     3      1     1     3
 2     1     1     3      0     1     3
 3     2     2     4      1     2     4
 4     2     2     4      0     2     4
 5     3     1     3      1     1     3
 6     3     1     3      0     1     3

如果数字列中的值等于 1,我想让所有值都等于 NA,但仅限于以“_1”结尾的列(因此 X_1 和 Y_1)。

我也想在 _2 列中做相反的事情(即数字等于 0 的行变为 NA)。

它最终应该看起来像这样......

# A tibble: 20 x 6
      id   X_1   Y_1 number   X_2   Y_2
   <int> <dbl> <dbl>  <dbl> <dbl> <dbl>
 1     1    NA    NA      1     1     3
 2     1     1     3      0     1     3
 3     2    NA    NA      1     2     4
 4     2     2     4      0     2     4
 5     3    NA    NA      1     1     3
 6     3     1     3      0     1     3

我尝试了以下...

df %>% mutate_at(vars(contains("_1")), .funs = list(~if_else(number == 1, NA_real_, .)))

但这没有用。

我主要使用 tidyverse 工作,所以最好使用 tidyverse 解决方案。

【问题讨论】:

  • 如果数字列等于 1 你的意思是行而不是列,对吧?您对Y_1 的预期输出也关闭了。值为 3 但被替换为 NA?

标签: r dplyr


【解决方案1】:

这里的解决方案实际评估变量 number 是 0 还是 1(之前的解决方案评估了以“_1”或“_2”结尾的变量是 1 还是 0)。

library(dplyr)
df %>% 
  mutate(across((ends_with("_1")), ~ na_if(number, 1)),
        (across((ends_with("_2")), ~ na_if(number, 0))))

# A tibble: 6 x 6
     id   X_1   Y_1 number   X_2   Y_2
  <int> <int> <int>  <int> <int> <int>
1     1    NA    NA      1     1     1
2     1     0     0      0    NA    NA
3     2    NA    NA      1     1     1
4     2     0     0      0    NA    NA
5     3    NA    NA      1     1     1
6     3     0     0      0    NA    NA

编辑(保留原始值)

df %>% 
  mutate(across((ends_with("_1")), ~if_else(number == 1, NA_integer_, .))) %>% 
  mutate(across((ends_with("_2")), ~if_else(number == 0, NA_integer_, .)))

# A tibble: 6 x 6
     id   X_1   Y_1 number   X_2   Y_2
  <int> <int> <int>  <int> <int> <int>
1     1    NA    NA      1     1     3
2     1     1     3      0    NA    NA
3     2    NA    NA      1     2     4
4     2     2     4      0    NA    NA
5     3    NA    NA      1     1     3
6     3     1     3      0    NA    NA

数据

df <- tibble::tribble(
        ~id, ~X_1, ~Y_1, ~number, ~X_2, ~Y_2,
         1L,   1L,   3L,      1L,   1L,   3L,
         1L,   1L,   3L,      0L,   1L,   3L,
         2L,   2L,   4L,      1L,   2L,   4L,
         2L,   2L,   4L,      0L,   2L,   4L,
         3L,   1L,   3L,      1L,   1L,   3L,
         3L,   1L,   3L,      0L,   1L,   3L
        )

【讨论】:

  • 你能简单解释一下 ~ 在你的解决方案中做了什么吗?
  • 它是传递匿名函数的快捷方式,来自高级R书:“匿名函数非常有用,但语法很冗长。所以purrr支持一个特殊的快捷方式:map_dbl(mtcars, ~length (唯一(.x)))”。所以在我们的例子中,我们不必输入“function(x) na_if(number, 1))”,但可以将“function(x)”替换为“~”。
  • 我刚刚意识到,当我希望它们保留其原始值时,所有值都已更改为 0 或 1。例如,对于 X_1 和 Y_1,第 2 行仍应为 1、3。所有的 NA 都在正确的位置,但我不想替换任何其他值。你知道如何解决这个问题吗?
【解决方案2】:

如果你的数据很大,可以像这样使用data.table-package 来提高速度

library( data.table )
#first make your data a data.table, using `setDT( mydata )`
cols <- grep( "_1$", names(DT), value = TRUE )
for(col in cols) set(dt, i=which(dt[[col]]==1), j=cols, value=NA)
cols <- grep( "_2$", names(DT), value = TRUE )
for(col in cols) set(dt, i=which(dt[[col]]==0), j=cols, value=NA)

【讨论】:

    猜你喜欢
    • 2018-11-17
    • 1970-01-01
    • 2018-11-18
    • 1970-01-01
    • 1970-01-01
    • 2015-06-30
    • 2018-09-07
    • 2013-03-15
    相关资源
    最近更新 更多