논리 형 벡터에서 TRUE 값을 계산하는 방법


160

R TRUE에서 논리 벡터 의 값 수를 계산하는 가장 효율적인 / 아이디 오마 틱 방법은 무엇입니까? 두 가지 방법을 생각할 수 있습니다.

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이 아닌 수 있습니다
요시 Farjoun

@YossiFarjoun 네, 그리고 그것은 내 대답에 있습니다. 이것이 작동하지 않는 이유입니다. 나의 해결책은sum(z, na.rm = TRUE)
Marek

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경우 가장 좋은 방법은 명확하게 사용하는 것 입니다. NAMarek이 제안한대로 값 을 확인할 수도 있습니다 .

NA 값과 which함수 에 관한 메모를 추가하려면 다음을 수행하십시오.

> which(c(T, F, NA, NULL, T, F))
[1] 1 4
> which(!c(T, F, NA, NULL, T, F))
[1] 2 5

이는 logical 만 검사 TRUE하므로 비논리적 값은 기본적으로 무시합니다.


BTW, 더크 응답의 타이밍 멋진 트릭이 있었다 : 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])약 10x 느리고 table(z)[TRUE]약 200x 느립니다 sum(z).

요약 sum(z)하면 입력하고 실행하는 것이 가장 빠릅니다.


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 = TRUEsum기능, 당신은 당신이 원하는 결과를 얻을 수 있습니다.

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

질문이 엄격하게 이론적인가, 논리 벡터에 관한 실제적인 문제가 있습니까?


퀴즈를 채점하려고했습니다. 신청 내에서 sum (youranswer == rightanswer)과 같은 일을합니다.
Jyotirmoy Bhattacharya

답변이 너무 길어서 이전 답변과 다르기 때문에 새로운 답변을 게시했습니다.
aL3xa

6

또 다른 옵션은 요약 기능을 사용하는 것입니다. 그것은 Ts, Fs 및 NA의 요약을 제공합니다.

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

1
또한 "TRUE"결과 만 얻으려면 (문자열로 출력되지만 "TRUE"도 출력에 포함) : summary(hival)["TRUE"];
마이클

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

나는 * 플라이 기능을 사용하여보다 우아한 방식 으로이 작업을 시도합니다. 내가 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 객체의 하위 집합을 가져 와서 논리 테스트를 적용하여 논리 벡터를 반환합니다. 이 벡터는 grep의 인수로 사용되며 TRUE 항목의 위치를 ​​반환합니다. 그러면 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.