벡터에서 x 값을 가진 요소 수 계산


400

숫자로 구성된 벡터가 있습니다.

numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,
         453,435,324,34,456,56,567,65,34,435)

R이 값 x 가 벡터에 나타나는 횟수를 어떻게 계산할 수 있습니까?

답변:


505

당신은 사용할 수 있습니다 table():

> a <- table(numbers)
> a
numbers
  4   5  23  34  43  54  56  65  67 324 435 453 456 567 657 
  2   1   2   2   1   1   2   1   2   1   3   1   1   1   1 

그런 다음 하위 집합을 만들 수 있습니다.

> a[names(a)==435]
435 
  3

또는 더 편안하게 작업하려면 data.frame으로 변환하십시오.

> as.data.frame(table(numbers))
   numbers Freq
1        4    2
2        5    1
3       23    2
4       34    2
...

21
잠재적 인 부동 소수점 문제, 특히 테이블에서 숫자를 문자열로 강제 변환하는 것을 잊지 마십시오.
hadley

4
좋은 지적입니다. 이것들은 모두 정수이므로이 예제에서는 문제가되지 않습니까?
Shane

정확히. 테이블의 요소는 정수 클래스 class (table (numbers) [1])이지만 435는 부동 소수점 숫자입니다. 정수로 만들려면 435L을 사용할 수 있습니다.
Ian Fellows

@Ian-이 예제에서 435가 플로트 인 이유가 혼란 스럽다. 당신은 조금 명확하게 할 수 있습니까? 감사.
Heather Stark

4
a["435"]insetead 하지 a[names(a)==435]?
Pomber

262

가장 직접적인 방법은 sum(numbers == x)입니다.

numbers == xx가 발생하는 모든 위치에서 TRUE 인 논리 형 벡터를 생성하고, suming 일 때 논리 형 벡터를 숫자로 강제 변환하여 TRUE를 1로, FALSE를 0으로 변환합니다.

그러나 부동 소수점 숫자의 경우 다음과 같은 것을 사용하는 것이 좋습니다 sum(abs(numbers - x) < 1e-6).


1
부동 소수점 문제에 대한 좋은 지적. 그것은 내가 일반적으로 인정하는 것보다 내 엉덩이를 더 문다.
JD Long

3
@Jason은 질문에 직접 대답하지만 사람들은 x알려진 특정 값 대신 데이터의 모든 것에 대한 답변을 제공하는보다 일반적인 솔루션을 선호한다고 생각합니다 x. 공평하게, 그것은 원래의 질문에 관한 것이 었습니다. 아래 답변에서 언급했듯이 "모든 값이 아니라 하나의 값의 빈도를 알고 싶어하는 경우는 거의 없습니다 ..."
JBecker

62

아마 이런 식으로 할 것

length(which(numbers==x))

하지만 더 좋은 방법은

table(numbers)

10
table(numbers)sum(numbers==x)목록에서 다른 모든 숫자의 수를 계산하기 때문에 가장 쉬운 솔루션보다 훨씬 더 많은 작업을 수행 할 것입니다.
Ken Williams

1
테이블의 문제점은 더 복잡한 미적분학에 포함시키기가 더 어렵다는 것입니다. 예를 들어 데이터 프레임에서 apply ()를 사용하는 것
skan

38

패키지 도 count(numbers)있습니다 plyr. table제 생각 보다 훨씬 편리합니다 .


이것과 동등한 dplyr가 있습니까?
stevec

34

내가 선호하는 솔루션은을 사용 rle하여 값 ( x예 : 레이블 )과 길이 를 반환합니다. 이 길이는 해당 값이 순서대로 나타난 횟수를 나타냅니다.

rle와 결합 sort하면 값이 나타나는 횟수를 세는 매우 빠른 방법이 있습니다. 보다 복잡한 문제에 도움이 될 수 있습니다.

예:

> numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,453,435,324,34,456,56,567,65,34,435)
> a <- rle(sort(numbers))
> a
  Run Length Encoding
    lengths: int [1:15] 2 1 2 2 1 1 2 1 2 1 ...
    values : num [1:15] 4 5 23 34 43 54 56 65 67 324 ...

당신이 원하는 값이 표시되지 않습니다, 또는 나중에에 그 값을 저장해야하는 경우, 확인 adata.frame.

> b <- data.frame(number=a$values, n=a$lengths)
> b
    values n
 1       4 2
 2       5 1
 3      23 2
 4      34 2
 5      43 1
 6      54 1
 7      56 2
 8      65 1
 9      67 2
 10    324 1
 11    435 3
 12    453 1
 13    456 1
 14    567 1
 15    657 1

모든 값이 아닌 하나의 값의 빈도를 알고 싶어하는 경우는 드물며 rle은 모든 값을 세고 저장하는 가장 빠른 방법 인 것 같습니다.


1
이 대 테이블의 장점은 더 쉽게 사용할 수있는 형식으로 결과를 제공합니까? 감사
Heather Stark

@HeatherStark 두 가지 장점이 있다고 말할 것입니다. 첫 번째는 테이블 출력보다 더 쉽게 사용되는 형식이라는 것입니다. 두 번째는 때때로 전체 데이터 세트가 아닌 "행에서"요소의 수를 세고 싶어한다는 것입니다. 예를 들어, c(rep('A', 3), rep('G', 4), 'A', rep('G', 2), rep('C', 10))반환 values = c('A','G','A','G','C')하고 lengths=c(3, 4, 1, 2, 10)때로는 유용합니다.
JBecker

1
microbenchmark를 사용하면 table더 빠르지 만 when the vector is long(100000 시도) 짧아지면 약간 길어
보입니다 (

숫자가 많으면 정말 느려질 것입니다.
skan December

19

R에는 표준 기능이 있습니다.

tabulate(numbers)


단점은 tabulate0과 음수를 처리 할 수 ​​없다는 것입니다.
omar

2
그러나 다른 솔루션이 처리하지 않는 주어진 수의 0 인스턴스를 처리 할 수 ​​있습니다
Dodgie

환상적인 속도! omar가 말했듯이, 나타나지 않는 값은 0으로 표시되어 주파수 분포를 만들 때 매우 유용합니다. 를 사용하기 전에 상수를 추가하여 0 또는 음의 정수를 처리 할 수 ​​있습니다 tabulate. 참고 : sort일반적인 올바른 사용법을 위해 필요한 것 같습니다 : tabulate(sort(numbers)).
pglpm

11
numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435 453,435,324,34,456,56,567,65,34,435)

> length(grep(435, numbers))
[1] 3


> length(which(435 == numbers))
[1] 3


> require(plyr)
> df = count(numbers)
> df[df$x == 435, ] 
     x freq
11 435    3


> sum(435 == numbers)
[1] 3


> sum(grepl(435, numbers))
[1] 3


> sum(435 == numbers)
[1] 3


> tabulate(numbers)[435]
[1] 3


> table(numbers)['435']
435 
  3 


> length(subset(numbers, numbers=='435')) 
[1] 3

9

여기에 빠르고 더러운 방법이 있습니다.

x <- 23
length(subset(numbers, numbers==x))

9

이후에 출현 횟수를 계산하려면이 sapply기능 을 사용할 수 있습니다 .

index<-sapply(1:length(numbers),function(x)sum(numbers[1:x]==numbers[x]))
cbind(numbers, index)

산출:

        numbers index
 [1,]       4     1
 [2,]      23     1
 [3,]       4     2
 [4,]      23     2
 [5,]       5     1
 [6,]      43     1
 [7,]      54     1
 [8,]      56     1
 [9,]     657     1
[10,]      67     1
[11,]      67     2
[12,]     435     1
[13,]     453     1
[14,]     435     2
[15,]     324     1
[16,]      34     1
[17,]     456     1
[18,]      56     2
[19,]     567     1
[20,]      65     1
[21,]      34     2
[22,]     435     3

