如何调整字符串替换功能以用 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 正确提到的那样,D
和 M
之间的行为是一致的。 NAfun
函数在 D
上运行,因为它已经由行 D <- sapply(D, as.character)
转换为 matrix
。
现在,问题是为什么 matrix
和 data.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.frame
和 matrix
:
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))
}
我写了一个函数,可以完美地用 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 正确提到的那样,D
和 M
之间的行为是一致的。 NAfun
函数在 D
上运行,因为它已经由行 D <- sapply(D, as.character)
转换为 matrix
。
现在,问题是为什么 matrix
和 data.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.frame
和 matrix
:
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))
}