11.1 히스토그램

히스토그램(Histogram)한 개의 연속형 변수를 일정한 구간 폭(binwidth)을 갖는 구간(bin)으로 분할하여, 각 구간의 빈도수를 막대 그래프로 시각화한 것입니다.

11.1.1 데이터 세트

이번 절에서는 먼저 ggplot2 패키지의 geom_histogram() 를 활용해서 히스토그램을 그리는 방법에 대해서 알아보겠습니다.

데이터는 MASS 패키지에 들어있는 Cars93 데이터 프레임 데이터 세트에서 가격(Price)과 자동차유형(Type) 변수를 활용하여 히스토그램을 그려보겠습니다.

library(ggplot2)         # 또는 library(tidyverse)
# Cars93 데이터 프레임 
library(MASS) 
str(Cars93)

11.1.2 기본 히스토그램

ggplot2 패키지를 library()로 호출한 후에 ggplot() 함수의 + geom_histogram() 함수를 사용하여 기본 값 옵션으로 히스토그램을 그리면 됩니다.

히스토그램을 그리는 기본적인 절차는 다음과 같습니다.

  • ggplot(Cars93, aes(x = Price)) : Cars93을 데이터 세트로 사용하며, aes( ) 함수 안에 x 축에 표시할 변수로 Price를 지정해 줍니다. 이 ggplot() 함수로 기본 그래프를 작성하지만 아무런 결과도 표시가 되지 않습니다.
  • + : 기본 그래프와 다음에 나올 그래프 관련 함수들을 연결해 줍니다.
  • geom_histogram() : 기본 그래프히스토그램 형태로 시각화 해줍니다.

이제 Cars93 데이터 세트에서 가격(Price) 변수를 기본적인 히스토그램으로 시각화해 보겠습니다.

# binwidth defaulted to range/30 
ggplot(Cars93, aes(x = Price)) +              # 그래프의 기본 틀을 설정합니다. 데이터와 X축의 변수를 지정합니다.
       geom_histogram()                     # 히스트로그램으로 표현합니다.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
기본 히스토그램

Figure 11.1: 기본 히스토그램

ggplot() 함수에 대한 자세한 사항은 ? ggplot을 참고하기 바랍니다.

Go Top

11.1.3 구간 폭의 기본값

위에 실행결과 콘솔창의 메시지를 보면 “stat_bin: binwidth defaulted to range/30. Use 'binwidth = x' to adjust this.”이라는 메시지가 아래 보이는데요, 이는 binwidth를 설정하지 않아서 range/30 디폴트 기준으로 binwidth를 계산해서 그렸다는 뜻입니다. 구간의 갯수(bins)는 기본 값이 30개입니다.

아래에 실제 범위(range)를 구해서 30으로 나누었더니 1.816 이었고, 이 값을 geom_histogram(binwidth = 1.816) 옵션값으로 입력해서 히스토그램을 그려보았더니 위와 같음을 알 수 있습니다.

library(MASS)

range(Cars93$Price)                             # Price 변수의 범위를 구합니다. (최솟값, 최댓값)
## [1]  7.4 61.9
diff(range(Cars93$Price))                       # (최댓값 - 최솟값) 을 구합니다.
## [1] 54
diff(range(Cars93$Price))/30                    # (최댓값 - 최솟값) / 30 을 구합니다. = 1.816
## [1] 1.8
ggplot(Cars93, aes(x=Price)) +                  # 그래프의 기본 틀을 설정합니다. 데이터와 X축을 지정합니다.
       geom_histogram(binwidth = 1.816) +       # 앞에서 구한 1,816을 구간의 폭으로 지정합니다.
       ggtitle("Binwidth=1.816 ; Default, range/30")    
히스토그램의 구간의 폭

Figure 11.2: 히스토그램의 구간의 폭

Go Top

11.1.4 구간의 폭 조정

히스토그램에서 중요하면서 어려운 문제 중의 하나가 bin 개수를 몇 개로 할 것인가, 다른 말로 binwidth로 구간의 폭을 얼마로 할 것인가 입니다.

