在R中,计算逻辑向量中TRUE
值的数量的最有效/惯用方法是什么?我可以想到两种方式:
z <- sample(c(TRUE, FALSE), 1000, rep = TRUE)
sum(z)
# [1] 498
table(z)["TRUE"]
# TRUE
# 498
你更喜欢哪个?还有什么更好的吗?
答案 0 :(得分:154)
当逻辑向量包含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
。
答案 1 :(得分:80)
未提及的另一个选项是使用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
是最好的方法。您可能还想检查Marek建议的NA
值。
只需添加关于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
,因此它实际上忽略了非逻辑值。
答案 2 :(得分:11)
另一种方式是
> length(z[z==TRUE])
[1] 498
虽然sum(z)
很好而且简短,但对我来说length(z[z==TRUE])
更能自我解释。虽然,我认为通过这样一个简单的任务,它并没有真正有所作为......
如果它是一个大型向量,您可能应该使用最快的解决方案,即sum(z)
。 length(z[z==TRUE])
慢约10倍,table(z)[TRUE]
比sum(z)
慢约200倍。
总结一下,sum(z)
是最快输入和执行的。
答案 3 :(得分:6)
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
您的问题是否严格理论化,或者您对逻辑向量有一些实际问题?
答案 4 :(得分:5)
另一种选择是使用汇总功能。它给出了Ts,Fs和NA的总结。
<html>
<body>
<b>Calendario Eventi</b><br>
<textarea id="stdout" style="width:90%;height:20em;padding:1em;border:1px black solid;background-color:aliceblue;"></textarea>
<script type="text/javascript">
function main() {
var films = joinData([ ar1, ar2, ar3 ]);
document.getElementById('stdout').value = JSON.stringify( films, null, ' ' );
}
function joinData( data ) {
var i, obj={};
for(i=0; i<data.length; i++) {
obj["day" + (1 + i ) ] = data[i];
}
return obj;
}
// EXAMPLE DATA: Films today, tomorrow, ...
var ar1 = [
{
"titolo": " Child 44 – Il bambino numero 44 ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/Child-44-trailer-italiano-e-locandina-del-thriller-con-Gary-Oldman-e-Tom-Hardy-2-150x214.jpg"
},
{
"titolo": " Run All Night – Una notte per sopravvivere ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/locandina2-150x214.jpg"
},
{
"titolo": " Ritorno al Marigold Hotel ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/36366-150x214.jpg"
},
{
"titolo": " I 7 nani ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/xHIrTDXTLZF1jBd7CQNf-150x214.jpg"
}
];
var ar2 = [
{
"titolo": " I 7 nani ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/xHIrTDXTLZF1jBd7CQNf-150x214.jpg"
},
{
"titolo": " Adaline – L’eterna giovinezza ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/adaline-poster-150x214.jpg"
},
{
"titolo": " Avengers: Age of Ultron – 2D ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/ultron.poster-2-150x214.jpg"
},
{
"titolo": " Fast and Furious 7 ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/49946-150x214.jpg"
}
];
var ar3 = [
{
"titolo": " The Gunman ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/RIBqwqVPwUp6VIWeRZlS-150x214.jpg"
},
{
"titolo": " Doraemon il film ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/doraemon-il-film-le-avventure-di-nobita-e-dei-cinque-esploratori_notizia-2-150x214.jpg"
},
{
"titolo": " Child 44 – Il bambino numero 44 ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/Child-44-trailer-italiano-e-locandina-del-thriller-con-Gary-Oldman-e-Tom-Hardy-2-150x214.jpg"
},
{
"titolo": " Run All Night – Una notte per sopravvivere ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/locandina2-150x214.jpg"
},
{
"titolo": " Ritorno al Marigold Hotel ",
"locandina": "http://www.metropoliscinemas.it/wp-content/uploads/36366-150x214.jpg"
}
];
main();
</script>
</body>
</html>
答案 5 :(得分:0)
主要思想是编写一个需要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。 我会尝试修复这个...希望它有所帮助!
答案 6 :(得分:0)
我只是遇到了一个特殊的问题,我必须从逻辑向量中计算出真实语句的数量,这对我来说效果最好......
length(grep(TRUE, (gene.rep.matrix[i,1:6] > 1))) > 5
所以这需要gene.rep.matrix对象的一个子集,并应用逻辑测试,返回逻辑向量。此向量作为参数放入grep,后者返回任何TRUE条目的位置。然后,Length计算grep找到的条目数,从而给出TRUE条目的数量。
答案 7 :(得分:0)
还有一个名为bit
的软件包,专门用于快速布尔运算。如果您有很大的向量或需要执行许多布尔运算,则它特别有用。
z <- sample(c(TRUE, FALSE), 1e8, rep = TRUE)
system.time({
sum(z) # 0.170s
})
system.time({
bit::sum.bit(z) # 0.021s, ~10x improvement in speed
})