您可以将不是 1 或 2 的元素转换为 NA,只需使用逻辑条件 df1==2 将其转换为逻辑矩阵,TRUE 为 2,FALSE 为 1,其余的NA
is.na(df1) <- !(df1==1|df1==2)
df1==2
对于大型数据集,最好使用lapply 循环遍历列
df1[] <- lapply(df1, function(x) {x[!x %in% c(1,2)] <- NA
x==2})
更新
如果我们只想应用列名以“XX”开头的列子集,grep 可以选择将列子集化,然后在该列子集上循环使用 lapply 并将该列替换为lapply 的输出。
indx <- grep('^XX', colnames(df2))
df2[indx] <- lapply(df2[indx], function(x) {x[!x %in% c(1,2)] <- NA
x==2})
另一种选择是使用来自dplyr 的mutate_each
library(dplyr)
mutate_each(df2, funs((NA^!. %in% 1:2)*.==2), matches('^XX'))
我们选择名称以 XX (matches('^XX')) 开头的列,在 funs 中创建逻辑条件。 . 表示列中的任何元素。
. %in% 1:2
给出一个逻辑输出。如果元素是 1 或 2,我们得到TRUE,如果不是FALSE。
(NA^!. %in% 1:2)
我们对TRUE/FALSE的输出取反(!),使TRUE变为FALSE,FALSE变为TRUE,将TRUE值变为NA(NA^!...),从而将不是1或2的值转换为NA和所有其他值到 1。
*.==2
然后我们将* 与我们从之前的输出中得到的值相乘,这样 NA 值保持为 NA 并且 1 值更改为该位置的值,例如1*2=2。这可以通过.==2 制成逻辑输出。如果值为 2,则返回 TRUE,否则(即 1)返回 FALSE。
使用mutate_each不会改变原来的对象,除非我们给原来的对象名赋值
df2 <- mutate_each(df2, funs((NA^!. %in% 1:2)*.==2), matches('^XX'))
另一个无需重新分配的选项是使用来自magrittr 的%<>% 运算符
library(magrittr)
df2 %<>%
mutate_each(funs((NA^!. %in% 1:2)*.==2), matches('^XX'))
数据
set.seed(24)
df1 <- as.data.frame(matrix(sample(1:5, 20*5, replace=TRUE), ncol=5))
df2 <- df1
colnames(df2)[c(2,4)] <- paste0('XX', 1:2)