bin 개수가 너무 많으면 (즉, binwidth가 너무 좁으면) 이빨빠진 머리빗처럼 데이터의 분포 모양을 파악하는데 부적절할 수가 있습니다. 반면에 bin 개수가 너무 적으면 (즉, binwidth가 너무 넓으면) 너무 많은 도수가 하나의 bin에 몰려서 막대기둥 한 두개만 덩그라니 서 있게 되어 이 또한 데이터의 분포 모양을 파악하는데 도움이 안되게 됩니다.

적절한 bin 개수를 선정하는게 중요합니다. 아래에서는 binwidth 값을 조절해 가면서 히스토그램을 그려보겠습니다.

그런데 여기서 ggplot() 함수의 결과를 h1과 같이 변수에 치환할 수 있습니다. 그리고 h1을 입력하면 바로 그래프가 출력되게 됩니다.

library(MASS)

# 다양한 폭으로 히스토그램 그리기 

h1 <- ggplot(Cars93, aes(x=Price)) +               
             geom_histogram(binwidth = 0.5) +      # 구간의 폭을 0.5로 설정합니다.
             ggtitle("Binwidth=0.5") 

h2 <- ggplot(Cars93, aes(x=Price)) +               
             geom_histogram(binwidth = 1.0) +      # 구간의 폭을 1.0으로 설정합니다.
             ggtitle("Binwidth=1.0") 
 
h3 <- ggplot(Cars93, aes(x=Price)) +               
             geom_histogram(binwidth = 1.5) +      # 구간의 폭을 1.5로 설정합니다.
             ggtitle("Binwidth=1.5") 
 
h4 <- ggplot(Cars93, aes(x=Price)) +               
             geom_histogram(binwidth = 1.816) +    # 구간의 폭을 1.816으로 설정합니다.
             ggtitle("Binwidth=1.816 ; Default, range/30") 
 
h5 <- ggplot(Cars93, aes(x=Price)) +  
             geom_histogram(binwidth = 5) +        # 구간의 폭을 5로 설정합니다.
             ggtitle("Binwidth=5") 
 
h6 <- ggplot(Cars93, aes(x=Price)) +  
             geom_histogram(binwidth = 10) +       # 구간의 폭을 10으로 설정합니다.
             ggtitle("Binwidth=10") 

##-----------------
## multiplot function by knitr and Jekyll (author of Cookbook for R)
## 아래 사용자정의 함수를 그대로 카피해서 사용하면 됩니다.
# install.packages("grid")
library(grid)

multiplot <- function(..., plotlist=NULL, file, cols=1, layout=NULL) {
  library(grid)
  
  # Make a list from the ... arguments and plotlist
  plots <- c(list(...), plotlist)
  
  numPlots = length(plots)
  
  # If layout is NULL, then use 'cols' to determine layout
  if (is.null(layout)) {
    # Make the panel
    # ncol: Number of columns of plots
    # nrow: Number of rows needed, calculated from # of cols
    layout <- matrix(seq(1, cols * ceiling(numPlots/cols)),
                     ncol = cols, nrow = ceiling(numPlots/cols))
  }
  
  if (numPlots==1) {
    print(plots[[1]])
    
  } else {
    # Set up the page
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(nrow(layout), ncol(layout))))
     
    # Make each plot, in the correct location
    for (i in 1:numPlots) {
      # Get the i,j matrix positions of the regions that contain this subplot
      matchidx <- as.data.frame(which(layout == i, arr.ind = TRUE))
      
      print(plots[[i]], vp = viewport(layout.pos.row = matchidx$row,
                                      layout.pos.col = matchidx$col))
    }
  }
}
##-----------------

# 하나의 페이지에 여러 개의 플롯을 그리기 : multiplot() 함수 이용
multiplot(h1, h2, h3, h4, h5, h6, cols=2)               # 6개의 그래프를 2개의 열로 나타냅니다.
히스토그램의 구간의 너비 조정

Figure 11.3: 히스토그램의 구간의 너비 조정

