在R中,对TRUE
逻辑向量中的值数进行计数的最有效/惯用方式是什么?我可以想到两种方式:
z <- sample(c(TRUE, FALSE), 1000, rep = TRUE)
sum(z)
# [1] 498
table(z)["TRUE"]
# TRUE
# 498
你喜欢哪个?还有什么更好的吗?
在R中,对TRUE
逻辑向量中的值数进行计数的最有效/惯用方式是什么?我可以想到两种方式:
z <- sample(c(TRUE, FALSE), 1000, rep = TRUE)
sum(z)
# [1] 498
table(z)["TRUE"]
# TRUE
# 498
你喜欢哪个?还有什么更好的吗?
Answers:
逻辑向量包含NA
值时存在一些问题。
参见例如:
z <- c(TRUE, FALSE, NA)
sum(z) # gives you NA
table(z)["TRUE"] # gives you 1
length(z[z == TRUE]) # f3lix answer, gives you 2 (because NA indexing returns values)
所以我认为最安全的是使用na.rm = TRUE
:
sum(z, na.rm = TRUE) # best way to count TRUE values
(给出1)。我认为该table
解决方案效率较低(请看table
功能代码)。
另外,如果逻辑向量中没有TRUE值,则应谨慎使用“表”解决方案。假设z <- c(NA, FALSE, NA)
或者干脆z <- c(FALSE, FALSE)
,然后table(z)["TRUE"]
给你NA
的这两种情况。
sum(z, na.rm = TRUE)
另一个未提及的选择是使用which
:
length(which(z))
只是为了提供有关“哪个是更快的问题”的背景信息,测试自己总是最容易的。我将向量做大了比较:
z <- sample(c(TRUE,FALSE),1000000,rep=TRUE)
system.time(sum(z))
user system elapsed
0.03 0.00 0.03
system.time(length(z[z==TRUE]))
user system elapsed
0.75 0.07 0.83
system.time(length(which(z)))
user system elapsed
1.34 0.28 1.64
system.time(table(z)["TRUE"])
user system elapsed
10.62 0.52 11.19
因此,sum
在这种情况下,显然使用是最佳方法。您可能还想NA
按照Marek的建议检查值。
仅添加有关NA值和which
功能的注释:
> which(c(T, F, NA, NULL, T, F))
[1] 1 4
> which(!c(T, F, NA, NULL, T, F))
[1] 2 5
请注意,该命令仅检查TRUE
逻辑值,因此它实际上会忽略非逻辑值。
which
是一个很好的选择,尤其是当您对矩阵进行运算时(请检查?which
并注意arr.ind
参数)。但我建议您坚持使用sum
,因为na.rm
可以NA
在逻辑向量中处理的参数。例如:
# create dummy variable
set.seed(100)
x <- round(runif(100, 0, 1))
x <- x == 1
# create NA's
x[seq(1, length(x), 7)] <- NA
如果你输入sum(x)
你会得到NA
一个结果,但如果传递na.rm = TRUE
的sum
功能,你会得到的结果是你想要的。
> sum(x)
[1] NA
> sum(x, na.rm=TRUE)
[1] 43
您的问题严格是理论上的,还是关于逻辑向量的一些实际问题?
几周前我一直在做类似的事情。这是一个可能的解决方案,它是从头开始编写的,因此它是beta版本或类似的内容。我将尝试通过从代码中删除循环来改善它。
主要思想是编写一个将接受2(或3)个参数的函数。第一个是data.frame
保存从问卷中收集的数据,第二个是带有正确答案的数值向量(这仅适用于单选问卷)。或者,您可以添加第三个参数,该参数将返回具有最终分数的数字矢量或具有嵌入式分数的data.frame。
fscore <- function(x, sol, output = 'numeric') {
if (ncol(x) != length(sol)) {
stop('Number of items differs from length of correct answers!')
} else {
inc <- matrix(ncol=ncol(x), nrow=nrow(x))
for (i in 1:ncol(x)) {
inc[,i] <- x[,i] == sol[i]
}
if (output == 'numeric') {
res <- rowSums(inc)
} else if (output == 'data.frame') {
res <- data.frame(x, result = rowSums(inc))
} else {
stop('Type not supported!')
}
}
return(res)
}
我将尝试通过一些* ply函数以一种更加优雅的方式进行此操作。请注意,我没有提出na.rm
争论...将这样做
# create dummy data frame - values from 1 to 5
set.seed(100)
d <- as.data.frame(matrix(round(runif(200,1,5)), 10))
# create solution vector
sol <- round(runif(20, 1, 5))
现在应用一个函数:
> fscore(d, sol)
[1] 6 4 2 4 4 3 3 6 2 6
如果传递data.frame参数,它将返回修改后的data.frame。我将尝试修复此问题……希望对您有所帮助!
rowSums(t(t(d)==sol), na.rm=TRUE)
。R循环矢量进行比较。如果您d
是矩阵,矩阵中的列为例,则其简化为rowSums(d==sol, na.rm=TRUE)
。
我有一个特殊的问题,我必须计算逻辑向量中的真实语句的数量,这对我来说最有效。
length(grep(TRUE, (gene.rep.matrix[i,1:6] > 1))) > 5
因此,这采用了gene.rep.matrix对象的子集,并应用了逻辑测试,并返回了逻辑向量。该向量作为grep的参数放置,该参数返回任何TRUE条目的位置。然后,Length计算grep找到多少个条目,从而给出TRUE条目的数量。
table(c(FALSE))["TRUE"]
给人NA,不是0