如何计算逻辑向量中的TRUE值

时间:2010-02-03 09:03:38

标签: r

在R中,计算逻辑向量中TRUE值的数量的最有效/惯用方法是什么?我可以想到两种方式:

z <- sample(c(TRUE, FALSE), 1000, rep = TRUE)
sum(z)
# [1] 498

table(z)["TRUE"]
# TRUE 
#  498 
你更喜欢哪个?还有什么更好的吗?

8 个答案:

答案 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)

几周前我一直在做类似的事情。这是一个可能的解决方案,它是从头开始编写的,所以它是一种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。 我会尝试修复这个...希望它有所帮助!

答案 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
})