위에서 처럼 한개의 화면에 여러개의 그래프를 배열하기 위해서 multiplot() 함수(by knitr and Jekyll)를 사용하였습니다. binwidth = 5 일 때가 위의 6개 그래프 중에서는 상대적으로 가장 적합해 보이므로 아래 예제부터는 binwidth = 5 를 사용하겠습니다.

Go Top

11.1.5 구간의 수 조정

앞에서는 데이터를 구분할 때 데이터 구간의 폭(binwidth)으로 조정하였습니다. 이번에는 데이터를 구분하는 전체 구간의 수(bins)로 조절해 보겠습니다. bins의 기본 값은 30입니다.

library(MASS)

# 구간의 수 조정
b1 <- ggplot(Cars93, aes(x=Price)) +             
             geom_histogram(bins = 10)  +         # 구간의 수를 10개로 정합니다.
             ggtitle("Bins = 10")

b2 <- ggplot(Cars93, aes(x=Price)) +             
             geom_histogram(bins = 15)  +         # 구간의 수를 15개로 정합니다.
             ggtitle("Bins = 15")

b3 <- ggplot(Cars93, aes(x=Price)) +             
             geom_histogram(bins = 20)  +         # 구간의 수를 20개로 정합니다.
             ggtitle("Bins = 20")

b4 <- ggplot(Cars93, aes(x=Price)) +             
             geom_histogram(bins = 25)  +         # 구간의 수를 25개로 정합니다.
             ggtitle("Bins = 25")

# 하나의 페이지에 여러 개의 플롯을 그리기 : multiplot() 함수 이용
multiplot(b1, b2, b3, b4, cols=2)                 # 6개의 그래프를 2개의 열로 나타냅니다.
히스토그램의 구간 수 조정

Figure 11.4: 히스토그램의 구간 수 조정

자세한 사항은 ? geom_histogram 을 참고하기 바랍니다.

Go Top

히스토그램의 bin width를 수동으로 설정해주고, bin별로 색깔을 다르게 해서 히스토그램을 그려보겠습니다.

#----------------
# histogram with variable size of bin width and different colors per bins using ggplot2
#----------------
# sample data frame
mydf <- data.frame(var = c(1100, 10000, 100000, 190000, 110000, 220000, 550000, 701000, 790000))

# numeric notation for large numbers
options(scipen = 30)

library("ggplot2")

# fill color with different colors per bins
mydf$group <- ifelse(mydf $var < 10000, 1, 
                          ifelse(mydf $var < 100000, 2, 
                                 ifelse(mydf $var < 200000, 3, 
                                        ifelse(mydf $var < 500000, 4, 5))))

# breaks of bin
bins <- c(1000, 10000, 100000, 200000, 500000, 800000)

# draw histogram with variable size of bin width and different colors per bins
ggplot(mydf, aes(x= var)) +
  geom_histogram(data=subset(mydf, group==1), breaks = c(1000, 10000), fill="black") +
  geom_histogram(data=subset(mydf, group==2), breaks = c(10000, 100000), fill="yellow") +
  geom_histogram(data=subset(mydf, group==3), breaks = c(100000, 200000), fill="green") +
  geom_histogram(data=subset(mydf, group==4), breaks = c(200000, 500000), fill="blue") +
  geom_histogram(data=subset(mydf, group==5), breaks = c(500000, 800000), fill="red") +
  scale_x_continuous(breaks = bins, limits = c(1000, 800000)) +
  xlab("variable 1") + 
  ylab("count") +
  ggtitle("Histogram with different size of bin width and colors") + 
  theme(plot.title = element_text(hjust = 0.5, size = 14))

Go Top

11.1.6 색 지정

위의 히스토그램을 보면 거무튀튀하니 그다지 색깔이 아름답지는 않지요? 그러면 이번에는 색 채우기, 경계선 색 지정하기를 해보겠습니다.

library(MASS)

# 채우기 색, 경계선 색 : geom_histogram(binwidth, fill, colour) 
ggplot(Cars93, aes(x=Price)) +                   
       geom_histogram(binwidth=5,                
                      fill = "blue",             # 막대의 색을 "blue"로 설정합니다.
                      colour = "black") +        # 막대의 테두리 색을 "black"으로 설정합니다.
       ggtitle("히스토그램의 채우기 색과 테두리 색 지정")
