'dplyr 패키지를 사용해서 그룹별 행의 개수 세기'에 해당되는 글 1건

  1. 2016.10.08 [R] dplyr 패키지를 사용해서 그룹별 행의 개수 세기 (counting up rows by group using dplyr) : summarise(n=n()), tally(), count() (4)

그동안 R dplyr package 의 기본 함수와 chaining operator (%>%) 에 대해서 알아보았습니다.

이번 포스팅에서는 R dplyr package를 사용해서 그룹별로 행의 개수 세기 (counting rows up by group using dplyr package)를 해보겠습니다.  counting 하는 것은 기본 중의 기본이라서 탐색적분석(Exploratory Data Analysis) 할 때 수시로 사용하므로 알아두면 유용하겠지요?!

혹시 chaining operator (%>%, shift+ctr+M) 에 대해서 모르는 분은 http://rfriend.tistory.com/236 포스팅을 참고하세요.  

 R dplyr package 의 summarise(n = n()), summarise(dist_n = distinct_n(factor)), tally(), count() 함수에 대해서 하나씩 예를 들면서 설명하겠습니다.  summarise(n = n()), summarise(dist_n = distinct_n(factor)), tally() 함수는 group_by()를 chaining 해서 사용하며, 마지막의 count() 함수만 group_by() chaining 없이 사용합니다.

 

[ 그룹별로 행의 개수 세기 (counting rows up by group using dplyr package) ]

 

예시에 사용할 데이터는 MASS package에 내장되어 있는 Cars93 데이터 프레임입니다.

 ##--------------------------------------------------
## counting things up by group, using dplyr package
##--------------------------------------------------

library(dplyr)
library(MASS)

str(Cars93)

 

차종(Type)별로 행의 개수 (차량의 개수)를 세어보겠습니다.

 
'data.frame':	93 obs. of  28 variables:
 $ Manufacturer      : Factor w/ 32 levels "Acura","Audi",..: 1 1 2 2 3 4 4 4 4 5 ...
 $ Model             : Factor w/ 93 levels "100","190E","240",..: 49 56 9 1 6 24 54 74 73 35 ...
 $ Type              : Factor w/ 6 levels "Compact","Large",..: 4 3 1 3 3 3 2 2 3 2 ...
 $ Min.Price         : num  12.9 29.2 25.9 30.8 23.7 14.2 19.9 22.6 26.3 33 ...
 $ Price             : num  15.9 33.9 29.1 37.7 30 15.7 20.8 23.7 26.3 34.7 ...
 $ Max.Price         : num  18.8 38.7 32.3 44.6 36.2 17.3 21.7 24.9 26.3 36.3 ...
 $ MPG.city          : int  25 18 20 19 22 22 19 16 19 16 ...
 $ MPG.highway       : int  31 25 26 26 30 31 28 25 27 25 ...
 $ AirBags           : Factor w/ 3 levels "Driver & Passenger",..: 3 1 2 1 2 2 2 2 2 2 ...
 $ DriveTrain        : Factor w/ 3 levels "4WD","Front",..: 2 2 2 2 3 2 2 3 2 2 ...
 $ Cylinders         : Factor w/ 6 levels "3","4","5","6",..: 2 4 4 4 2 2 4 4 4 5 ...
 $ EngineSize        : num  1.8 3.2 2.8 2.8 3.5 2.2 3.8 5.7 3.8 4.9 ...
 $ Horsepower        : int  140 200 172 172 208 110 170 180 170 200 ...
 $ RPM               : int  6300 5500 5500 5500 5700 5200 4800 4000 4800 4100 ...
 $ Rev.per.mile      : int  2890 2335 2280 2535 2545 2565 1570 1320 1690 1510 ...
 $ Man.trans.avail   : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 1 1 1 1 1 ...
 $ Fuel.tank.capacity: num  13.2 18 16.9 21.1 21.1 16.4 18 23 18.8 18 ...
 $ Passengers        : int  5 5 5 6 4 6 6 6 5 6 ...
 $ Length            : int  177 195 180 193 186 189 200 216 198 206 ...
 $ Wheelbase         : int  102 115 102 106 109 105 111 116 108 114 ...
 $ Width             : int  68 71 67 70 69 69 74 78 73 73 ...
 $ Turn.circle       : int  37 38 37 37 39 41 42 45 41 43 ...
 $ Rear.seat.room    : num  26.5 30 28 31 27 28 30.5 30.5 26.5 35 ...
 $ Luggage.room      : int  11 15 14 17 13 16 17 21 14 18 ...
 $ Weight            : int  2705 3560 3375 3405 3640 2880 3470 4105 3495 3620 ...
 $ Origin            : Factor w/ 2 levels "USA","non-USA": 2 2 2 2 2 1 1 1 1 1 ...
 $ Make              : Factor w/ 93 levels "Acura Integra",..: 1 2 4 3 5 6 7 9 8 10 ...
 $ sub_yn            : num  0 0 0 0 0 0 0 0 0 0 ...

 

 

