我正试图处理无处不在的which
函数。在我开始阅读问题/答案之前,我从未发现它的必要性。而我仍然没有。
据我所知,which
采用布尔向量并返回一个弱的较短向量,其中包含元素的索引为真:
> seq(10)
[1] 1 2 3 4 5 6 7 8 9 10
> x <- seq(10)
> tf <- (x == 6 | x == 8)
> tf
[1] FALSE FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE
> w <- which(tf)
> w
[1] 6 8
那么我为什么要使用which
而不是直接使用布尔向量?我可能会看到一些巨大的向量存在内存问题,因为length(w)
&lt;&lt; length(tf)
,但这并不令人信服。并且帮助文件中有一些选项不会增加我对此功能的可能用途的理解。帮助文件中的示例也没有多大帮助。
为了清晰起见而编辑 - 我了解which
会返回索引。我的问题是关于两件事: 1)为什么你需要使用索引而不是仅仅使用布尔选择器向量?和 2) which
的哪些有趣行为可能会让我更喜欢使用矢量化布尔比较?
答案 0 :(得分:25)
好的,这是昨晚证明有用的东西:
在给定的值向量中,第3个非NA值的索引是什么?
> x <- c(1,NA,2,NA,3)
> which(!is.na(x))[3]
[1] 5
与DWin的使用略有不同,虽然我说他的引人注目!
答案 1 :(得分:19)
手册页?which
的标题提供了动力。标题是:
哪些指数为
TRUE
?
如果您想知道逻辑向量的元素是TRUE
,我将其解释为可能使用的函数。这与仅使用逻辑向量本身本质上是不同的。这会选择TRUE
的元素,而不是告诉你哪些元素是TRUE
。
常见的用例是获取向量中最大值或最小值的位置:
> set.seed(2)
> x <- runif(10)
> which(x == max(x))
[1] 5
> which(x == min(x))
[1] 7
这些常用,which.max()
和which.min()
已创建:
> which.max(x)
[1] 5
> which.min(x)
[1] 7
但是,请注意,特定表单不是通用表单的准确替换。有关详细信息,请参阅?which.min
。一个例子如下:
> x <- c(4,1,1)
> which.min(x)
[1] 2
> which(x==min(x))
[1] 2 3
答案 2 :(得分:17)
两个非常令人信服的理由,不要忘记which
:
1)当您使用“[”从数据框中提取时,行位置中导致NA的任何计算都将返回一个垃圾行。使用which
删除NA。您可以使用subset
或%in%
,但不会产生同样的问题。
> dfrm <- data.frame( a=sample(c(1:3, NA), 20, replace=TRUE), b=1:20)
> dfrm[dfrm$a >0, ]
a b
1 1 1
2 3 2
NA NA NA
NA.1 NA NA
NA.2 NA NA
6 1 6
NA.3 NA NA
8 3 8
# Snipped remaining rows
2)当你需要阵列指示器时。
答案 3 :(得分:12)
which
可能有用(通过保存计算机和人力资源),例如如果必须按给定的变量/列过滤数据框/矩阵的元素,并根据它更新其他变量/列。例如:
df <- mtcars
而不是:
df$gear[df$hp > 150] <- mean(df$gear[df$hp > 150])
你可以这样做:
p <- which(df$hp > 150)
df$gear[p] <- mean(df$gear[p])
如果您必须过滤过滤后的元素,则需要使用简单&
或|
无法完成的操作。当您必须根据其他数据表更新数据框的某些部分时。这样就需要存储(至少是临时的)过滤元素的索引。
如果你不得不循环思考数据框架/矩阵的一部分,或者必须进行其他类型的转换,需要知道几种情况的索引,那么我会想到另一个问题。例如:
urban <- which(USArrests$UrbanPop > 80)
> USArrests[urban, ] - USArrests[urban-1, ]
Murder Assault UrbanPop Rape
California 0.2 86 41 21.1
Hawaii -12.1 -165 23 -5.6
Illinois 7.8 129 29 9.8
Massachusetts -6.9 -151 18 -11.5
Nevada 7.9 150 19 29.5
New Jersey 5.3 102 33 9.3
New York -0.3 -31 16 -6.0
Rhode Island -2.9 68 15 -6.6
对于虚拟的例子很抱歉,我知道将美国最城市化的州与字母表中的州比较之前没有多大意义,但我希望这是有道理的:)
结帐which.min
和which.max
也提供了一些线索,因为您不必输入很多内容,例如:
> row.names(mtcars)[which.max(mtcars$hp)]
[1] "Maserati Bora"
答案 4 :(得分:11)
好吧,我找到了一个可能的原因。起初我认为它可能是,useNames
选项,但事实证明,简单的布尔选择也是如此。
但是,如果您感兴趣的对象是矩阵,则可以使用,arr.ind
选项将结果作为(行,列)有序对返回:
> x <- matrix(seq(10),ncol=2)
> x
[,1] [,2]
[1,] 1 6
[2,] 2 7
[3,] 3 8
[4,] 4 9
[5,] 5 10
> which((x == 6 | x == 8),arr.ind=TRUE)
row col
[1,] 1 2
[2,] 3 2
> which((x == 6 | x == 8))
[1] 6 8
这是一个方便的技巧,但似乎没有理由证明它的不断使用。
答案 5 :(得分:7)
很惊讶没有人回答这个问题:内存效率怎么样?
如果你有一个非常稀疏的TRUE
的长向量,那么只跟踪TRUE值的索引可能会更加紧凑。
答案 6 :(得分:4)
我经常在数据探索中使用它。例如,如果我有一个孩子数据的数据集,并从摘要中看到最大年龄是23(并且应该是18),我可能会去:
sum(dat$age>18)
如果那是67,我想看得更近,我可以使用:
dat[which(dat$age>18)[1:10], ]
如果您正在进行演示并希望提取一小段数据以证明某种奇怪或不存在,那么也很有用。