히스토그램의 채우기 색과 테두리 색 지정

Figure 11.5: 히스토그램의 채우기 색과 테두리 색 지정

자세한 사항은 ? geom_histogram 을 참고하기 바랍니다.

Go Top

11.1.7 stat_bin() 함수의 이용

geom_*() 함수들은 기본적인 stat_*() 함수를 가지고 있습니다.4 args(geom_histogram)로 확인해 보면 geom_histogram() 함수는 stat = "bin"을 알고리즘으로 사용하고 있습니다.

geom_histogram() 함수의 경우에는 stat_bin() 함수가 여기에 해당하며, geom_histogram() 함수 대신에 stat_bin() 함수를 이용할 수 있습니다.

ggplot(Cars93, aes(x=Price)) +  
       stat_bin(binwidth = 5)       # 히스트로그램으로 표현합니다.
기본 히스토그램 : stat_bin() 함수

Figure 11.6: 기본 히스토그램 : stat_bin() 함수

자세한 사항은 ? stat_density()로 확인하기 바랍니다.

11.1.8 데이터 레이블 달기

stat_bin() 함수를 이용하여 데이터 레이블을 표시할 수 있습니다.

library(MASS)

# 채우기 색, 경계선 색 : geom_histogram(binwidth, fill, colour) 
ggplot(Cars93, aes(x=Price)) +                   
       geom_histogram(binwidth=5,                
                      fill = "blue",             # 막대의 색을 "blue"로 설정합니다.
                      colour = "black") +        # 막대의 테두리 색을 "black"으로 설정합니다.
       stat_bin(binwidth = 5, 
                geom = "text", 
                aes(label = ..count..), 
                color = "red",
                vjust = -0.5) +   # or position = position_stack(vjust = 0.5)) +
       ylim(c(0, 25)) +
       ggtitle("히스토그램에 데이터 레이블 달기")
히스토그램에 데이터 레이블 달기

Figure 11.7: 히스토그램에 데이터 레이블 달기

11.1.9 그룹별 히스토그램

일변량 연속형 데이터에 대한 그래프를 그룹별로 작성할 수도 있습니다.

예를 들어 지금까지 차량의 가격(Price)으로 히스토그램을 작성하였는데, 이를 요인형 변수인 차량의 유형(Type) 별로 작성할 수도 있습니다.

이를 위해서는 다음과 같은 3가지 방법으로 가능하며, 각각의 모수에 요인형 변수를 지정해 주는 것입니다.

  1. aes()함수에 colour, fill, group 등의 모수를 추가하는 방법입니다.
  2. facet_grid() 함수를 이용하는 방법입니다.
  3. facet_wrap() 함수를 이용하는 방법입니다.

11.1.9.1 aes() 함수의 모수 이용

aes() 함수에 추가할 수 있는 모수로 colour, fill, group 등이 있습니다.

  • colour = Type을 추가하면, 각 히스토그램의 막대의 테두리 색Type별로 구분이 되어 표시됩니다.

  • fille = Type을 추가하면 히스토그램의 막대가 Type 별로 색이 채워집니다. 이때는 geom_histogram() 함수에 colour = “white” 와 같이 테두리 색을 지정해 주는 것이 좋습니다.

  • group = Type을 추가하면 히스토그램이 Type별로 구분이 됩니다. 그러나, geom_histogram() 함수에 colour = “white” 와 같이 테두리 색을 지정해 주어야 확인이 가능합니다.

# 그룹별 히스토그램 그리기 : aes()에 모수 지정하기
# colour 모수에 Type 변수를 지정하기
ggplot(Cars93, 
       aes(x = Price, 
           colour = Type)) +                   # 막대를 채우는 색으로 요인형 변수를 지정합니다.
  geom_histogram(binwidth=5)
그룹별 히스토그램 : aes() 모수 이용

Figure 11.8: 그룹별 히스토그램 : aes() 모수 이용

