변수의 개수 및 데이터의 형태에 따라서 그래프, 시각화 방법이 달라지는데요,

 

지난번 포스팅에서는 한 변수의 연속형 데이터의 시각화 방법으로

 

 - 히스토그램(Histogram)
    : geom_histogram()

- 커널 밀도 곡선(Kernel Density Curve)
    : geom_density()

 - 박스 그래프(Box Plot)
    : geom_boxplot()

 - 바이올린 그래프(Violin Plot)
    : geom_violin()

 

범주형 데이터에 대한 시각화 방법으로

 

 - 막대그림(Bar Chart): geom_bar()

 - 원그림(Pie Chart): geom_bar() + coord_polar()

 - 모자이크 그림(Mosaic Chart): vcd 패키지 mosaic()

 

알아보았습니다.

 

 

이번에는 두 개 이상의 연속형 변수를 시각화하는 방법으로

 

 - 산점도 (Scatter Plot): geom_point()

 - 선 그래프(Line Plot): geom_line()

 - 시계열 그래프(Time Series Plot): geom_line()  

 

에 대해서 알아보겠습니다.

 

 

[ 변수 개수 및 형태에 따른 그래프 종류 ]

 

 

 

 

 

선 그래프(Line Graph)는 x축의 연속형 변수(또는 (순서나 크기가 있는 이산형 변수, ordered factor)의 변화에 따른 y축의 변화를 선으로 이어서 보여주는 그래프입니다.  x축이 시간의 순서이면 시계열 그래프(Time Series Graph) 이구요.

 

 

Base 패키지에 들어있는 airquality 데이터 프레임을 가지고 시계열 그래프를 그려보도록 하겠습니다.

airquality 데이터 프레임은 1973년 5월부터 9월달까지 뉴욕의 공기의 Ozone, Solar, Wind, Temp를 Daily 로 측정한 데이터 셋입니다.  결측값이 없는 Wind와 Temp를 가지고 시계열 그래프를 그려보겠습니다.

 

> str(airquality)
'data.frame':	153 obs. of  6 variables:
 $ Ozone  : int  41 36 12 18 NA 28 23 19 8 NA ...
 $ Solar.R: int  190 118 149 313 NA NA 299 99 19 194 ...
 $ Wind   : num  7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ...
 $ Temp   : int  67 72 74 62 56 66 65 59 61 69 ...
 $ Month  : int  5 5 5 5 5 5 5 5 5 5 ...
 $ Day    : int  1 2 3 4 5 6 7 8 9 10 ...
 
> head(airquality)
  Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
5    NA      NA 14.3   56     5   5
6    28      NA 14.9   66     5   6

 

> # 결측값 여부 확인
> sum(is.na(airquality$Ozone))
[1] 37
> sum(is.na(airquality$Solar.R))
[1] 7
> sum(is.na(airquality$Wind))
[1] 0
> sum(is.na(airquality$Temp))
[1] 0

 

 

보기에 좋도록 Month 변수와 Day 변수를 합쳐서 Time이라는 새로운 변수를 만들어보겠습니다.

 

> # Time 변수 생성
> airquality <- transform(airquality, 
+                         Month.ch_temp = as.character(Month), 
+                         Day.ch_temp = as.character(Day))
> 
> airquality <- transform(airquality, 
+                         Month.ch = paste("0", Month.ch_temp, sep=""), 
+                         Day.ch = ifelse(Day.ch_temp == "1", "01", 
+                                  ifelse(Day.ch_temp == "2", "02", 
+                                  ifelse(Day.ch_temp == "3", "03", 
+                                  ifelse(Day.ch_temp == "4", "04", 
+                                  ifelse(Day.ch_temp == "5", "05", 
+                                  ifelse(Day.ch_temp == "6", "06", 
+                                  ifelse(Day.ch_temp == "7", "07", 
+                                  ifelse(Day.ch_temp == "8", "08", 
+                                  ifelse(Day.ch_temp == "9", "09", 
+                                                  Day))))))))))
> 
> airquality <- transform(airquality, 
+                         Time = paste(Month.ch, Day.ch, sep=""))
> 
> airquality_May <- airquality[c(1:31), c(1:6, 11)]
> 
> head(airquality_May)
  Ozone Solar.R Wind Temp Month Day Time
1    41     190  7.4   67     5   1 0501
2    36     118  8.0   72     5   2 0502
3    12     149 12.6   74     5   3 0503
4    18     313 11.5   62     5   4 0504
5    NA      NA 14.3   56     5   5 0505
6    28      NA 14.9   66     5   6 0506

 

 

 

선그래프를 그릴 때 group 지정을 안해주면 아래처럼 경고메시지가 뜨고, 선그래프가 텅 비게 나옵니다.

 

* 경고메시지: geom_path: Each group consist of only one observation. Do you need to adjust the group aesthetic?

 

> # 선그래프
> library(ggplot2)
> 
> # warning: geom_path: Each group consist of only one observation. Do you need to adjust the group aesthetic?
>
> ggplot(airquality_May, aes(x=Time, y=Wind)) + 
+   geom_line() + 
+   ggtitle("Line Graph, Wind from May.01 to May.31")
geom_path: Each group consist of only one observation. Do you need to adjust the group aesthetic?

 

 

 

 

 

이 문제를 해결하기 위해 gruop=1 을 지정해줍니다.

 

> # group=1
> ggplot(airquality_May, aes(x=Time, y=Wind, group=1)) + 
+   geom_line() + 
+   ggtitle("Time Series Graph, Wind from May.01 to May.31")

 

 

 

 

 


> ggplot(airquality_May, aes(x=Time, y=Temp, group=1)) + 
+   geom_line() + 
+   ggtitle("Time Series Graph, Temp from May.01 to May.31")

 

 

 

 

 

 

위의 두 개의 시계열 그래프를 보면 y축을 ggplot2 가 자동으로 계산해서 적정 범위를 설정해주었습니다만, 경우에 따라서는 사용자가 강제로 특정 범위를 설정해주고 싶을 때가 있습니다.  아래는 ylim()을 이용해서 0~max(y) 값 까지 y축 범위를 설정한 예시입니다.

 

> # y축 범위 설정 0~max
> ggplot(airquality_May, aes(x=Time, y=Temp, group=1)) + 
+   geom_line() + 
+   ylim(0, max(airquality_May$Temp)) +
+   ggtitle("Time Series Graph, Temp from May.01 to May.31, y axis from 0 to max")

 

 

 

 

 

 

 

선그래프의 선 모양도 바꿔보고 싶고, 점도 덮입혀 보고 싶다면 아래 예제를 참고하세요.

 

> # 점선으로 변경, 점 추가
> ggplot(airquality_May, aes(x=Time, y=Temp, group=1)) + 
+   geom_line(linetype="dotted", size=1, colour="blue") + 
+   geom_point(size=3, shape=19, colour="blue") +
+   ggtitle("Time Series Graph, Temp from May.01 to May.31, with dotted line, dot")

 

 

 

 

 

참고로 R Line Type과 Shape 은 아래와 같습니다.

 

[ R Line Type ]

 

 

 

[ R Symbol Shape ]

 

 

 

다음은 aes() 내 group과 colour 를 사용하여 그룹별로 선그래프, 시계열그래프 그리는 방법입니다. 

 

> # 집단별 시계열 그래프 : 월별(5월~9월) Temp 시계열 그래프
> ggplot(data=airquality, aes(x=Day, y=Temp, colour=Month, group=Month)) + 
+   geom_line() + 
+   geom_point(size=3) +
+   ggtitle("Time Seires Graph, Temp from May to Sep.")

 

 

 

 

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

 

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

 

728x90
반응형
Posted by Rfriend
,

변수의 개수 및 데이터의 형태에 따라서 그래프, 시각화 방법이 달라지는데요,

 

지난번 포스팅에서는 한 변수의 연속형 데이터의 시각화 방법으로

 

 - 히스토그램(Histogram)
    : geom_histogram()

- 커널 밀도 곡선(Kernel Density Curve)
    : geom_density()

 - 박스 그래프(Box Plot)
    : geom_boxplot()

 - 바이올린 그래프(Violin Plot)
    : geom_violin()

 

범주형 데이터에 대한 시각화 방법으로

 

 - 막대그림(Bar Chart): geom_bar()

 - 원그림(Pie Chart): geom_bar() + coord_polar()

 - 모자이크 그림(Mosaic Chart): vcd 패키지 mosaic()

 

알아보았습니다.

 

 

이번에는 두 개 이상의 연속형 변수를 시각화하는 방법으로

 

 - 산점도 (Scatter Plot): geom_point()

 - 선 그래프(Line Plot): geom_line()

 - 시계열 그래프(Time Series Plot): geom_line()  

 

에 대해서 알아보겠습니다.

 

참고로 ☞ ggplot2의 geom_point() 산점도 그리기 

          ☞ Base Graphics 패키지의 pairs() 함수를 사용한 산점도 행렬 그리기

 

 

[ 변수 개수 및 형태에 따른 그래프 종류 ]

 

 

 

 

산점도(Scatter Plot)는 x축과 y축에 연속형인 두 변수의 값을 점으로 뿌려준 그래프로서, 연속형인 두 변수 간의 관계를 파악하는데 유용합니다.  다중회귀분석을 할 때 제일 처음 하는 일이 바로 산점도 (행렬)을 그려보고 두 변수간의 선형성 여부를 탐색해보는 일입니다.

 

MASS패키지 내 Cars93 데이터 프레임의 고속도로연비(MPG.highway)와 엔진크기(EngineSize), 무게(Weight), 길이(Length) 와의 관계를 ggplot2 패키지의 geom_point() 함수를 가지고 산포도를 그려서 알아보도록 하겠습니다.   그리고 차종(Type)별로 고속도로연비(MPG.highway) 는 어떻게 되는지도 산포도를 가지고 점의 색깔과 모양을 달리해서 보는 방법을 알아보겠습니다.

 

 

> library(MASS)
> str(Cars93)
'data.frame':	93 obs. of  27 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 ...

 

 

상관계수를 가지고 고속도로연비(MPG.highway)와 엔진크기(EngineSize), 무게(Weight), 길이(Length) 와의 상관도를 먼저 살펴보면, 고속도로연비와 엔진크기, 무게, 길이가 모두 역의 상관관계가 있는 걸로 나왔고, 특히 무게가 역의 상관관계가 크게 나왔습니다.  

 

> Cars93_MPG <- Cars93[,c("MPG.highway", "EngineSize", "Weight", "Length")]
> cor(Cars93_MPG)
            MPG.highway EngineSize     Weight     Length
MPG.highway   1.0000000 -0.6267946 -0.8106581 -0.5428974
EngineSize   -0.6267946  1.0000000  0.8450753  0.7802831
Weight       -0.8106581  0.8450753  1.0000000  0.8062743
Length       -0.5428974  0.7802831  0.8062743  1.0000000 

 

 

이제 산점도를 그려서 고속도로연비(MPG.highway)와 엔진크기(EngineSize), 무게(Weight), 길이(Length) 관계를 살펴보겠습니다.

 

제일 쉬운 방법은 Base graphics 패키지에 있는 plot()함수를 사용하는 방법입니다.  위에서 분석하려는 변수만 따로 선별해놓은 Cars93_MPG 데이터 프레임을 가지고 한번 산점도 행렬을 그려보겠습니다.

 

> plot(Cars93_MPG, 
+      main="Scatter Plot Matrix")

 

 

 

 

 

 

ggplot2로는 산점도 행렬(Scatter Plot matrix)를 그리는 것이 힘듭니다.  대신 여러 조건을 주어서 두 변수 간 산점도 행렬을 다양하게 그려보는데는 아주 강력합니다   우선 ggplot2의 geom_point()함수를 가지고 색깔(colour)과 모양(shape)을 달리하면서 산점도를 그려보겠습니다.

 

> # Scatter Plot: MPG.highway vs. EngineSize, Weight, Length
> library(ggplot2)
> 
> ggplot(data=Cars93, aes(x=EngineSize, y=MPG.highway)) + 
+   geom_point(shape=15, size=3, colour="blue") + # shape 15: solid square
+   ggtitle("Scatter Plot: MPG.highway vs. EngineSize")

 

 

 

 
 

 

> ggplot(data=Cars93, aes(x=Weight, y=MPG.highway)) + 
+   geom_point(shape=19, size=3, colour="red") + # shape 19: solid circle
+   ggtitle("Scatter Plot: MPG.highway vs. Weight")

 

 

 

 

 

 

> ggplot(data=Cars93, aes(x=Length, y=MPG.highway)) + 
+   geom_point(shape=24, size=3, colour="black") + # shape 24: filled triangle point-up
+   ggtitle("Scatter Plot: MPG.highway vs. Length")

 

 

 

 

 

 

참고로, R plot의 숫자별 모양은 다음과 같습니다.

 

> # R plot symbols: points
> help(pch)

 

 

 

 

 

 

이번에는 두 변수의 산포도에 모델명 라벨을 geom_text(label=) 함수를 이용하여 입혀보겠습니다.  

 

> # Scatter Plot with Label (Model Name) > ggplot(data=Cars93, aes(x=Weight, y=MPG.highway)) + + geom_point(shape=19, size=3, colour="red") + # shape 19: solid circle + ggtitle("Scatter Plot: MPG.highway vs. Weight with Model Label") + + geom_text(aes(label=Model, size=2, vjust=-1, hjust=0)) # vjust=-1 위로, hjust=1 오른쪽

 

 

 

 

 

 

 

다음으로 차종(Type)별로 구분하여서 무게(Weight)와 고속도로연비(MPG.highway) 간의 관계를 3가지 방법을 사용하여 산포도로 그려보도록 하겠습니다.

 

     (1) 차종(Type)별로 색깔(colour)을 달리해서

     (2) 차종(Type)별로 모양(shape)을 달리해서

     (3) 차종(Type)별로 층(facet_grid)을 나누어서

산포도를 그려보겠습니다.

 

 

(1) 차종(Type)별로 색깔(colour)을 달리했을 때 

 

> # Scatter Plot by Type, using different Colours
> ggplot(data=Cars93, aes(x=Weight, y=MPG.highway, colour=Type)) + 
+   geom_point(shape=19, size=3) + 
+   ggtitle("Scatter Plot by Type, using different Colours")

 

 

 

 

 

 

 (2) 차종(Type)별로 모양(shape)을 달리했을 때

 

> # Scatter Plot by Type, differenct Shapes
> ggplot(data=Cars93, aes(x=Weight, y=MPG.highway, shape=Type)) + 
+   geom_point(size=3) + 
+   ggtitle("Scatter Plot by Type, differenct Shapes")

 

 

 

 

 

(3) 차종(Type)별로 층(facet_grid)을 나누어서 산포도를 그릴 때 

 

> # Scatter Plot by Type, using facet_grid
> ggplot(data=Cars93, aes(x=Weight, y=MPG.highway)) + 
+   geom_point(size=3, shape=19) + 
+   facet_grid(Type ~.) +
+   ggtitle("Scatter Plot by Type, using facet_grid")

 

 

 

 

 

 

다음으로, 산포도에 선형 회귀선 (신뢰구간 95%)을 적합시켜보겠습니다.

 

> # Scatter Plot with linear regression line
> ggplot(data=Cars93, aes(x=Weight, y=MPG.highway)) + 
+   geom_point(shape=19, size=3, colour="red") + # shape 19: solid circle 
+   stat_smooth(method=lm, level=0.95) + 
+   ggtitle("Scatter Plot: Linear Regression Line with Confidence Level 95%")
 

 

 

 

아래는 산포도에 회귀선을 적합시켰는데, 위와는 다르게 신뢰구간은 뺀 경우입니다.

 

> ggplot(data=Cars93, aes(x=Weight, y=MPG.highway)) + 
+   geom_point(shape=19, size=3, colour="red") + # shape 19: solid circle 
+   stat_smooth(method=lm, se=FALSE) + 
+   ggtitle("Scatter Plot: Linear Regression Line without Confidence Level")

 

 

 

 

 

 

산포도에 선을 적합시킬 때 선형회귀선말고도 loess(locally weighted polynomial) 를 써서 비모수 회귀(Nonparametric regression) 선을 적합시킬 수도 있습니다.

 

> # Scatter Plot with loess(locally weighted polynomial)
> ggplot(data=Cars93, aes(x=Weight, y=MPG.highway)) + 
+   geom_point(shape=19, size=3, colour="red") + # shape 19: solid circle 
+   stat_smooth(method=loess, level=0.95) + 
+   ggtitle("Scatter Plot: loess Line with Confidence Level 95%")

 

 

 

 

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

 

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

 

 

728x90
반응형
Posted by Rfriend
,

변수의 개수 및 데이터의 형태에 따라서 그래프, 시각화 방법이 달라지는데요,

 

지난번 포스팅에서는 연속형 데이터의 시각화 방법으로

 - 히스토그램(Histogram)
    : geom_histogram()

- 커널 밀도 곡선(Kernel Density Curve)
    : geom_density()

 - 박스 그래프(Box Plot)
    : geom_boxplot()

 - 바이올린 그래프(Violin Plot)
    : geom_violin()

에 대해서 알아보았습니다. 

 

 

이번 포스팅에서는 범주형 데이터의 시각화 방법으로서

 

 - 막대그림(Bar Chart): geom_bar()

 - 원그림(Pie Chart): geom_bar() + coord_polar()

 - 모자이크 그림(Mosaic Chart): vcd 패키지 mosaic()

 

에 대해서 소개해드리겠습니다.

 

 

[ 변수 개수 및 데이터 형태에 따른 그래프 ]

 

 

 

데이터는 MASS 패키지에 들어있는 Cars93 데이터 프레임의 차종(Type)과 제조국(Origin) 데이터를 활용해서 차종별 제조국별 도수를 구한 후에, 원그림을 그려보겠습니다.

 

원그림은 세로로 쌓아올린(stacked) 막대그림을 먼저 geom_bar()로 먼저 그린 후에 ==> coord_polar("y")로 해서 표현 형식을 원형(polar coordinates)으로 바꾸어주는 절차를 따릅니다.

 

(1) 바로 아래에 있는 그래프가 쌓아올린 막대그림 (stacked bar chart) 이구요,

 

> ## 원그림(Pie Chart)
> library(ggplot2)
> library(MASS)
> 
> # 막대그림 먼저 그린 후 => 원그림
> library(sqldf)
> Car_Type_Origin_cnt <- sqldf( 'select Type, Origin, count(*) as Type_Origin_cnt
+                               from Cars93
+                               group by Type, Origin
+                               order by Type, Origin
+                               ')
> 
> Car_Type_Origin_cnt
      Type  Origin Type_Origin_cnt
1  Compact     USA               7
2  Compact non-USA               9
3    Large     USA              11
4  Midsize     USA              10
5  Midsize non-USA              12
6    Small     USA               7
7    Small non-USA              14
8   Sporty     USA               8
9   Sporty non-USA               6
10     Van     USA               5
11     Van non-USA               4
> 
> sapply(Car_Type_Origin_cnt, class)
           Type          Origin Type_Origin_cnt 
       "factor"        "factor"       "integer" 
> 
> 
> ggplot(data=Car_Type_Origin_cnt, aes(x="", y=Type_Origin_cnt, fill=Type)) +
+   facet_grid(facets=. ~ Origin) + 
+   geom_bar(stat="identity", width=1) + 
+   ggtitle("Bar Chart of Frequency by Car Type & Origin")

 

 

 

 

 

(2) 그 다음 표현형식을 coord_polar("y") 를 써서 원형으로 바꾸어 본 것이 아래 script 가 되겠습니다.

 

> 
> # 원그림(Pie Chart) : geom_bar() + coord_ploar(theta="y")
> ggplot(data=Car_Type_Origin_cnt, aes(x="", y=Type_Origin_cnt, fill=Type)) +
+   facet_grid(facets=. ~ Origin) + 
+   geom_bar(stat="identity", width=1) + 
+   coord_polar(theta="y") + 
+   ggtitle("Pie Chart of Car Type by Origin, theta=y")

 

 

 

 

 

 

이번 포스팅에서 원그림(Pie Chart)를 소개하기는 했습니다만, 저는 원그림은 그다지 추천하지 않습니다.  일단 눈으로 보고 해석하기에, 범주간 비교하기에 그다지 용이하지가 않습니다.  파이 조각의 면적을 눈으로 가늠해서 비교하기가 쉽지 않거든요.  막대그림으로 높이를 비교하는 것이 범주 간 차이를 단박에 보여주는 것과 비교하면 원그림은 그래프를 봐야하는 이에게는 불친절한 그래프입니다.

(단, 두 집단(가령 USA, non-USA) 간에 과반을 넘는 특정 segment를 비교해서 강조하고 싶은 경우는 원그림이 효과적일 수 있음)

 

신문이나 잡지에서 보면 원그림을 많이 사용하고 있고, 더 나아가서는 입체 원그림을 그리고, 또 나아가서는 입체 원그림의 한 조각을 확대하거나 원그림을 살짝 눕히기도 하는데요, 이건 정말 최악 중의 최악입니다.  일단, 시각적으로 해석하기에 어렵구요, 더 나아가서는 악의를 가지고 시각의 불완전성을 이용해서 정보를 왜곡/오도하기 위한 것일 수도 있으니 주의가 필요합니다

 

웬만하면 원그림은 사용하지 말기를 권하며, 누가 원그림 사용하거든 그만 사용하라고 권해주기를 권합니다.  그냥 쉽고 편한 막대그림 사용하세요.

 

참고용으로, 막대그림으로 나타내면 아래와 같은데요, 위의 원그림과 비교해보시기 바랍니다.  뭐가 더 쉽고 해석하기 편한지요.

 

> # 막대그림
> ggplot(data=Car_Type_Origin_cnt, aes(x=Type, y=Type_Origin_cnt)) +
+   facet_grid(facets=. ~ Origin) + 
+   geom_bar(stat="identity", width=1, fill="white", colour="black") + 
+   ggtitle("Bar Chart of Frequency by Car Type & Origin")

 

 

 

 

원그림 소개한다고 해놓고는, 막대그림으로 끝을 맺네요. ^^'

 

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

 

 

728x90
반응형
Posted by Rfriend
,

변수의 개수 및 데이터의 형태에 따라서 그래프, 시각화 방법이 달라지는데요,

 

지난번 포스팅에서는 일변량 연속형 데이터의 시각화 방법으로

 - 히스토그램(Histogram)
    : geom_histogram()

- 커널 밀도 곡선(Kernel Density Curve)
    : geom_density()

 - 박스 그래프(Box Plot)
    : geom_boxplot()

 - 바이올린 그래프(Violin Plot)
    : geom_violin()

에 대해서 알아보았습니다. 

 

 

이번 포스팅에서는 일변량 범주형 데이터의 시각화 방법으로서

 

 - 막대그림(Bar Chart): geom_bar()

 - 원그림(Pie Chart): geom_bar() + coord_polar()

 

에 대해서 소개해드리겠습니다.

 

 

[ 변수 개수 및 데이터 형태에 따른 그래프 ]

 

 

 

 

 

 

먼저, 범주별 도수를 구하고 이를 막대 형태로 나타낸 막대 그래프 (Bar Chart)를 ggplot2의 geom_bar() 로 그려보겠습니다. 

 

사용할 데이터는 MASS 패키지에 있는 Cars93 데이터 프레임에서 자동차 유형(Type), 제조국(Origin) 등의 범주형/요인(factor)형 변수를 사용하겠습니다.

 

> library(MASS)
> str(Cars93)
'data.frame':	93 obs. of  27 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 ... 

 

 

자동차 유형(Type)별 도수를 가지고 막대그림을 그려보겠습니다.

 

> ggplot(Cars93, aes(x=Type)) + 
+   geom_bar(fill="white", colour="black") + 
+   ggtitle("Bar Chart of Frequency by Car Type")

 

 

 

 

 

 

위와 똑같은 그래프를 그려볼건데요, 이번에는 aes(x, y)의 x변수와 도수에 해당하는 y변수로 된 데이터프레임을 만들어서 이를 직접 x, y에 입력해서 그래프를 그려보겠습니다 (간편하게는 위의 방식 사용하면 되구요, 아래 처럼 데이터가 구성이 되어있다면 이번 방식을 이용하면 되겠습니다).  아래 예제에서는 자동차 유형(Type)별로 도수를 집계(aggregation)할 때 sqldf 패키지를 사용하였습니다.

 

> install.packages("sqldf")
> library(sqldf)
> 
> Car_Type_cnt <- sqldf( 'select Type, count(*) as Type_cnt
+                           from Cars93
+                           group by Type
+                           order by Type
+                         ')
> 
> Car_Type_cnt
     Type Type_cnt
1 Compact       16
2   Large       11
3 Midsize       22
4   Small       21
5  Sporty       14
6     Van        9
> 
> sapply(Car_Type_cnt, class)
     Type  Type_cnt 
 "factor" "integer" 

 

다음으로 자동차 유형(Type)별로 geom_bar()를 이용하여 막대그림을 그려보도록 하겠습니다.  y에 직접 입력해주고, geom_bar()에 stat="identity"를 설정해주어야 합니다.

 

> # 자동차 유형별 도수 막대 그림
> library(ggplot2)
> 
> ggplot(Car_Type_cnt, aes(x=Type, y=Type_cnt)) + 
+   geom_bar(stat="identity", fill="white", colour="black") + 
+   ggtitle("Bar Chart of Frequency by Car Type")

 

 

 

 

 

 


 

일변량에 더해서, 이번에는 2개의 변수를 사용한 막대그림도 살펴보도록 하겠습니다.  차종(Type) 별 제조국(Origin) 별 자동차 수를 가지고 막대그림을 그려보도록 하겠습니다. 

 

> # Origin별 구분 추가하기
> ggplot(Cars93, aes(x=Type, fill=Origin)) + 
+   geom_bar(position="dodge", colour="black") + 
+   scale_fill_brewer(palette=1) +
+   ggtitle("Bar Chart of Frequency by Car Type & Origin")

 

 

 

 

 

 

이번에는 위와 동일한 그래프를 그릴건데요, sqldf()로 차종(Type)별 & Origin 별 자동차 도수를 집계를 해서 데이터프레임을 만들어서 막대그림을 그려보겠습니다.

 

> # 차종(Type) 별 실린더개수(Cylinders) 별 자동차 개수 > library(sqldf)

> Car_Type_Origin_cnt <- sqldf( 'select Type, Origin, count(*) as Type_Origin_cnt + from Cars93 + group by Type, Origin + order by Type, Origin + ') > Car_Type_Origin_cnt Type Origin Type_Origin_cnt 1 Compact USA 7 2 Compact non-USA 9 3 Large USA 11 4 Midsize USA 10 5 Midsize non-USA 12 6 Small USA 7 7 Small non-USA 14 8 Sporty USA 8 9 Sporty non-USA 6 10 Van USA 5 11 Van non-USA 4 >

 

geom_bar()로 막대그림을 그리되, 처음의 일변량 때와는 다르게 fill=Origin 로 하여서 제조국별로 구분을 해보겠습니다.  position="dodge" 를 하면 수평으로 나란히 Origin별로 그려집니다.

 

> ggplot(Car_Type_Origin_cnt, aes(x=Type, y=Type_Origin_cnt, fill=Origin)) + 
+      geom_bar(stat="identity", position="dodge", colour="black") + 
+      scale_fill_brewer(palette=1) +
+      ggtitle("Bar Chart of Frequency by Car Type & Origin_1")

 

 

 

 

 

만약 position="dodge" 옵션을 지정하지 않으면 아래와 같이 세로로 올라탄 그래프 형식으로 제시됩니다.

 

> # without position="dodge" > ggplot(Car_Type_Origin_cnt, aes(x=Type, y=Type_Origin_cnt, fill=Origin)) + + geom_bar(stat="identity", colour="black") + # position="dodge" 미지정 + scale_fill_brewer(palette=1) + + ggtitle("Bar Chart of Frequency by Car Type & Origin, without podge option")

 

 




* 누적 막대 그래프 (stacked bar chart)


아래와 같이 생긴 데이터프레임에서 'id' 그룹별로 'bin_val' 값을 이용해서 누적 막대그래프 (stacked bar chart)를 그려보겠습니다. 이때 막대그래프의 색깔은 'color' 칼럼의 색으로 지정해서 그려보겠습니다. 


parsed.txt


df = read.table('parsed.txt', sep=',', header=T)

df <- transform(df, bin_val = bin_end - bin_start)

df

A data.frame: 12 × 7
idcolor_cdcolorbin_startbin_endbin_rangebin_val
<fct><fct><fct><int><int><fct><int>
AAAared0100[0,100)100
AAAbblue100200[100,200)100
AAAared200300[200,300)100
AAAbblue300400[300,400)100
BBBared0250[0,250)250
BBBbblue250350[250,350)100
BBBared350450[350,450)100
BBBbblue450550[450,550)100
BBBared550650[550,650)100
BBBbblue650750[650,750)100
BBBared750800[750,800)50
BBBbblue800910[800,910)110


library(ggplot2)

ggplot(df, aes(x=id, y=bin_val, fill=color, group=id)) + 

    geom_bar(stat="identity") +

    scale_fill_manual("legend", values = c("red" = "red", "blue" = "blue"))





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

다음번 포스팅에서는 원그림(Pie Chart)를 알아보겠습니다.

 

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

 

728x90
반응형
Posted by Rfriend
,

데이터셋을 받으면 제일 먼저 하는 일이 데이트의 구조를 파악하고, 변수명, 변수별 데이터 유형(숫자형, 문자형, 논리형), 결측값 여부, 이상치/영향치 여부, 데이터의 퍼진 정도/분포 모양 등을 탐색하게 됩니다.

 

하나의 연속형 변수에 대한 퍼진 정도/분포 모양와 이상치 여부를 쉽고 빠르게 파악할 수 있는 그래프로

 - 히스토그램(Histogram)

 - 커널 밀도 곡선 (Kernel Density Curve)

 - 박스그림(Box Plot)

 - 바이올린 그래프 (Violin Plot) 

등 이 있습니다.

 

 

 

[ 변수 개수 및 형태별 그래프 종류 ]

 

 

 

 

박스 그래프(Box Plot)는 Box-and-Whiskers Plot 이라고도 하는데요, 연속형 변수에 대해 min, Q1, median, Q3, max, lower whisker, upper whisker, outlier(*IQR(Inter-Quartile Range)의 1.5배 초과 시) 등을 한눈에 볼 수 있게 그린 그래프입니다. 연속형 한 변수의 분포의 중심, 퍼짐 정도(variance), 치우침 정도(skewness), 이상치/특이값(outlier) 존재 여부, 대칭성(symmetry) 등을 알 수 있는 매우, 매우, 매우 유용한 그래프라고 하겠습니다.  특히 박스 그래프는 이상치에 덜 민감한(robust) 중앙값, IQR 값을 사용한다는 점에서 이상치에 민감한 평균, 표준편차 대비 중심 경향과 퍼짐 정도를 파악하는데 있어 상대적으로 더 믿을 만 하다고 말할 수 있습니다.  상당히 유용하겠지요?!

 

 

[ 박스 그래프(Box-Whiskers Plot) 이해 ]

 

 

 

이번 포스팅에서는 먼저 ggplot2 패키지의 geom_boxplot() 를 활용해서 박스그래프(상자그림)을 그리는 방법에 대해서 알아보겠습니다. 

 

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

 

> # Cars93 데이터 프레임
> library(MASS)
> str(Cars93)
'data.frame':	93 obs. of  27 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 ...

 

 

 

그럼, 먼저 Cars93 데이터 프레임 내 가격(Price) 변수 하나를 가지고 geom_boxplot()을 사용하여 박스 그래프(Box Plot)을 그려보겠습니다. 

 

> ggplot(Cars93, aes(x = 1, y = Price)) + # x=1 (임의의 값) 지정해줘야 함
+   geom_boxplot(width=0.8, outlier.size=3, outlier.shape=16, outlier.colour="red") + 
+   scale_x_continuous(breaks = NULL) + # x축 이름 생략
+   theme(axis.title.x = element_blank()) + # x축 구분자 생략
+   ggtitle("Box Plot")

 

 

 

 

 

 

다음으로, 차종별(Type)로 가격(Price) 변수에 대해 박스 그래프를 그려보겠습니다.  aes(x = factor variable) 을 입력해주면 되겠습니다.  여기서 주의할 점은 x 에다가 요인(factor)형 변수를 입력해줘야 합니다.  차종(Type)은 이미 요인형 변수이므로 그대로 입력하면 되겠구요, 만약 요인형 변수가 아니라면 x=factor(variable name)  이런 식으로 입력해주거나, 아니면 transform() 함수로 as.factor()로 데이터 형태를 요인형 변수로 아예 만든 후에 ggplot2 그래프를 그려도 되겠습니다.

 

> # 박스그림(Box Plot) - 차종별(Type)
> ggplot(Cars93, aes(x = Type, y = Price)) + 
+   geom_boxplot(width=0.8, outlier.size=3, outlier.shape=16, outlier.colour="red") +
+   ggtitle("Box Plot by Car Type")

 

 

 

 

 

 

위의 차종(Type)별 박스그림의 박스 가운데 선은 중앙값(Median)을 나타낸다고 했는데요, 이번에는 평균을 추가해 보도록 하겠습니다.  평균은 이상치에 민감하므로 아래 예제처럼 이상치가 있는 경우에는 중심화 경향을 나타내는 통계량으로 부적합하며, 박스 그림의 박스 가운데에 쳐진 선이 의미하는 중앙값(Median) 이 더 적합한 중심화 경향 지표라고 하겠습니다.

 

> # box plot with mean > ggplot(Cars93, aes(x = Type, y = Price)) + + geom_boxplot(width=0.8, outlier.size=3, outlier.shape=16, outlier.colour="red") + + stat_summary(fun.y="mean", geom="point", shape=21, size=3, fill="blue") + + ggtitle("Box Plot by Car Type, adding mean")

 

 

 

 


만약 차종(Type)과 생산지(Origin)의 두 기준/그룹으로 구분해서 박스 그래프를 그리고 싶다면 aes(fill = Origin) 을 추가해주면 됩니다. 



> ggplot(Cars93, aes(x = Type, y = Price, fill = Origin)) + 

+   geom_boxplot(width=0.8, outlier.size=3, outlier.shape=16, outlier.colour="red") +

+   ggtitle("Box Plot by Car Type and Origin")

 





 

다음으로 박스 그래프(Box Plot)와 커널 밀도 곡선(Kernel Density Curve)을 짬뽕해놓은 바이올린 그래프(Violin Plot)를 geom_violin()을 사용해 그려보겠습니다.  제공해주는 정보량이 많아서 바이올린 그래프(Violin Plot) 또한 유용한 편인데요, 실전에서는 별로 사용하지 않게 되는 그래프이기도 합니다. ^^;

 

> # Violin Plot with Box Plot
> ggplot(Cars93, aes(x = Type, y = Price)) + 
+   geom_violin() + 
+   geom_boxplot(width=0.1, fill="white", outlier.colour=NA) +
+   stat_summary(fun.y="median", geom="point", shape=21, size=2, fill="black") + 
+   ggtitle("Violin Plot by Car Type with Box Plot")

 

 

 

 

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

 

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

 

 

728x90
반응형
Posted by Rfriend
,

데이터셋을 받으면 제일 먼저 하는 일이 데이트의 구조를 파악하고, 변수명, 변수별 데이터 유형(숫자형, 문자형, 논리형), 결측값 여부, 이상치/영향치 여부, 데이터의 퍼진 정도/분포 모양 등을 탐색하게 됩니다.

 

하나의 연속형 변수에 대한 퍼진 정도/분포 모양와 이상치 여부를 쉽고 빠르게 파악할 수 있는 그래프로 히스토그램(Histogram), 커널 밀도 곡선 (Kernel Density Curve)과 박스그림(Box Plot), 바이올린 그래프 (Vilon Plot) 등 이 있습니다.

 

 

 

[ 변수 개수별 형태별 그래프 종류 ]

 

 

 

히스토그램(Histogram)은 연속형 변수를 일정한 구간(binwidth)으로 나누어서 빈도수를 구한 후에 이를 막대그래프로 그린 그래프입니다.

 

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

 

 

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

 

> # Cars93 데이터 프레임
> library(MASS)
> str(Cars93)
'data.frame':	93 obs. of  27 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 ...

 

 

ggplot2 패키지를 library()로 호출한 후에 ggplot() 함수의 +geom_histogram() 함수를 사용하여 default 옵션으로 히스토그램을 그리면 아래와 같습니다.

 

> ## 히스토그램 (Histogram)
> # install.packages("ggplot2") # ggplot2 패키지 설치
> library(ggplot2)
> 
> 
> # binwidth defaulted to range/30
> 
> ggplot(Cars93, aes(x=Price)) + 
+   geom_histogram()
stat_bin: binwidth defaulted to range/30. Use 'binwidth = x' to adjust this. 
 

 

 

 

위에 실행결과 콘솔창의 메시지를 보면 "stat_bin: binwidth defaulted to range/30. Use 'binwidth = x' to adjust this."이라는 메시지가 아래 보이는데요, 이는 binwidth를 설정하지 않아서 range/30 디폴트 기준으로 binwidth를 계산해서 그렸다는 뜻입니다.  아래에 실제 범위(range)를 구해서 30으로 나누었더니 1.816 이었고, 이 값을 geom_histogram(binwidth = 1.816) 옵션값이 입력해서 히스토그램을 그려보았더니 위와 같음을 알 수 있습니다.  

 

> range(Cars93$Price) # 7.4 ~ 61.9
[1]  7.4 61.9
> diff(range(Cars93$Price))  # 54.5
[1] 54.5
> diff(range(Cars93$Price))/30 # 1.816
[1] 1.816667
> 
> ggplot(Cars93, aes(x=Price)) + 
+   geom_histogram(binwidth=1.816) + 
+   ggtitle("Binwidth=1.816 ; Default, range/30")
 

 

 

 

히스토그램에서 중요하면서 어려운 문제 중의 하나가 bin 개수를 몇 개로 할 것인가, 다른 말로 binwidth를 몇  으로 할 것인가 입니다.  bin 개수가 너무 많으면 (즉, binwidth가 너무 좁으면) 이빨빠진 머리빗처럼 데이터의 분포 모양을 보기에 부적할 수가 있습니다.  반면에 bin 개수가 너무 적으면 (즉, binwidth가 너무 넓으면) 너무 많은 도수가 하나의 bin에 퉁쳐져서 막대기둥 한두개만 덩그라니 서있게 되어 이 또한 데이터의 분포 모양을 파악하는데 도움이 안되게 됩니다.  적절한 bin 개수를 선정하는게 중요한데요, 아래에 binwidth 를 조절해가면서 히스토그램을 그려봤습니다. 

 

 

> # histograms by various binwidths > > h1 <- ggplot(Cars93, aes(x=Price)) + + geom_histogram(binwidth=1.816) + + ggtitle("Binwidth=1.816 ; Default, range/30") > > h2 <- ggplot(Cars93, aes(x=Price)) + + geom_histogram(binwidth=5) + + ggtitle("Binwidth=5") > > h3 <- ggplot(Cars93, aes(x=Price)) + + geom_histogram(binwidth=10) + + ggtitle("Binwidth=10") > > h4 <- ggplot(Cars93, aes(x=Price)) + + geom_histogram(binwidth=20) + + ggtitle("Binwidth=20") > > h5 <- ggplot(Cars93, aes(x=Price)) + + geom_histogram(binwidth=30) + + ggtitle("Binwidth=30") > > h6 <- ggplot(Cars93, aes(x=Price)) + + geom_histogram(binwidth=40) + + ggtitle("Binwidth=40") > > > > > ##----------------- > ## multiplot function by knitr and Jekyll (author of Cookbook for R) > ## 아래 사용자정의 함수를 그대로 카피해서 사용하면 됨 > install.packages("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)) + } + } + } > ##----------------- > > # Multiple graphs on one page : multiplot > multiplot(h1, h2, h3, h4, h5, h6, cols=2)

 

 

 

 

 

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

 

 

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

 

> # 채우기 색, 경계선 색 : geom_histogram(binwidth, fill, colour)
> ggplot(Cars93, aes(x=Price)) + 
+   geom_histogram(binwidth=5, fill = "blue", colour = "black") + 
+   ggtitle("Binwidth=5, fill = blue, colour = black")

 

 

 

 

 

마지막으로, facet_grid() 를 써서 요인(factor)/집단/그룹별로 히스토그램을 구분해서 그려보도록 하겠습니다.  단, facet_grid()에 들어가는 변수는 요인(factor)형 변수이어야 합니다.

 

> # 요인(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("Binwidth=5, fill = blue, colour = black, group by Type") + 
+   facet_grid(Type ~ .)

 

 

 

 

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

 

 

참고로, 위처럼 가로로 비교를 하는 것이 아니라 세로로 세워서 그래프를 그린 후에 비교를 하려면

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

 

> # 요인/집단/그룹(factor)별로 나누어서 히스토그램 그리기
> ggplot(Cars93, aes(x=Price)) + 
+   geom_histogram(binwidth=5, fill = "blue", colour = "black") + 
+   ggtitle("Binwidth=5, fill = blue, colour = black, group by Type") + 
+   facet_grid(. ~ Type) # 수직 
 
 

 

 

 

 

다음으로, 커널 밀도 추정함수를 가지고 그린 커널 밀도 곡선(kernel density curve)를 그려보겠습니다. 

 

히스토그램은 빈도를 가지고 그리며, geom_histogram()함수를 사용하며, 계단식으로 각이 져 있는데요,

 

커널 밀도 곡선(kernel density curve)은 확률(모두 더하면 1)을 가지고 그리고, geom_density() 함수를 사용하며, smoothing 된 곡선으로 되어 있습니다.

 

> # 가격 커널 밀도 곡선(Kernel Density Curve) > ggplot(Cars93, aes(x=Price)) + + geom_density(fill = "yellow", colour=NA, alpha=.5) + # alpha 반투명 + geom_line(stat="density") + + expand_limits(y=0) + + ggtitle("Kernel Density Curve")

 
> # 차종별 가격 커널 밀도 곡선(Kernel Density Curve)_중복
> ggplot(Cars93, aes(x=Price, colour = Type)) + 
+   geom_density(fill = NA) + 
+   geom_line(stat = "density") + 
+   expand_limits(y = 0) + 
+   ggtitle("Kernel Density Curve by Car Type_overlap")
 

 

> # 차종별 가격 커널 밀도 곡선(Kernel Density Curve)_수평 > ggplot(Cars93, aes(x=Price)) + + geom_density(fill = "yellow", colour=NA, alpha=.5) + + geom_line(stat="density") + + expand_limits(y=0) + + ggtitle("Kernel Density Curve by Car Type") + + facet_grid(Type ~ .) + + xlim(10, 40) # X축 범위를 지정해줬더니 40 초과하는 값 짤렸다고 경고메시지 뜸 Warning messages: 1: Removed 3 rows containing non-finite values (stat_density). 2: Removed 10 rows containing non-finite values (stat_density). 3: Removed 3 rows containing non-finite values (stat_density). 4: Removed 10 rows containing non-finite values (stat_density).

 

 

 
 

 

R ggplot2의 커널밀도곡선에서 최대 피크값 좌표를 구하고 수직선을 추가하는 방법은 https://rfriend.tistory.com/485 를 참고하세요. 


 


히스토그램과 커널 밀도 곡선을 겹쳐서 그려보도록 하겠습니다.

 

> # Histogram + Kernel Density Curve
> ggplot(Cars93, aes(x=Price, y=..density..)) + 
+   geom_histogram(binwidth=5, fill = "blue", colour="white", alpha=0.5) + 
+   geom_density(fill = NA, colour=NA, alpha=0.8) + 
+   geom_line(stat="density") + 
+   expand_limits(y=0) + 
+   ggtitle("Histogram + Kernel Density Curve")

 

 

 





히스토그램의 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))






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

 

다음번 포스팅에서는 Box Plot 을 소개하겠습니다.

 

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

 

 

728x90
반응형
Posted by Rfriend
,

R에는 다양한 그래프 패키지들이 있는데요, 그 중에서도 가장 많이 사용되는 패키지 3개를 들자면 Base Graphics package(Base package로서 별도 설치 필요 없음), Lattice package(별도 설치/호출 필요), ggplot22 package(별도 설치/호출 필요) 를 꼽을 수 있습니다. 

 

시중에 나와있는 많은 수의 R 관련 책에서는 Base Graphics package를 가지고 R 그래프 소개를 많이 하고 있는 편이구요, R 그래프/시각화 전문 책에서는 ggplot2에 무게중심을 두고 쓰여진 책이 많은 편인데요, 저는 ggplot2를 중심으로 'R 그래프/시각화' 카테고리에 포스팅을 해보려고 합니다.  (ggplot2를 주로 쓰고, 부수적으로 Base Graphics package, Lattice package 의 그래프 R script를 참고용으로 간략히 소개하는 식으로 글을 써나갈까 합니다.)

 

 

[ R 그래프 패키지 ]

 

 

 

일단 Base Graphics, Lattice, ggplot2에 대해 간략히 장단점을 짚어보고, 그 다음으로 ggplot2의 문법에 대해도 간략히 소개하겠습니다.

 

 

 package

author 

장점 

단점 

 Base Graphics

 R Core Team and contributors worldwide

- 별도 설치/호출 필요 없음

- 쉽고 편함

- 사람이 생각하는 방식처럼
 순차적으로 그래프를 쌓아감

- 한번 실행하면 취소 못함

- 미리 계획 필요
  (예: 세로 축 scale)

 Lattice

Deepayan Sarkar

 - 전체 데이터를 보고 세로축,
  마진, 여백 자동 계산 편리

- 여러개 그래프를 동시에

 하나의 화면에 그릴때 편리

- 순차적으로 그래프 쌓아가는 것 안됨

- 직관적이지 못함

 ggplot2

Hadley Wickham

- Base Graphics 와 Lattice의

 장점만 골라놨음

- 그래프 문법에 따라 체계적,

 통계적 조건 등 부여하여
 고급 그래프 생성 가능

- 처음 배우기가 상대적으로 

 어려움

 (단, 일단 문법이 익으면 

 그때부터는 생산성 더 높음) 

 

 

위 표에서 언급했듯이 ggplot2가 Base Graphics의 interactive하게 하나씩 생각하고, 그려보고, 눈으로 확인하고, 그래프 위에 하나 더 쌓아서 그려보고...하는 직관적인 방식의 장점과, Lattice의 여러개의 집단 전체 데이터의 범위를 보고 축/마진/여백 등을 자동 설정해주는 등의 편리함의 장점을 따다가 '그래프 문법(Grammer of Graphics)'이라는 체계적인 방식으로 만들어진 패키지이다 보니 ggplot2를 추천하는 바입니다.  (ps. 그냥 R로 그래프 몇 개 그리다 말거면, 그냥 일회성으로 쉽게 뚝딱 그래프 그리고 말거면 편하게 Base Graphics 패키지 활용하는게 견적이 더 좋을 수도 있겠습니다.  하지만 그래프 많이 쓰는 사용자라면 Base Graphics는 예외 케이스가 많아서 나중에는 생산성이 ggplot2에 비해 떨어집니다.)

 

그래프의 문법(Grammer of Graphics)라고 말씀드렸는데요, 그래프를 그리는데에도 "동사(Verb)", "명사(Noun)", "형용사(Adjective)"라는 체계를 갖추어 문법을 만들었다고 보면 되겠습니다.

 

 

"In brief, the grammer tells us that a statistical graphic is a mapping from data to aesthetic attirbutes (colour, shape, size) of geometric objects (points, lines, bars). The plot may also contain statistical transformations of the data and is drawn on a specific coordinate system"

       - source : ggplot2 book

 

[ R ggplot2 Components ]

 

 

 

lattice와 ggplot2 패키지 설치 및 패키지 호출은 아래와 같이 하면 됩니다. 

 

## lattice 패키지 설치/호출

install.packages("lattice")
library(lattice)

 

## ggplot2 패키지 설치/호출

install.packages("ggplot2")
library(ggplot2) 

 

 

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

 

 

728x90
반응형
Posted by Rfriend
,