본문 바로가기
개발, IT

[R프로그래밍] R을 이용해 바차트(막대그래프)와 히스토그램(도수분포표) 정복하기

by Nabi™ 2018. 7. 27.

"히스토그램과 바차트의 차이는 무엇인가?", 이 질문에 바로 대답할 수 있으신가요? 히스토그램은 우리말로 하면 도수분포표입니다. 반면, 바차트는 우리말로 막대그래프입니다. 이름만 다를 뿐 그게 그거 아닌가 할 수도 있겠지만 그 쓰임에는 분명한 차이가 있습니다. 히스토그램(이하 도수분포표)은 분포(Distribution)을 표현하는데 사용하는 반면 바차트(이하 막대그래프)는 데이터를 분류(Category)하는데 사용됩니다. 아래 그림을 살펴보시죠.

 

 

올해 책을 30권 읽었다고 가정해 보겠습니다. 이 읽은 책에 대한 데이터를 정리하는 방법은 여러가지가 있을 것입니다. 소설, 인문학, 경영서, IT, 예술 등과 같이 장르별로 읽은 책의 권수를 정리 할 수도 있고, 책의 가격대를 비교해 볼 수도 있습니다. 전자는 막대그래프로 후자는 도수분포표으로 표시하면 됩니다. 막대그래프의 목적은 데이터의 비교입니다. 따라서 분류기준을 잘 만드는 것이 중요합니다. 막대그래프로 데이터를 비교할 때 각 항목의 폭은 모두 같게 표시하고 막대 사이의 여유도 좀 두면 시각적으로 편안합니다. 비교되는 값은 막대의 높이로 나타냅니다. 반면, 도수분포표의 목적은 데이터의 분포를 표시하는 것입니다. 각 막대의 면적의 합은 모두 1이고, 막대의 폭역시 같을 필요는 없습니다. 도수분포표에서 중요한 정보는 막대의 면적입니다.


이제 R을 이용해서 막대그래프와 도수분포표을 만들어 보도록 하겠습니다. 여기서 사용할 데이터는 PGA 투어 선수들의 키입니다. 상단의 데이터를 활용하시기 바랍니다. 데이터는 NewsOK에서 추출해서 단위를 변환하고 각 선수들의 대륙에 대한 정보를 추가했습니다. 키가 불분명한 선수는 제외했습니다. <사진:PGA TOUR>


이 포스팅에 대한 아이디어는 비주얼라이즈 디스와 데이터 포인트로 친숙한 네이선 야우의 'How to Read Histograms and Use Them in R'에서 얻었습니다. 이 포스팅에 설명되지 않은 코드에 대한 자세한 설명은 R매뉴얼이나 'help()' 명령어를 참고하시기 바랍니다.


PGA 투어에 활동중인 한국 선수들의 키로 가로막대그래프 그리기

우선, 데이터를 읽어와 PGA투어에서 활동 중인 한국 선수들의 키를 가로 막대그래프를 만듭니다. 여기서 사용한 subset()함수는 불러온 데이터셋에서 특정조건을 만족하는 데이터만으로 새로운 데이터 셋을 만들어 주는 역할을 합니다. 즉, 전체 PGA 선수들의 데이터에서 국적(Country)이 한국(KOR)인 선수들의 데이터로 새로운 데이터 셋을 만드는 것입니다. 데이터 셋을 만든 후 데이터를 키를 기준으로 정렬했습니다. 이제 한국 선수들의 키로 기본적인 기술통계량을 만듭니다.


한국선수들의 키는 165cm에서 191cm에 분포해 있으며 평균은 177.9cm로 나타납니다. 막대그래프를 그릴 차례입니다. 그래프에 들어갈 기본적인 세팅을 합니다. par() 함수는 다양한 파라미터를 통해 그래프를 그릴 때 필요한 설정사항을 미리 지정합니다. 여기서 사용한 파라미터 'mar'는 그래프의 마진을 설정합니다. 순서는 하, 좌, 상, 우 순입니다. 막대그래프는 barplot() 함수를 통해 그릴 수 있습니다. 가로 막대그래프를 그리기 위해 'horiz=TRUE'라는 인수를 사용하였고, 그래프를 그릴 대상은 Korean이라는 데이터셋을 오름차순으로 정렬한 Korean.o라는 데이터 셋입니다. 정렬은 오름차순이 디폴트입니다. 그래프는 맨 처음 데이터부터 쌓아 올리는 형태로 그리기 때문에 내림차순처럼 보이게 됩니다.

# 데이터 읽어오기
players <- read.csv("E:/RawData/PGA_Players_Converted.csv",
                             stringsAsFactors=FALSE)
 
# PGA Tour에서 활동중인 한국 선수들의 키로 가로 막대그래프 만들기
Korean <- subset(players, Country=="KOR")
Korean.o <- Korean[order(Korean$Ht),]
summary(Korean$Ht)
par(mar=c(5,10,5,5))
barplot(Korean.o$Ht, names.arg=Korean.o$Players, horiz=TRUE, border=NA,
            xlim=c(0, 200), las=1, main="Heights of Korean PGA Tour Players")



대륙별 PGA 투어 선수들의 평균키로 세로막대그래프 그리기

대륙별 선수들의 평균키로 세로막대그래프를 그려보겠습니다. aggregate()라는 새로운 함수가 나왔습니다. aggregate()함수는 데이터셋의 요약 통계량을 계산해 주는 함수입니다. 여기서는 포지션별 키의 평균값을 계산하였습니다.