자, 이제 dplyr 패키지를 사용해서 실습을 해보시지요.

 

(1)  dataframe %>% group_by(factor) %>% summarise(n = n())

먼저 summarise(n = n()) 함수입니다. group_by() 와 함께 chaining 해서 사용하는 예시입니다.

 

# using summarise(n = n()) in {dplyr} package
Cars93 %>%
  group_by(Type) %>%
  summarise(n = n())

 

 

# A tibble: 6 x 2
     Type     n
   <fctr> <int>
1 Compact    16
2   Large    11
3 Midsize    22
4   Small    21
5  Sporty    14
6     Van     9

 

 

 

 (2) dataframe %>% group_by(factor) %>% summarise(n = n(), n_dist = n_distinct())

차종(Type)별로 자동차 대수(행의 개수)와 더불어서, 차종별로 유일한 제조회사(Manufacturer)의 개수를 세어서 n_distinct_maker 라는 새로운 변수를 추가해보겠습니다.

 

# adding the number of distinct manufacturers
# by using multiple summaries inside summarise()
# like summarize(n = n(), n_distinct = n_distinct())
Cars93 %>%
  group_by(Type) %>%
  summarize(n = n(),
            n_distinct_maker = n_distinct(Manufacturer)) 

 

 

# A tibble: 6 x 3
     Type     n       n_distinct_maker
   <fctr> <int>            <int>
1 Compact    16               15
2   Large    11               10
3 Midsize    22               20
4   Small    21               16
5  Sporty    14               12
6     Van     9                8

 

 

 

 (3) dataframe %>% group_by(factor) %>% tally()

 R dplyr에는 summarise(n = n()) 함수와 동일한 기능, 동일한 결과를 반환하는 또 다른 함수로 tally() 가 있습니다.  group_by() 와 함께 chaining 해서 사용합니다.

 

# using tally() in {dplyr} package
Cars93 %>%
  group_by(Type) %>%
  tally()

 

 

# A tibble: 6 x 2
     Type     n
   <fctr> <int>
1 Compact    16
2   Large    11
3 Midsize    22
4   Small    21
5  Sporty    14
6     Van     9

 

 

 (4) dataframe %>% count(factor)

마지막으로 소개할 count(factor) 함수는 group_by(factor) chaining 없이 사용합니다.  위의 3개 보다 좀더 간단하긴 한데요, 해석이나 가독성 면에서 group_by() 가 들어가게 프로그램 짜는 것을 더 선호하는 사용자도 있을 듯 합니다. 

 

# using count() in {dplyr} package}
Cars93 %>%
  count(Type) # doing both grouping and counting (no need for group_by())

 

 

# A tibble: 6 x 2
     Type     n
   <fctr> <int>
1 Compact    16
2   Large    11
3 Midsize    22
4   Small    21
5  Sporty    14
6     Van     9

 

 


 

참고로, dplyr 패키지 말고도 {base} package의 table() 함수나, {sqldf} package의 sqldf() 함수를 사용해도 그룹별 관측치 개수 세기가 가능합니다.  아래 참고하세요.

 

(대안 1) {base} package의 table() 함수