# fill 모수에 Type변수를 지정하기
ggplot(Cars93, 
       aes(x = Price, 
           colour = Type,
           fill = Type)) +                     # 막대를 채우는 색으로 요인형 변수를 지정합니다.
  geom_histogram(binwidth=5, 
                 colour = "white")             # 테두리 선을 지정합니다.
그룹별 히스토그램 : aes() 모수 이용

Figure 11.9: 그룹별 히스토그램 : aes() 모수 이용

# group 모수에 Type변수를 지정하기
ggplot(Cars93, 
       aes(x = Price, 
           group = Type)) +                    # 막대가 Type별로 구분됩니다.
  geom_histogram(binwidth=5,
                 colour = "white")             # 구분된 부분의 테두리 색을 지정합니다.
그룹별 히스토그램 : aes() 모수 이용

Figure 11.10: 그룹별 히스토그램 : aes() 모수 이용

11.1.9.2 facet_grid() 함수 이용

자동차 유형별(Type)로 앞의 히스토그램을 비교하기 위해서는 facet_grid(Type ~ .) 또는 facet_grid(vars(Type))으로 지정하는 방법과 facet_grid( . ~ Type) 으로 지정하는 방법을 각각 살펴 보겠습니다.

library(MASS)

# Type 그룹별 히스토그램 그리기
# 요인(factor) 여부 확인, levels 확인 
class(Cars93$Type); levels(Cars93$Type)
## [1] "factor"
## [1] "Compact" "Large"   "Midsize" "Small"   "Sporty"  "Van"
# 요인/집단/그룹(factor)별로 나누어서 히스토그램 그리기 
ggplot(Cars93, aes(x=Price)) +                  
       geom_histogram(binwidth=5,               
                      fill = "blue",            
                      colour = "black") +       
       ggtitle("facet_grid(Type ~ .)") +  
       facet_grid(Type ~ .)                      # 히스토그램을 Type 별로 세로로 배열합니다.
그룹별 히스토그램 : facet_grid( Type ~ .)

Figure 11.11: 그룹별 히스토그램 : facet_grid( Type ~ .)

위의 히스토그램처럼 자동차의 유형(Type)인 ‘Compact,’ ‘Large,’ ‘Midsize,’ ‘Small,’ ‘Sporty,’ ‘Van’ 의 6개 유형별로 가격(Price)의 히스토그램을 그려보면 서로 한눈에 비교가 가능하니 매우 유용하다고 하겠습니다.

참고로, 위처럼 가로로 비교를 하는 것이 아니라 세로로 세워서 그래프를 그린 후에 비교를 하려면 + facet_grid(. ~ Type) 처럼 괄호안의 기입 순서를 바꾸어주면 됩니다.

단, 아래에 예시 그래프를 보면 알겠지만, 차종별로 가격의 분포를 비교하기에는 아래처럼 그래프를 그려서는 안되겠지요? 분석 목적에 맞게 가로로 비교할지, 세로로 비교할지 잘 선택해서 사용하시기 바랍니다.

library(MASS)

# 요인/집단/그룹(factor)별로 나누어서 히스토그램 그리기 
# 그룹 히스토그램
ggplot(Cars93, aes(x=Price)) +  
       geom_histogram(binwidth=5, fill = "blue", colour = "black") +  
       ggtitle(" facet_grid(. ~ Type)") +
       facet_grid(. ~ Type)                           # 히스토그램을 Type 별로 가로로 배열합니다.
그룹별 히스토그램 : facet_grid( . ~ Type)

Figure 11.12: 그룹별 히스토그램 : facet_grid( . ~ Type)

자세한 사항은 ? facet_grid 를 참고하기 바랍니다.

Go Top

11.1.9.3 facet_wrap() 함수 이용

한편, facet_wrap() 함수를 이용하여 각 자동차 유형(Type)별 히스트로그램을 작성할 수도 있습니다. 1 함수 대신에 facet_wrap(~ Type, ncol = 2)를 추가해 보겠습니다.

library(MASS)