# 대륙별 선수들의 평균키로 세로 막대그래프 만들기
par(mar=c(5,5,5,5))
avgHeights <- aggregate(Ht ~ Continent, data=players, mean)
avgHeights.o <- avgHeights[order(avgHeights$Ht, decreasing=FALSE),]
avgHeights.o <- avgHeights[order(avgHeights$Ht, decreasing=FALSE),]
barplot(avgHeights.o$Ht, ylim=c(0, 200),names.arg=avgHeights.o$Continent,
             border=NA, las=1)

PGA 투어선수들 키로 도수분포표 만들기

PGA 투어 선수들의 키로 도수분포표를 만들어 보겠습니다. 도수분포표는 hist()함수를 사용합니다. 기본적으로 도수분포표를 그릴 변수를 설정하고, 나머지 파라미터를 주게 됩니다. 간격, 밀도, 그래프의 색상, 레이블 등 다양한 파라미터를 사용할 수 있습니다. 파라미터 ylim은 y축의 범위를 설정합니다. col은 그래프의 색상을 지정합니다. 색상은 "red", "blue", "pink"와 같이 색상명을 사용할 수도 있고, RGB컬러를 알고 있다면 "#000000"에서 "#FFFFFF"까지의 RGB 컬러를 사용할 수도 있습니다. PGA투어 선수들의 키는 180cm에서 185cm사이에 가장 많이 분포해있는 것을 확인할 수 있습니다.


# 선수 키에 대한 히스토그램 만들기
hist(players$Ht, main="PGA Players Heights", ylim=c(0, 250), xlab="cm",
      col="#80fd3d")

도수분포표의 분포 범위 조정하기

키의 분포를 조정해 보겠습니다. breaks 파라미터는 분포를 만들 범위를 지정합니다. par()함수에 mfrow라는 파라미터는 그래프가 그려질 공간을 나누는 역할을 합니다. 여기서 사용한 mfrow=c(1,3)의 의미는 그래프가 그려질 공간을 세로로 3등분하라는 뜻입니다. breaks를 1, 2, 5로 조정해가면서 히스토그램이 어떻게 그려지는지 확인해 보겠습니다.


# 선수 키에 대한 히스토그램 - 키의 분포 범위를 조정
par(mfrow=c(1,3), mar=c(3, 3, 3, 3))
hist(players$Ht, main="PGA Players Heights", ylim=c(0, 160), xlab="cm",
       breaks=seq(160, 200, 1))
hist(players$Ht, main="PGA Players Heights", ylim=c(0, 160), xlab="cm",
       breaks=seq(160, 200, 2))
hist(players$Ht, main="PGA Players Heights", ylim=c(0, 250), xlab="cm",
       breaks=seq(160, 200, 5))


도수분포표의 분포 범위 다양하게 만들기

앞서 도수분포표는 막대의 면적이 중요하고, 막대의 폭 역시 같을 필요가 없다고 말씀드린 것 기억하시나요? 키의 범위별로 도수분포표의 폭을 달리 표현해 보겠습니다. seq()함수는 숫자열을 생성하는 기본적인 함수입니다. breaks 파라미터에 시퀀스 함수를 추가해 도수분포의 범위를 조정하는 것이 포인트입니다. c(seq(160, 170, 2), 185, 200) 부분만 R에 넣고 실행해 보시기 바랍니다. 숫자열이 다르게 생성됩니다. 그래프도 이 숫자열에 따라 그려집니다.


# 선수 키에 대한 히스토그램 - 키의 분포 범위를 조정
par(mfrow=c(1,3), mar=c(3, 3, 3, 3))
hist(players$Ht, main="PGA Players Heights", ylim=c(0, 0.05), xlab="cm",
       breaks=c(seq(160, 170, 2), 185, 200))
hist(players$Ht, main="PGA Players Heights", ylim=c(0, 0.06), xlab="cm",
       breaks=c(160, 170, seq(185, 200, 2)))
hist(players$Ht, main="PGA Players Heights", ylim=c(0, 0.25), xlab="cm",
       breaks=c(160, seq(170, 185, 1), 200))


PGA 투어 선수들의 대륙별 평균키로 도수분포표 만들기

마지막으로 선수들의 대륙별 평균 키를 그려보겠습니다. 먼저 그래프가 그려질 영역을 2행 3열 총 6개로 설정하고 여백도 설정했습니다. continent라는 변수에 대륙의 고유값만 추출해 할당합니다. 순환문을 이용해 각 대륙을 순환하면서 같은 대륙의 선수들만 대상으로 한 도수분포표 6개를 만듭니다. 도수분포표 생성시 준 파라미터 lwd는 라인의 폭을 설정하는 것입니다. 기본값은 1입니다.


#PGA 선수 키에 대한 히스토그램 - 대륙별 평균키
par(mfrow=c(2, 3), las=1, mar=c(5, 5, 4, 1))
continent <- unique(players$Continent)
for (i in 1:length(continent)) {
  currPlayers <- subset(players, Continent==continent[i])
  hist(currPlayers$Ht, main=continent[i], breaks=160:200, xlab="cm",
         border="#ffffff", col="#999999", lwd=0.4)
}



PGA투어 선수들의 키로 막대그래프와 도수분포표를 만들어 보았습니다. 도수분포표는 어떤 데이터를 분석하더라도 꼭 필요한 툴 중의 하나입니다. 멋지게 활용해 보시기 바랍니다.


출처: http://analyticsstory.com/118 [Analytics Story]


댓글