이것은 테이블보다 빠른 방법입니까?
가리 니


3

내가 찾은 또 다른 방법은 다음과 같습니다.

numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,453,435,324,34,456,56,567,65,34,435)
(s<-summary (as.factor(numbers)))

이것은 데이터 세트를 factor로 변환 한 다음 summary ()는 제어 총계 (고유 값의 개수)를 제공합니다.

출력은 다음과 같습니다

4   5  23  34  43  54  56  65  67 324 435 453 456 567 657 
2   1   2   2   1   1   2   1   2   1   3   1   1   1   1 

원하는 경우 데이터 프레임으로 저장할 수 있습니다.

as.data.frame (cbind (숫자 = 이름, 빈도 = s), stringsAsFactors = F, 행 이름 = 1 : 길이)

여기에서 row.names는 행 이름의 이름을 바꾸는 데 사용되었습니다. row.names를 사용하지 않으면 s의 열 이름이 새 데이터 프레임에서 행 이름으로 사용됩니다.

출력은 다음과 같습니다

     Number Freq
1       4    2
2       5    1
3      23    2
4      34    2
5      43    1
6      54    1
7      56    2
8      65    1
9      67    2
10    324    1
11    435    3
12    453    1
13    456    1
14    567    1
15    657    1

3

테이블을 사용하지만 다음과 비교하지는 않습니다 names.

numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435)
x <- 67
numbertable <- table(numbers)
numbertable[as.character(x)]
#67 
# 2 

table다른 요소의 개수를 여러 번 사용할 때 유용합니다. 카운트가 하나만 필요한 경우sum(numbers == x)


2

특정 요소를 세는 다른 방법이 있습니다

library(plyr)
numbers =c(4,23,4,23,5,43,54,56,657,67,67,435,453,435,7,65,34,435)

print(length(which(numbers==435)))

#Sum counts number of TRUE's in a vector 
print(sum(numbers==435))
print(sum(c(TRUE, FALSE, TRUE)))

#count is present in plyr library 
#o/p of count is a DataFrame, freq is 1 of the columns of data frame
print(count(numbers[numbers==435]))
print(count(numbers[numbers==435])[['freq']])

1

긴 벡터에서 비교적 빠르며 편리한 출력을 제공하는 방법은 사용하는 것입니다 lengths(split(numbers, numbers))( 끝에 있는 S 참고 lengths).

# Make some integer vectors of different sizes
set.seed(123)
x <- sample.int(1e3, 1e4, replace = TRUE)
xl <- sample.int(1e3, 1e6, replace = TRUE)
xxl <-sample.int(1e3, 1e7, replace = TRUE)

# Number of times each value appears in x:
a <- lengths(split(x,x))

# Number of times the value 64 appears:
a["64"]
#~ 64
#~ 15

# Occurences of the first 10 values
a[1:10]
#~ 1  2  3  4  5  6  7  8  9 10 
#~ 13 12  6 14 12  5 13 14 11 14 

결과는 단순히 명명 된 벡터입니다.
속도는 JBeckerrle제안한 속도와 비슷하며 매우 긴 벡터에서는 조금 더 빠릅니다. 다음은 제안 된 기능 중 일부가 포함 된 R 3.6.2 의 마이크로 벤치 마크입니다 .

library(microbenchmark)

f1 <- function(vec) lengths(split(vec,vec))
f2 <- function(vec) table(vec)
f3 <- function(vec) rle(sort(vec))
f4 <- function(vec) plyr::count(vec)

microbenchmark(split = f1(x),
               table = f2(x),
               rle = f3(x),
               plyr = f4(x))
#~ Unit: microseconds
#~   expr      min        lq      mean    median        uq      max neval  cld
#~  split  402.024  423.2445  492.3400  446.7695  484.3560 2970.107   100  b  
#~  table 1234.888 1290.0150 1378.8902 1333.2445 1382.2005 3203.332   100    d
#~    rle  227.685  238.3845  264.2269  245.7935  279.5435  378.514   100 a   
#~   plyr  758.866  793.0020  866.9325  843.2290  894.5620 2346.407   100   c 

