为什么 R 不能在一组空索引上正确删除元素?
Why does R not remove elements properly over an empty set of indices?
我在 R
中遇到了一些奇怪的行为。假设我有一个矩阵,我想删除一组指定的行和列。这是一个非常有效的示例。
#Create a matrix
MATRIX <- matrix(1:50, nrow = 4, ncol = 5)
rownames(MATRIX) <- c('a', 'b', 'c', 'd')
colnames(MATRIX) <- c('a', 'b', 'c', 'd', 'e')
#Specify rows and columns to remove
REMOVE.ROW <- 3
REMOVE.COL <- 2
#Print the matrix without these rows or columns
MATRIX[-REMOVE.ROW, -REMOVE.COL]
a c d e
a 1 9 13 17
b 2 10 14 18
d 4 12 16 20
但是,当 REMOVE.ROW
或 REMOVE.COL
中的一个或两个对象为 空 时,而不是什么都不删除(因此返回原始矩阵),它返回一个空矩阵。
#Specify rows and columns to remove
REMOVE.ROW <- integer(0)
REMOVE.COL <- integer(0)
#Print the matrix without these rows or columns
MATRIX[-REMOVE.ROW, -REMOVE.COL]
<0 x 0 matrix>
凭直觉,我本以为删除一组空的索引会留下原始的一组索引,因此我本以为会从该命令返回完整的矩阵。由于某种原因,R
在这种情况下从矩阵中删除了所有行和列。据我所知,这似乎是 R
中的错误,但也许有一些我不知道的充分理由。
问题:有人可以解释一下为什么 R
会这样吗?除了使用 if-then 语句来处理特殊情况之外,我是否可以进行任何简单的调整以使 R
像我想要的那样运行?
空对象有一个奇怪的 属性,它们不是 NULL
,长度为 0,但不是子集化的。一种可能的解决方法是考虑所有可能的组合并使用 属性 使 length(integer0)
等于零。我知道这个解决方案可能并不理想。
is.na(integer(0))
#> logical(0)
is.null(integer(0))
#> [1] FALSE
length(integer(0))
#> [1] 0
integer(0)[[1]]
#> Error in integer(0)[[1]]: subscript out of bounds
integer(0)[[0]]
#> Error in integer(0)[[0]]: attempt to select less than one element in get1index <real>
MATRIX <- matrix(1:50, nrow = 4, ncol = 5)
#> Warning in matrix(1:50, nrow = 4, ncol = 5): data length [50] is not a sub-
#> multiple or multiple of the number of rows [4]
REMOVE.ROW <- integer(0)
REMOVE.COL <- integer(0)
if (all(length(REMOVE.ROW > 0) , length(REMOVE.COL) > 0)) {
MATRIX[-REMOVE.ROW, -REMOVE.COL]
} else {
if (length(REMOVE.ROW) > 0 && length(REMOVE.COL) == 0) {
MATRIX[-REMOVE.ROW, ]
} else {
if (length(REMOVE.ROW) == 0 && length(REMOVE.COL) > 0) {
MATRIX[, -REMOVE.COL]
} else {
MATRIX
}
}
}
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 1 5 9 13 17
#> [2,] 2 6 10 14 18
#> [3,] 3 7 11 15 19
#> [4,] 4 8 12 16 20
由 reprex package (v2.0.1)
于 2021-11-27 创建
问题是R
使用的是算术求反,不是集求反
根据有用的评论(给 IceCreamToucan 的帽子提示),这似乎是因为使用负索引对矩阵进行索引时涉及两步过程,负索引是使用算术求反而不是集合构造的否定。这似乎是其中一个运算的标准数学解释不同于计算解释。
在一组索引上对矩阵进行索引的数学解释中,我们将 set negation 视为生成一个新集合,该集合由原始 'sample space' 中但在否定集合之外的元素组成。在 R
中的计算解释中,负号的应用产生了负算术值,这些随后被解释为调用矩阵时要删除的元素。
在这种情况下发生了什么: 对于我们有一组非空索引的通常情况,使用否定符号只是将索引变成 负值,然后当我们调用矩阵时,它会查看负值以外的所有索引。
#Specify rows and columns to remove
REMOVE.ROW <- 3
REMOVE.COL <- 2
#See negatives of the removed indices
identical(MATRIX[-REMOVE.ROW, -REMOVE.COL], MATRIX[-3, -2])
[1] TRUE
但是,当我们使用空索引向量时,该向量的负值仍然是空索引向量——即向量 integer(0)
与其负值 -integer(0)
相同.因此,当我们尝试删除索引的空向量时,我们实际上是在要求调用矩阵对空向量的负数,它仍然是空向量。
#The empty vector is equivalent to its negative
identical(integer(0), -integer(0))
[1] TRUE
#Therefore, calling over these vectors is equivalent
identical(MATRIX[-integer(0), -integer(0)], MATRIX[integer(0), integer(0)])
[1] TRUE
所以,这里的问题是您将 -REMOVE.ROW
和 -REMOVE.COL
解释为好像他们在使用 set negation 而实际上他们只是在使用值的初始向量并将它们变为负数(即,将它们乘以负数)。
解决问题:似乎没有一个标准的函数来调用矩阵以使用集合否定解释索引的方式,所以你需要使用条件为特定案例或自定义函数构造解决方案的逻辑。这是一个自定义函数 sub.matrix
,用于删除特定的行和列,这些行和列在集合否定的意义上进行解释。
sub.matrix <- function(x, remove.rows = integer(0), remove.cols = integer(0)) {
#Check that input x is a matrix
if (!('matrix' %in% class(x))) {
stop('This function is only for objects of class \'matrix\'') }
#Create output matrix
R <- length(remove.rows)
C <- length(remove.cols)
if ((R > 0)&(C > 0)) { OUT <- MATRIX[-remove.rows, -remove.cols] }
if ((R == 0)&(C > 0)) { OUT <- MATRIX[, -remove.cols] }
if ((R > 0)&(C == 0)) { OUT <- MATRIX[-remove.rows, ] }
if ((R == 0)&(C == 0)) { OUT <- MATRIX }
#Return the output matrix
OUT }
我在 R
中遇到了一些奇怪的行为。假设我有一个矩阵,我想删除一组指定的行和列。这是一个非常有效的示例。
#Create a matrix
MATRIX <- matrix(1:50, nrow = 4, ncol = 5)
rownames(MATRIX) <- c('a', 'b', 'c', 'd')
colnames(MATRIX) <- c('a', 'b', 'c', 'd', 'e')
#Specify rows and columns to remove
REMOVE.ROW <- 3
REMOVE.COL <- 2
#Print the matrix without these rows or columns
MATRIX[-REMOVE.ROW, -REMOVE.COL]
a c d e
a 1 9 13 17
b 2 10 14 18
d 4 12 16 20
但是,当 REMOVE.ROW
或 REMOVE.COL
中的一个或两个对象为 空 时,而不是什么都不删除(因此返回原始矩阵),它返回一个空矩阵。
#Specify rows and columns to remove
REMOVE.ROW <- integer(0)
REMOVE.COL <- integer(0)
#Print the matrix without these rows or columns
MATRIX[-REMOVE.ROW, -REMOVE.COL]
<0 x 0 matrix>
凭直觉,我本以为删除一组空的索引会留下原始的一组索引,因此我本以为会从该命令返回完整的矩阵。由于某种原因,R
在这种情况下从矩阵中删除了所有行和列。据我所知,这似乎是 R
中的错误,但也许有一些我不知道的充分理由。
问题:有人可以解释一下为什么 R
会这样吗?除了使用 if-then 语句来处理特殊情况之外,我是否可以进行任何简单的调整以使 R
像我想要的那样运行?
空对象有一个奇怪的 属性,它们不是 NULL
,长度为 0,但不是子集化的。一种可能的解决方法是考虑所有可能的组合并使用 属性 使 length(integer0)
等于零。我知道这个解决方案可能并不理想。
is.na(integer(0))
#> logical(0)
is.null(integer(0))
#> [1] FALSE
length(integer(0))
#> [1] 0
integer(0)[[1]]
#> Error in integer(0)[[1]]: subscript out of bounds
integer(0)[[0]]
#> Error in integer(0)[[0]]: attempt to select less than one element in get1index <real>
MATRIX <- matrix(1:50, nrow = 4, ncol = 5)
#> Warning in matrix(1:50, nrow = 4, ncol = 5): data length [50] is not a sub-
#> multiple or multiple of the number of rows [4]
REMOVE.ROW <- integer(0)
REMOVE.COL <- integer(0)
if (all(length(REMOVE.ROW > 0) , length(REMOVE.COL) > 0)) {
MATRIX[-REMOVE.ROW, -REMOVE.COL]
} else {
if (length(REMOVE.ROW) > 0 && length(REMOVE.COL) == 0) {
MATRIX[-REMOVE.ROW, ]
} else {
if (length(REMOVE.ROW) == 0 && length(REMOVE.COL) > 0) {
MATRIX[, -REMOVE.COL]
} else {
MATRIX
}
}
}
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 1 5 9 13 17
#> [2,] 2 6 10 14 18
#> [3,] 3 7 11 15 19
#> [4,] 4 8 12 16 20
由 reprex package (v2.0.1)
于 2021-11-27 创建问题是R
使用的是算术求反,不是集求反
根据有用的评论(给 IceCreamToucan 的帽子提示),这似乎是因为使用负索引对矩阵进行索引时涉及两步过程,负索引是使用算术求反而不是集合构造的否定。这似乎是其中一个运算的标准数学解释不同于计算解释。
在一组索引上对矩阵进行索引的数学解释中,我们将 set negation 视为生成一个新集合,该集合由原始 'sample space' 中但在否定集合之外的元素组成。在 R
中的计算解释中,负号的应用产生了负算术值,这些随后被解释为调用矩阵时要删除的元素。
在这种情况下发生了什么: 对于我们有一组非空索引的通常情况,使用否定符号只是将索引变成 负值,然后当我们调用矩阵时,它会查看负值以外的所有索引。
#Specify rows and columns to remove
REMOVE.ROW <- 3
REMOVE.COL <- 2
#See negatives of the removed indices
identical(MATRIX[-REMOVE.ROW, -REMOVE.COL], MATRIX[-3, -2])
[1] TRUE
但是,当我们使用空索引向量时,该向量的负值仍然是空索引向量——即向量 integer(0)
与其负值 -integer(0)
相同.因此,当我们尝试删除索引的空向量时,我们实际上是在要求调用矩阵对空向量的负数,它仍然是空向量。
#The empty vector is equivalent to its negative
identical(integer(0), -integer(0))
[1] TRUE
#Therefore, calling over these vectors is equivalent
identical(MATRIX[-integer(0), -integer(0)], MATRIX[integer(0), integer(0)])
[1] TRUE
所以,这里的问题是您将 -REMOVE.ROW
和 -REMOVE.COL
解释为好像他们在使用 set negation 而实际上他们只是在使用值的初始向量并将它们变为负数(即,将它们乘以负数)。
解决问题:似乎没有一个标准的函数来调用矩阵以使用集合否定解释索引的方式,所以你需要使用条件为特定案例或自定义函数构造解决方案的逻辑。这是一个自定义函数 sub.matrix
,用于删除特定的行和列,这些行和列在集合否定的意义上进行解释。
sub.matrix <- function(x, remove.rows = integer(0), remove.cols = integer(0)) {
#Check that input x is a matrix
if (!('matrix' %in% class(x))) {
stop('This function is only for objects of class \'matrix\'') }
#Create output matrix
R <- length(remove.rows)
C <- length(remove.cols)
if ((R > 0)&(C > 0)) { OUT <- MATRIX[-remove.rows, -remove.cols] }
if ((R == 0)&(C > 0)) { OUT <- MATRIX[, -remove.cols] }
if ((R > 0)&(C == 0)) { OUT <- MATRIX[-remove.rows, ] }
if ((R == 0)&(C == 0)) { OUT <- MATRIX }
#Return the output matrix
OUT }