counting 결과 제시 포맷이 위의 dplyr 패키지를 사용했을 때와는 다릅니다.  dplyr 패키지를 사용한 그룹별 행의 개수 세기에서는 차종(Type)이 별도 행, count 개수 n이 별도 행으로 제시가 되었었는데요, base 패키지의 table() 함수는 아래의 예시처럼 옆으로 차종이 죽~ 늘어서 있습니다.

 

## alternative : table()

# using table() in {base} package
table(Cars93$Type)

 

 

Compact   Large Midsize   Small  Sporty     Van 
     16      11      22      21      14       9 

 

 

table() 분석 결과는 데이터 프레임이 아니라 'table'입니다.

> str(table(Cars93$Type))
 'table' int [1:6(1d)] 16 11 22 21 14 9
 - attr(*, "dimnames")=List of 1
  ..$ : chr [1:6] "Compact" "Large" "Midsize" "Small" ...

 

 

(대안 2) {sqldf} 패키지의 sqldf() 함수

 

## alternative : sqldf() 

# using {sqldf} package
install.packages("sqldf")
library(sqldf)
sqldf('
      select Type, count(*) as n
      from Cars93
      group by Type
      order by Type
      ')

 

 
     Type  n
1 Compact 16
2   Large 11
3 Midsize 22
4   Small 21
5  Sporty 14
6     Van  9

 

 

sqldf 패키지의 sqldf() 함수에 대한 좀더 자세한 사용법은 http://rfriend.tistory.com/79  포스팅을 참고하세요.

많은 도움 되었기를 바랍니다.

 

이번 포스팅이 도움이 되셨다면 아래의 '공감 ~ ♡'를 눌러주세요. ^^

Posted by R Friend R_Friend

댓글을 달아 주세요

  1. 궁금해요 2016.10.14 18:16  댓글주소  수정/삭제  댓글쓰기

    안녕하세요. 블로그에서 많은 정보를 얻어가고 있습니다.

    제 질문은 다양한 변수가 존재하는 데이터에서 (예: 변수 x,y가 있는 데이터 프레임)

    x의 변수를 기준으로 변수내 행에서 동일한 값들에 대응되는 y의 변수값들을 더하고 싶은데.. 다양한 방법중 for문과 if문을 이용하여 만들어보았는데 에러가 나며 잘 돌아가지 않습니다.

    혹시 도와 주실수 있으신가요?
    x=c("ad001","ad001","ad001","ad002","ad002","ad002","ad003","ad003","ad003")
    y=c(1,1,3,4,5,1,3,2,4)
    total=data.frame(x,y)
    for(j in length(unique(total$x))-1){
    for(i in nrow(total)-1){
    ifelse(total$x[i]==total$x[i+1],c<-c+total$y[i],data[j]<-c)
    i=i+1}
    j=j+1}
    도와주시면 정말 감사하겠습니다.

    • R Friend R_Friend 2016.10.15 00:50 신고  댓글주소  수정/삭제

      안녕하세요 '궁금해요' 님,

      여러가지 방법들이 있으며, 간단하게
      (1) dplyr 패키지를 사용한 방법, (2) loop programming 사용한 방법을 각각 소개해보면요,

      ## making dataset

      x=c("ad001","ad001","ad001","ad002","ad002","ad002","ad003","ad003","ad003")
      y=c(1,1,3,4,5,1,3,2,4)
      total=data.frame(x,y)


      # (1) summation of 'y' by group 'x' using dplyr package

      total %>% group_by(x) %>% summarise(y_sum = sum(y))


      ## (2) summation of 'y' by group 'x' using programming

      group_x <- unique(total$x)
      group_x # ad001 ad002 ad003

      group_sum <- data.frame() # making null vector
      for (i in 1:length(group_x)){
      group_sum[i,1] = group_x[i]
      group_sum[i,2] = sum(subset(total, select = c("y"), subset = (x == group_x[i])))
      }

      names(group_sum) <- c("group_x", "sum_y")
      group_sum

      많은 도움 되었기를 바랍니다.

  2. 궁금해요 2016.10.17 09:11  댓글주소  수정/삭제  댓글쓰기

    정말 감사드립니다. 많은 도움이 되었습니다.