microbenchmark(split = f1(xl),
               table = f2(xl),
               rle = f3(xl),
               plyr = f4(xl))
#~ Unit: milliseconds
#~   expr       min        lq      mean    median        uq       max neval cld
#~  split  21.96075  22.42355  26.39247  23.24847  24.60674  82.88853   100 ab 
#~  table 100.30543 104.05397 111.62963 105.54308 110.28732 168.27695   100   c
#~    rle  19.07365  20.64686  23.71367  21.30467  23.22815  78.67523   100 a  
#~   plyr  24.33968  25.21049  29.71205  26.50363  27.75960  92.02273   100  b 

microbenchmark(split = f1(xxl),
               table = f2(xxl),
               rle = f3(xxl),
               plyr = f4(xxl))
#~ Unit: milliseconds
#~   expr       min        lq      mean    median        uq       max neval  cld
#~  split  296.4496  310.9702  342.6766  332.5098  374.6485  421.1348   100 a   
#~  table 1151.4551 1239.9688 1283.8998 1288.0994 1323.1833 1385.3040   100    d
#~    rle  399.9442  430.8396  464.2605  471.4376  483.2439  555.9278   100   c 
#~   plyr  350.0607  373.1603  414.3596  425.1436  437.8395  506.0169   100  b  

중요한 것은 결 측값 수를 계산하는 유일한 함수 NAplyr::count입니다. 이들은 또한 다음을 사용하여 별도로 얻을 수 있습니다sum(is.na(vec))


1

이것은 1 차원 원자 벡터에 대한 매우 빠른 솔루션입니다. 에 의존 match()하므로 다음과 호환됩니다 NA.

x <- c("a", NA, "a", "c", "a", "b", NA, "c")

fn <- function(x) {
  u <- unique.default(x)
  out <- list(x = u, freq = .Internal(tabulate(match(x, u), length(u))))
  class(out) <- "data.frame"
  attr(out, "row.names") <- seq_along(u)
  out
}

fn(x)

#>      x freq
#> 1    a    3
#> 2 <NA>    2
#> 3    c    2
#> 4    b    1

알고리즘이 실행되지 않도록 조정할 수도 있습니다 unique().

fn2 <- function(x) {
  y <- match(x, x)
  out <- list(x = x, freq = .Internal(tabulate(y, length(x)))[y])
  class(out) <- "data.frame"
  attr(out, "row.names") <- seq_along(x)
  out
}

fn2(x)

#>      x freq
#> 1    a    3
#> 2 <NA>    2
#> 3    a    3
#> 4    c    2
#> 5    a    3
#> 6    b    1
#> 7 <NA>    2
#> 8    c    2

해당 출력이 필요한 경우 원래 벡터를 다시 반환하는 데 필요하지 않을 수도 있고 두 번째 열만 있으면됩니다. 파이프와 함께 한 줄로 얻을 수 있습니다.

match(x, x) %>% `[`(tabulate(.), .)

#> [1] 3 2 3 2 3 1 2 2

1
정말 좋은 해결책! 그것은 또한 내가 생각해 낼 수있는 가장 빠른 것입니다. u <-if (is.factor (x)) x [! duplicated (x)] else unique (x)를 사용하여 팩터 입력의 성능을 약간 향상시킬 수 있습니다.
Taz

0

이것은 명백한 의미 outer로 등식의 행렬을 얻기 위해 수행 할 수 있습니다 rowSums.
개수와 numbers동일한 데이터 집합 을 갖기 위해 data.frame이 먼저 생성됩니다. 별도의 입력 및 출력을 원하는 경우이 단계가 필요하지 않습니다.

df <- data.frame(No = numbers)
df$count <- rowSums(outer(df$No, df$No, FUN = `==`))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.