【问题标题】:Replace several values and keep others same efficiently in R在 R 中替换多个值并有效地保持其他值相同
【发布时间】:2020-10-20 20:03:42
【问题描述】:

我有一个如下的数据框:

combo_2  combo_4  combo_7  combo_9
12       23       14       17
21       32       41       71
2        3        1        7
1        2        4        1
21       23       14       71
2        32       1        7

每列有两个个位数的值和两个由个位数值按可能顺序组成的两位数值。

我正在尝试确定如何替换数据框中的某些值,以便只有一个版本的两位数值。例如,第一列中所有 21 的值都应为 12。第二列中所有 32 的值都应为 23。

我知道我可以使用以下代码来做这样的事情:

df <- df %>%
    mutate_at(vars(combo_2, combo_4, combo_7, combo_9), function(x)
    case_when(x == 21 ~ 12, x == 32 ~ 23, x == 41 ~ 14, x == 71 ~ 17))

这样做的问题是它给了我一个数据框,它在指定时包含正确的值,但将所有其他值保留为 NA。生成的数据帧仅包含 21、32、41 和 71 所在的值。我知道我可以通过指定每个值来解决这个问题,例如 x == 1 ~ 1。但是,我有很多值,并且希望只指定我想要更改的值。

如何替换数据框中的多个值而不使所有其他值变为 NA?有没有办法让我替换我想要替换的值,同时保持其他值相同而不直接指定这些值?

【问题讨论】:

  • df1[ df1 == 21 ] &lt;- 12 怎么样?
  • 当我有 1 列和 1 个值要替换时效果很好,但我试图找到一种方法同时对多列执行此操作并且当我有几个不同的值要替换时。跨度>

标签: r tidyverse dplyr


【解决方案1】:

您可以在case_when() 序列的末尾使用TRUE ~ x

df %>%
  mutate_at(vars(combo_2, combo_4, combo_7, combo_9), function(x)
    case_when(x == 21 ~ 12, x == 32 ~ 23, x == 41 ~ 14, x == 71 ~ 17, TRUE ~ x))

  combo_2 combo_4 combo_7 combo_9
1      12      23      14      17
2      12      23      14      17
3       2       3       1       7
4       1       2       4       1
5      12      23      14      17
6       2      23       1       7

另一个可能更有效的选项是data.tablefcase() 函数。

数据

df = read.table(header = TRUE, text = "combo_2  combo_4  combo_7  combo_9
12       23       14       17
21       32       41       71
2        3        1        7
1        2        4        1
21       23       14       71
2        32       1        7")

df[] = lapply(df, as.double) # side-note: tidyverse has become very stict about types

【讨论】:

  • 你能解释一下 TRUE ~ x 是什么意思吗?我对文档有些困惑。
  • 文档上的内容出奇地不清楚。因为它按顺序评估参数,所以如果没有匹配的情况,它会返回NA(如您所见)。将 TRUE ~ x last 循环使用 TRUE 以根据您之前的标准(即所有剩余值)尚未匹配的所有值。这有助于澄清吗?
【解决方案2】:

dplyrstringi 选项可能是:

df %>%
 mutate(across(everything(), 
               ~ if_else(. %in% c(21, 32, 41, 71), as.integer(stri_reverse(.)), .)))

  combo_2 combo_4 combo_7 combo_9
1      12      23      14      17
2      12      23      14      17
3       2       3       1       7
4       1       2       4       1
5      12      23      14      17
6       2      23       1       7

【讨论】:

  • 有没有一种简单的方法可以修改它以使其更通用?就像 21 的替代品不是 12 的情况一样。
  • 由于不符合规则,您必须手动指定此类实例。
  • @melbez 请提供真实数据和预期输出。
【解决方案3】:

使用映射

df1[] <- mapply(function(d, x1, x2){ ifelse(d == x1, x2, d) },
                d = df1, 
                x1 = c(21, 32, 41, 71),
                x2 = c(12, 23, 14, 17))

df1
#   combo_2 combo_4 combo_7 combo_9
# 1      12      23      14      17
# 2      12      23      14      17
# 3       2       3       1       7
# 4       1       2       4       1
# 5      12      23      14      17
# 6       2      23       1       7

【讨论】:

    猜你喜欢
    • 2021-05-30
    • 2022-11-14
    • 2021-02-21
    • 1970-01-01
    • 2014-08-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 1970-01-01
    相关资源
    最近更新 更多