論理ベクトルのTRUE値をカウントする方法


160

R TRUEで、論理ベクトルの値の数を数える最も効率的/慣用的な方法は何ですか?私は2つの方法を考えることができます:

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

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

どっちがいい?さらに良いものはありますか?

回答:


174

論理ベクトルに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を与えます。


table(c(FALSE))["TRUE"]NAではなく0を与える
Yossi Farjoun

@YossiFarjounはい、そしてそれは私の答えです。これが機能しない例です。私の解決策はsum(z, na.rm = TRUE)
マレク

84

言及されていない別のオプションは使用すること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マレクが提案したように、値を確認することもできます。

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論理値のみをチェックするため、基本的に非論理値は無視されることに注意してください。


ところで、ディルクの答えのタイミングとの素敵なトリックがあった:stackoverflow.com/questions/1748590/revolution-for-r/...
マレク

12

別の方法は

> length(z[z==TRUE])
[1] 498

一方でsum(z) いいと短いです、私のためにlength(z[z==TRUE])もっと自己説明です。しかし、私はこのような単純なタスクでは実際には違いはないと思います...

大きなベクトルの場合、おそらく最速のソリューションであるを使用する必要がありsum(z)ます。length(z[z==TRUE])は約10倍遅く、table(z)[TRUE]約200 倍遅くなりsum(z)ます。

まとめるsum(z)と、入力して実行するのが最速です。


6

which特に行列を操作する場合(引数を確認?whichしてarr.indください)は、良い代替案です。しかし、を論理ベクトルで処理できる引数があるsumため、に固執することをお勧めします。例えば:na.rmNA

# 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

あなたの質問は厳密に理論的なものですか、それとも論理ベクトルに関する実際的な問題がありますか?


クイズを採点しようとしていました。適用内でsum(youranswer == rightanswer)のようなことを行う。
Jyotirmoy Bhattacharya、2010

返事が長すぎるので、前回とは違うので、新しい回答を投稿しました。
aL3xa 2010

6

別のオプションは、集計関数を使用することです。Ts、Fs、NAの概要を示します。

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

1
さらに、「TRUE」の結果のみを取得するには(これは文字列として出力されますが、出力には「TRUE」も含まれます)summary(hival)["TRUE"]
マイケル

0

私は数週間前に同じようなことをしてきました。考えられる解決策は次のとおりです。ゼロから作成されているため、ベータ版などのようなものです。私はコードからループを削除することでそれを改善しようとします...

主なアイデアは、2つ(または3つ)の引数を取る関数を記述することです。1つ目は、data.frameアンケートから収集したデータを保持するa で、2つ目は、正解の数値ベクトルです(これは、単一選択アンケートにのみ適用されます)。または、最終スコアを含む数値ベクトル、またはスコアが埋め込まれたdata.frameを返す3番目の引数を追加できます。

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

0

私は論理ベクトルから真のステートメントの数を数えなければならないという特定の問題を抱えていましたが、これが私にとって最もうまくいきました...

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

したがって、これはgene.rep.matrixオブジェクトのサブセットを受け取り、論理テストを適用して論理ベクトルを返します。このベクトルは、任意のTRUEエントリの場所を返すgrepへの引数として配置されます。次に、Lengthは、grepが検出したエントリの数を計算し、TRUEエントリの数を示します。


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
})
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.