如何根据R中的条件替换多列中的值

How to replace values in multiple columns according to conditions in R

提问人:Nampa Gwakondo 提问时间:11/14/2023 最后编辑:Nampa Gwakondo 更新时间:11/14/2023 访问量:62

问:

我在编写代码时遇到问题,该代码将多列中的所有指定值替换为新值。数据框有 20+ 列,我只想更改 8 列(col1、col2、col3 等)中的值。我想将所有值(4、5、6、7)分别替换为 (0, -1, -2, -3)。我在 R 和 progamming 方面的知识非常有限,我只能得到一个可以完成一列工作的解决方案。

我在这里阅读了很多类似问题的解决方案,但我可以找到适合我的解决方案。所以这是我的代码:

data$col1[raw_data$col1 == 4 ] <- 0
data$col1[raw_data$col1 == 5 ] <- -1
data$col1[raw_data$col1 == 6] <- -2
data$col1[raw_data$col1 == 7] <- -3

因此,这适用于一列。我可以为所有列做一个吗?

下面是列和值的代码片段:dataframe

r 替换 mutate

评论

1赞 PGSA 11/14/2023
请注意 - 现有列是数字,但您的替换是字符串 - 您不需要新值的周围。" "
0赞 Julian 11/14/2023
你可以看看 和 .dplyr::acrossdplyr::case_when
0赞 Nampa Gwakondo 11/14/2023
你有什么指@Julian?例如,我使用了这个例子,但我无法弄清楚如何根据这个例子指定我的所有列和 4 个条件:[stackoverflow.com/questions/42888008/...
1赞 PGSA 11/14/2023
根据对现有答案的评论,我认为您的数据集需要首先清理 - 将任何列转换为适当的数据类型(整数、双精度、字符串)等,以便更清楚地了解您正在使用的内容,决定如何处理 NA 条目(并检查它们是真实的,而不是像这样的字符串NA"N/A")
1赞 Nampa Gwakondo 11/14/2023
我已经清理了我的数据并删除了缺失的值。现在我有了所有的数值。我不再收到错误,也没有替换值。

答:

0赞 PGSA 11/14/2023 #1

设置一个示例:

demodf <- data.frame(
  col1 = 1:10,
  col2 = 3:12,
  col3 = 5:14,
  col4 = 7:16
)

cols_to_amend <- c("col1", "col3")

仅替换相关列:

demodf[cols_to_amend] <- apply(demodf[cols_to_amend], 2, FUN = \(x) sapply(x, \(y) if (y %in% 4:7) 4-y else y))

给:

   col1 col2 col3 col4
1     1    3   -1    7
2     2    4   -2    8
3     3    5   -3    9
4     0    6    8   10
5    -1    7    9   11
6    -2    8   10   12
7    -3    9   11   13
8     8   10   12   14
9     9   11   13   15
10   10   12   14   16

解释:

# we can use the list of column names to choose where we are replacing
demodf[cols_to_amend]
# we then use `apply` and `MARGIN = 2` to apply a function to each column in this data frame:
 <- apply(demodf[cols_to_amend], 2,
# The function we apply will be an anonymous function (`\( )`) taking as its input one column at a time:
FUN = \(x)
# and it will use `sapply` to go down that column performing the following on each item:
\(y) if (y %in% 4:7) 4-y else y)

DPLYR 版本:

library(dplyr)

demodf |> 
  mutate(
    across(all_of(cols_to_amend),
           ~ ifelse(.x %in% 4:7, 4-.x, .x)
           )
    )

DPLYR 版本 2

这个玩具示例过于复杂,但允许比简单数学更复杂的替换:

demodf |> 
  mutate(
    across(all_of(cols_to_amend),
           ~ case_when(.x == 4 ~ 0,
                       .x == 5 ~ -1,
                       .x == 6 ~ -2,
                       .x == 7 ~ -3,
                       .default = .x)
           )
    )

评论

0赞 Nampa Gwakondo 11/14/2023
非常感谢保罗,但我有一个错误:4 - y 中的错误:二进制运算符的非数字参数。
0赞 PGSA 11/14/2023
啊,你的值必须存储为字符串(文本)而不是数字,或者你可能有缺失的值?
0赞 Nampa Gwakondo 11/14/2023
我有 n/a 值,我添加了 na.omit(data1),但它仍然不起作用。
0赞 PGSA 11/14/2023
@NampaGwakondo 你能用它来获取你的数据的精确副本,并作为代码块编辑到你的原始问题中吗?这将允许一个更有力的答案。请参阅此处获取帮助:stackoverflow.com/a/5963610/16730940dput()
0赞 Julien PRAMIL 11/14/2023 #2

只需替换要修改的相应列名,它应该可以工作。

library(dplyr)

df <- data.frame(
  ID = 1:5,
  col1 = c(4, 5, 6, 7, 8),
  col2 = c(4, 5, 6, 7, 8),
  col3 = c(4, 5, 6, 7, 8),
  col4 = c(4, 5, 6, 7, 8),
  col5 = c(4, 5, 6, 7, 8),
  col6 = c(4, 5, 6, 7, 8),
  col7 = c(4, 5, 6, 7, 8),
  col8 = c(4, 5, 6, 7, 8)
)

# Specify the columns you want to modify
columns_to_modify <- c("col5", "col6", "col7")

# Specify a replacement function for the corresponding values

my_fun_replace <- \(vec){
  case_match(
    vec,
    4 ~ 0,
    5 ~ -1,
    6 ~ -2,
    7 ~ -3,
    .default = vec
  )
  
}


# Use across to replace values in specified columns
df <- df %>%
  mutate(across(all_of(columns_to_modify), my_fun_replace))

评论

0赞 Nampa Gwakondo 11/14/2023
好一个..我完全理解语法,但我有一个错误:Caused by error in `across()`: ! Can't compute column `col2`. Caused by error in `case_match()`: ! Can't convert `..1 (left)` <double> to <character>.
0赞 Julien PRAMIL 11/14/2023
这个 repex 有错误吗?哼......我使用 dplyr 版本 1.1.3。也许它来自变量的类。尝试验证它是一个正确的数值变量?class(df$col5)
0赞 Nampa Gwakondo 11/14/2023
这是因为缺少值。我已经清理了数据并删除了缺少值的行。但是,更换仍未进行。没有错误,也没有更改原始值。
0赞 Julien PRAMIL 11/15/2023
不知道。。。你能举一个可重复的例子吗?至少,我的示例在您的会话中是否正常工作?