首页 文章

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

提问于
浏览
136

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

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

table(z)["TRUE"]
# TRUE 
#  498

你喜欢哪个?还有什么更好的吗?

7 回答

  • 11

    我刚才有一个特殊的问题,我必须从逻辑向量中计算真实语句的数量,这对我来说效果最好......

    length(grep(TRUE, (gene.rep.matrix[i,1:6] > 1))) > 5
    

    因此,它接受gene.rep.matrix对象的子集,并应用逻辑测试,返回逻辑向量 . 此向量作为参数放入grep,后者返回任何TRUE条目的位置 . 然后,Length计算grep找到的条目数,从而给出TRUE条目的数量 .

  • 0

    当逻辑向量包含 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值,您应该小心"table"解决方案 . 假设 z <- c(NA, FALSE, NA) 或只是 z <- c(FALSE, FALSE)

    table(z)["TRUE"] # gives you NA for both cases.
    
  • 77

    另一个未提及的选项是使用 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 ,因此它实际上忽略了非逻辑值 .

  • 143

    另一种方式是

    > 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) 是键入和执行最快的 .

  • 0

    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 ,但如果您在 sum 函数中传递 na.rm = TRUE ,您将获得所需的结果 .

    > sum(x)
    [1] NA
    > sum(x, na.rm=TRUE)
    [1] 43
    

    你的问题是严格的理论问题,还是你有一些关于逻辑向量的实际问题?

  • 6

    另一种选择是使用汇总功能 . 它给出了Ts,Fs和NA的总结 .

    > summary(hival)
       Mode   FALSE    TRUE    NA's 
    logical    4367      53    2076 
    >
    
  • 5

    几周前我一直在做类似的事情 . 这是一个可能的解决方案,它是从头开始编写的,所以它是一种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)
    }
    

    我'll try to do this in a more elegant manner with some *ply function. Notice that I didn' t把 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 . 我会尝试修复这个...希望它有所帮助!

相关问题