如何调整字符串替换功能以用 NA 替换数据框中的特定数字?

How to adapt string replacing function to replace specific numbers in data frame with NA?

我写了一个函数,可以完美地用 NA 替换矩阵的自定义值。

NAfun <- function (x, z) {
  x[x %in% z] <- NA
  x
}

M <- matrix(1:12, 3, 4)
M[1, 2] <- -77
M[2, 1] <- -99
> M
     [,1] [,2] [,3] [,4]
[1,]    1  -77    7   10
[2,]  -99    5    8   11
[3,]    3    6    9   12

z <- c(-77, -99)

> NAfun(M, z)
     [,1] [,2] [,3] [,4]
[1,]    1   NA    7   10
[2,]   NA    5    8   11
[3,]    3    6    9   12

但这不适用于数据框。

D <- as.data.frame(matrix(LETTERS[1:12], 3, 4))
> D
  V1 V2 V3 V4
1  A  D  G  J
2  B  E  H  K
3  C  F  I  L

z <- c("B", "D")

> NAfun(D, z)
  V1 V2 V3 V4
1  A  D  G  J
2  B  E  H  K
3  C  F  I  L

D[] <- lapply(D, function(x) as.character(x))  # same with character vectors

> NAfun(D, z)
  V1 V2 V3 V4
1  A  D  G  J
2  B  E  H  K
3  C  F  I  L

不过,如果我将数据框转换为矩阵,它就可以工作。

> NAfun(as.matrix(D), z)
     V1  V2  V3  V4 
[1,] "A" NA  "G" "J"
[2,] NA  "E" "H" "K"
[3,] "C" "F" "I" "L"

但我不能。

我不明白为什么这不能正常工作。以及调整函数的方式,使其适用于数据框,或者最好是两种类型,谢谢。

正如@Lyngbakr 正确提到的那样,DM 之间的行为是一致的。 NAfun 函数在 D 上运行,因为它已经由行 D <- sapply(D, as.character) 转换为 matrix

现在,问题是为什么 matrixdata.frame 之间的行为不一致?实际原因是 %in% 运算符。

%in% 运算符将向量 z 中矩阵的每个值比较为:

D %in% z
#[1] FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

而 data.frame 上的 %in% 运算符比较匹配列。因此,

M %in% c(-99,-77)
#[1] FALSE FALSE FALSE FALSE

但是

M %in% M[1:2]
#[1]  TRUE  TRUE FALSE FALSE

M %in% list(c(1,-99,3))
[1]  TRUE FALSE FALSE FALSE

函数 NAfun 需要修改以处理 data.framematrix:

NAfun <- function (x, z) {
  x <- as.matrix(x)
  x[x %in% z] <- NA
  x
}

您可以使它更优雅,但这里有一个使用 purrr 的解决方案,适用于这两种情况。

NAfun <- function (x, z) {

     f1 <- function(x, z){
          x[x %in% z] <- NA
          x
     }
     purrr::modify(x, ~f1(., z))
}