使用向量对数组进行子集筛选

3
我觉得这个问题应该已经有答案了,但我没有找到。我有一个数组,想使用一个向量对其进行子集操作。我知道如何以困难的方式做到这一点,但我相信一定有更简单的方法。有什么想法吗?
以下是我的示例:
dat <- data.frame(a = rep(letters[1:3], 2), b = rep(letters[1:2], 3), c = c(rep("a", 5), "b"), x = rnorm(6), stringsAsFactors = FALSE)

l <- by(dat[ , "x"], dat[ , 1:3], mean)

l["a", "a", "a"] # works  
l[c("a", "a", "a")] # does not work

所以我猜我需要找到一种方法,将 c("a", "a", "a") 中的 c() 包装器移除,然后再将其传递给 l

2个回答

4
这个问题已经有答案了,但我想让事情更加清晰一些。我们来看看你在这里的例子:
dat <- data.frame(a = rep(letters[1:3], 2), b = rep(letters[1:2], 3), c = c(rep("a", 
    5), "b"), x = rnorm(6), stringsAsFactors = FALSE)

l <- by(dat[, "x"], dat[, 1:3], mean)

l["a", "a", "a"]  # works  

## [1] 1.246

l[c("a", "a", "a")]  # does not work

## [1] NA NA NA

之前的答案建议使用matrix(rep("a", 3), nrow=1)进行子集操作。 我想进一步解释为什么这个方法是有效的。首先,让我们看一下这两种数据结构之间的区别:
a.mat <- matrix(rep("a", 3), nrow = 1)
a.vec <- c("a", "a", "a")  # Note: this is equivalent to rep('a', 3)
a.mat

##      [,1] [,2] [,3]
## [1,] "a"  "a"  "a"

a.vec

## [1] "a" "a" "a"

as.matrix(a.vec)

##      [,1]
## [1,] "a" 
## [2,] "a" 
## [3,] "a"

l[a.mat]

## [1] 1.246

l[a.vec]

## [1] NA NA NA

l[as.matrix(a.vec)]

## [1] NA NA NA
a.vec在输出到屏幕时看起来相同,但它们的处理方式不同,因为R以列主序的方式创建矩阵,即按列写入和读取矩阵。当您使用矩阵进行子集操作时,它将使用每个列作为不同的维度。如果矩阵中的列数与要进行子集操作的对象的维数匹配,则它会将每个列用于每个后续维度。

如果列数不匹配,R将折叠矩阵为向量,并尝试以此方式匹配元素索引。以下是一些示例:

a.mat[, -1]  # Now only two columns

## [1] "a" "a"

l[a.mat[, -1]]  # Notice you get NA twice here.

## [1] NA NA

l[matrix(rep("a", 4), nrow = 1)]  # Using a matrix with 4 columns.

## [1] NA NA NA NA

作为附注,当您使用字符向量进行子集操作时,R将尝试匹配任何元素的名称。如果它们不存在,则会得到一个NA或错误:
# Vector example:
x <- letters
x[1]

## [1] "a"

x["a"]

## [1] NA

names(x) <- letters
x[1]

##   a 
## "a"

x["a"]

##   a 
## "a"

x[c("a", "a", "a")]

##   a   a   a 
## "a" "a" "a"

x[a.mat]  # collapsing matrix down to a vector.

##   a   a   a 
## "a" "a" "a"
# Matrix example:
x <- matrix(letters[1:9], nrow = 3, ncol = 3)
x

##      [,1] [,2] [,3]
## [1,] "a"  "d"  "g" 
## [2,] "b"  "e"  "h" 
## [3,] "c"  "f"  "i"

x[c(1, 1)]

## [1] "a" "a"

x[1, 1]

## [1] "a"

x[c("a", "a")]

## [1] NA NA

x["a", "a"]

## Error: no 'dimnames' attribute for array

rownames(x) <- letters[1:3]
colnames(x) <- letters[1:3]
x

##   a   b   c  
## a "a" "d" "g"
## b "b" "e" "h"
## c "c" "f" "i"

x[c(1, 1)]

## [1] "a" "a"

x[1, 1]

## [1] "a"

x[c("a", "a")]

## [1] NA NA

x["a", "a"]

## [1] "a"

最后,如果您使用数字向量,您将始终获得一个定义的值(除非超出范围):
l[c(1,1,1)]

## [1] 1.246 1.246 1.246

l[1, 1, 1]

## [1] 1.246 

3

你可以使用矩阵代替向量:

l[matrix(rep("a", 3), nrow=1)]

4
可以直接转置向量,使用 t(c("a", "a", "a"))。转置后的结果是一个行向量。 - Josh O'Brien

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接