# 요인/집단/그룹(factor)별로 나누어서 히스토그램 그리기 
# 그룹 히스토그램
ggplot(Cars93, aes(x=Price)) +  
  geom_histogram(binwidth=5, fill = "blue", colour = "black") +  
  ggtitle("facet_wrap() 함수의 사용") +
  facet_wrap(~ Type, ncol = 2)                         # 히스토그램을 Type 별로 2열로 배열합니다.
그룹별 히스토그램 : facet_wrap(~ Type)

Figure 11.13: 그룹별 히스토그램 : facet_wrap(~ Type)

자세한 사항은 ? facet_wrap을 참고하기 바랍니다.

Go Top

11.1.10 Theme의 사용

ggplot2 패키지는 8 가지의 그래프 테마(Complete Themes)를 제공하고 있습니다. 다음의 예는 theme_class() 함수를 사용하여 X축과 Y축의 서식을 지정하는 예를 보여 주고 있습니다. 또한 참고로 Y축의 값에 컴마(,)를 삽입하는 예도 포함하였습니다.

## Theme의 사용
ggplot(Cars93, aes(x=Price)) +  
  geom_histogram(binwidth=5, fill = "blue", colour = "white") +  
  ggtitle("Theme의 사용") +
ggplot2::theme_classic() +                                         # 그래프 테마 지정
  ggplot2::theme(axis.title.x = element_text(size  = 10, 
                                             face  = "italic", 
                                             color = "gray", 
                                             angle = 0, 
                                             vjust = 0.5),
                 axis.title.y = element_text(size  = 10, 
                                             face  = "bold.italic", 
                                             color = "gray", 
                                             angle = 0, 
                                             vjust = 0.5)) +       # X축과 Y축의 서식 스타일 지정
  ggplot2::scale_y_continuous(labels = scales::comma)              # Y 값의 천단위에 콤마 표시
히스토그램 : Theme의 사용

Figure 11.14: 히스토그램 : Theme의 사용

자세한 Theme의 사용 방법은 ? theme을 참고하기 바랍니다.

Go Top

연습문제

1. Cars93 데이터 세트에 있는 연속형 변수를 히스토그램으로 시각화 하려 합니다.

1-1. MPG.highway 변수에 대한 기본 히스토그램을 작성하시오.
ggplot(Cars93, aes(x = MPG.highway)) +
    geom_histogram() +
    ggtitle("기본 히스토그램 : MPG.highway")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

##### 1-2. MPG.highway 변수의 구간 폭(binwidth)을 2 로 하여 히스토그램을 작성하시오. {-}

ggplot(Cars93, aes(x = MPG.highway)) +
    geom_histogram(binwidth = 2) +
    ggtitle("MPG.highway 히스토드램 : binwidth = 2")

1-3. MPG.highway 변수의 구간 수(bins)를 15 로 하여 히스토그램을 작성하시오.
ggplot(Cars93, aes(x = MPG.highway)) +
    geom_histogram(bins = 15) +
    ggtitle("MPG.highway 히스토드램 : bins = 15")

1-4. MPG.highway 변수에 대한 기본 히스토그램에서 막대의 채우기 색을 “blue”로 테두리 색은 “yellow”로 지정하시오.
ggplot(Cars93, aes(x = MPG.highway)) +
    geom_histogram(fill = "blue",
                   colour = "yellow") +
    ggtitle("MPG.highway 히스토그램 : 색 지정하기")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

2. MPG.highway 변수에 대하여 자동차 유형(Type) 변수를 그룹으로 하여 그룹별 히스토그램을 작성하시오.

단,

  • aes() 함수를 이용하고, 이 함수에 fill = Type 을 모수로 입력하시오.
  • 구간의 수(bins =)는 10개로 조정한다.
  • geom_histogram() 함수에 colour = "white"를 모수로 입력하시오.
ggplot(Cars93, 
       aes(x = MPG.highway,
           fill = Type,
           colour = Type)) +
  geom_histogram(bins = 10,
                 colour = "white") +
  ggtitle("자동차 유형별 MPG.highway 히스토그램 : aes() 함수 이용")

Go Top


  1. stat_*() 함수에 대한 설명을 참고하기 바랍니다.↩︎