2010-02-03 30 views
117

在R中,計算邏輯向量中TRUE值的數量的最有效/慣用的方法是什麼?我可以想到兩種方法:如何計算邏輯向量中的TRUE值

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

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

你更喜歡哪一種?有什麼更好的嗎?

回答

122

當邏輯向量包含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) 

所以我認爲安全是

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"] # gives you NA for both cases. 
10

另一種方式是

> 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)是鍵入和執行最快的。

71

尚未提到的另一種選擇是使用which

length(which(z)) 

只是實際提供一些背景的「這是更快的問題」,它總是最容易只是爲了測試自己。我做了很多比較大的載體:所以很明顯使用sum在這種情況下,最好的辦法

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 

。 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檢查,所以它基本上忽略非邏輯值。

+0

BTW,有一個好的技巧與時機在德克的回答:http://stackoverflow.com/questions/1748590/revolution-for-r/1748932#1748932 – Marek 2010-02-03 16:22:51

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結果,但如果你在sum功能通過na.rm = TRUE,你會得到你想要的結果。

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

你的問題是嚴格的理論,還是你有一些關於邏輯向量的實際問題?

+0

我試圖年級測驗。在應用中做類似sum(youranswer == rightanswer)的事情。 – 2010-02-05 06:55:21

+0

我的回覆太長了,所以我發佈了一個新的答案,因爲它與之前的答案不同。 – aL3xa 2010-02-05 18:25:00

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

單行:'rowSums(t(t(d)== sol),na.rm = TRUE)'。 R回收載體進行比較。如果你的'd'是矩陣的情況下,它的列簡化爲'rowSums(d == sol,na.rm = TRUE)'。 – Marek 2010-02-10 12:31:23

0

我剛喝了一個特別的問題,我必須指望從邏輯向量真實的陳述的數量,這個工作最適合我......

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

所以這需要基因的一個子集.rep.matrix對象,並應用邏輯測試,返回一個邏輯向量。這個向量作爲grep的一個參數,它返回任何TRUE條目的位置。長度然後計算grep找到的條目數,從而給出TRUE條目的數目。

4

另一種選擇是使用匯總功能。它給出了Ts,Fs和NAs的總結。

> summary(hival) 
    Mode FALSE TRUE NA's 
logical 4367  53 2076 
> 
+1

此外,僅獲得「TRUE」結果(將以字符串形式輸出,但在輸出中也包含「TRUE」):'summary(hival)[「TRUE」]'; – michael 2016-06-18 03:59:53