我有一个数据框:
mydf <- data.frame(
col1 = c("54", "abc", "123", "54 abc", "zzz", "a", "99"),
col2 = c("100", "200", "300", "400", "500", "600", "700"),
stringsAsFactors = FALSE
)
在此数据框中,我想用 NA 替换所有元素,除非它们满足以下条件之一:
- 严格来说是一个数字(例如“54”保留,“54 abc”丢弃)
- 属于 target_string
我不确定如何使用 apply 在 R 中执行此操作,因此我尝试编写一个循环:
target_string <- c("a", "zzz")
replace_with_na_old <- function(df, target_string) {
for (i in 1:nrow(df)) {
for (j in 1:ncol(df)) {
value <- df[i, j]
if (!grepl("^[0-9]+$", value) && !(value %in% target_string)) {
df[i, j] <- NA
}
}
}
return(df)
}
mydf_cleaned_old <- replace_with_na_old(mydf, target_string)
还有其他方法可以做到这一点吗?
注意:以下是如何用 %like% 替换 %in%:
replace_with_na_new <- function(df, target_string) {
for (i in 1:nrow(df)) {
for (j in 1:ncol(df)) {
value <- df[i, j]
if (!grepl("^[0-9]+$", value) && !any(sapply(target_string, function(pattern) grepl(pattern, value)))) {
df[i, j] <- NA
}
}
}
return(df)
}
最佳答案
3
您已经有了检查这一点所需的逻辑,您所需要做的就是对其进行矢量化。
replace_with_na <- function(value, target_string) {
value[!(grepl('^\\d+$', value) | value %in% target_string)] <- NA
value
}
apply*
现在,您可以使用基础 R 中的任何函数将此函数应用于每一列。
new_df <- mydf
new_df[] <- lapply(mydf, replace_with_na, target_string)
new_df
# col1 col2
#1 54 100
#2 <NA> 200
#3 123 300
#4 <NA> 400
#5 zzz 500
#6 a 600
#7 99 700
或者如果您愿意,dplyr
我们可以使用across
类似的结果。
library(dplyr)
mydf %>% mutate(across(everything(), \(x) replace_with_na(x, target_string)))
|
您可以替换所有不属于target_string
且包含非数字字符的元素。
mydf[sapply(mydf, \(x) grepl("\\D", x) & !x %in% target_string)] = NA
col1 col2
1 54 100
2 <NA> 200
3 123 300
4 <NA> 400
5 zzz 500
6 a 600
7 99 700
1
-
一个变体可能是
is.na(mydf) <- vapply(mydf, \(x) grepl("\\D", x) & !x %in% target_string, logical(nrow(mydf)))
–
|
您可以提前生成正则表达式模式,然后应用grepl
,例如,
patt <- sprintf(
"^\\d+$|%s",
paste0(sprintf("\\b%s\\b", target_string), collapse = "|")
)
list2DF(lapply(mydf, \(x) replace(x, !grepl(patt, x), NA)))
给出
col1 col2
1 54 100
2 <NA> 200
3 123 300
4 <NA> 400
5 zzz 500
6 a 600
7 99 700
2
-
target_string
在给定的例子中,这是可行的,但是当包含正则表达式将解释的内容时,可能会出现问题.
。例如,也许还可以使用stringr::str_escape
。
– -
@GKi 感谢指出这一点!是的,如果处理类似这样的问题,我的代码就会遇到麻烦
.
。在这种情况下,我承认其他两个比我的更强大、更安全。
–
|
|