提问人:Nampa Gwakondo 提问时间:11/14/2023 最后编辑:Nampa Gwakondo 更新时间:11/14/2023 访问量:62
如何根据R中的条件替换多列中的值
How to replace values in multiple columns according to conditions in R
问:
我在编写代码时遇到问题,该代码将多列中的所有指定值替换为新值。数据框有 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
因此,这适用于一列。我可以为所有列做一个吗?
答:
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
不知道。。。你能举一个可重复的例子吗?至少,我的示例在您的会话中是否正常工作?
评论
" "
dplyr::across
dplyr::case_when
NA
"N/A"
)