R/실습(project)

[R/실습] ggplot2를 이용한 iris 데이터 시각화

연정양 2023. 1. 3.

데이터 정의

컬럼명 의미
Sepal_Length 꽃받침의 길이(cm)
Sepal_Width 꽃받침의 너비(cm)
Petal_Length 꽃잎의 길이(cm)
Petal_Width 꽃잎의 너비(cm)
Species 붓꽃의 종(setosa, versicolor, virginica)

붓꽃의 3가지 종(setosa, versicolor, virginica)에 대해 꽃받침(sepal)과 꽃잎(petal)의 길이를 정리한 데이터이다. iris 변수별 Species를 중점으로 분석하되, 두 변수를 x, y 축으로 설정해야 하는 경우에는 꽃받침에 대한 설명인 Sepal_Length, Sepal_Width, 꽃잎에 대한 설명인 Petal_Length, Petal_Width를 각각 묶어 분석한다.  

 

데이터 준비

 

1) library 호출

library(ggplot2)
library(reshape2)
library(GGally)

2) 데이터 불러오기

data("iris")
visual_data <- iris

data <- aggregate(iris[,1:4], by = list(iris$Species),
                  FUN = mean)

mt.visual <- melt(data, id.vars = c('Group.1'))

 원 데이터를 담고 있는 변수 하나와, 막대그래프나 누적그래프를 생성할 때 사용할 변수 별 평균을 담고 있는 변수를 포함해 총 두 개의 변수를 생성했다.

 

시각화하기

* ggplot2의 주요한 특징은 요소를 맵핑할 수 있다는 것인데, 맵핑에 따라 테마나 제목 설정, 모양 등 여러 가지 변형을 줄 수 있으므로 알아 두면 좋다. (아래 링크 참고)

 

Function reference

Plot basics All ggplot2 plots begin with a call to ggplot(), supplying default data and aesthethic mappings, specified by aes(). You then add layers, scales, coords and facets with +. To save a plot to disk, use ggsave(). ggplot() Create a new ggplot aes()

ggplot2.tidyverse.org

한글 폰트도 넣을 수 있고 요소 하나하나 설정할 수 있기에,

디자인 측면으로나 자유도 측면으로나 재미있어서 앞으로도 자주 사용할 것 같다.

 

** 분석이 목적이 아니라 구현이 목적이라, 코드와 결과는 일부만 넣었다. 대부분은 변수 명만 변경하면 된다. 

 

1) 세로 막대 그래프

chart2 <- ggplot(mt.visual, aes(x = Group.1, y = value, 
                                group = variable, fill = variable)) +
  geom_bar(stat = "identity", position = "dodge") +
  xlab('Species') + ylab('Values(mean)') + theme_light()+
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5)) +
  ggtitle("iris 세로 막대 그래프")

 geom_bar로 막대차트를 생성하고 Position=dodge’로 막대를 각 범주별로 분리했다. species 기준 변수의 평균을 세로 막대차트로 시각화했다. 

 

2) 가로 막대 그래프

chart1 <- ggplot(mt.visual, aes(x = Group.1, y = value, 
                             group = variable, fill = variable)) +
  geom_bar(stat = "identity", position = "dodge") +
  xlab('Species') + ylab('Values(mean)') + theme_light() +
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5)) +
  coord_flip() +
  ggtitle("iris 가로 막대 그래프")

coord_flip 함수로 x축과 y축을 반경하여 가로 막대를 생성했다. 

 

* 여러 개의 그래프를 함께 출력하려면 이 코드를 추가하면 된다. 

gridExtra::grid.arrange(chart1, chart2, ncol = 1)

ncol = 열의 개수 이므로 위 코드를 실행하면 1열 2행으로 세로그래프, 가로그래프가 나온다. 

 

3) 누적막대 차트

chart3 <- ggplot(mt.visual, aes(x = Group.1, y = value, 
                                group = variable, fill = variable)) +
  
  geom_bar(stat = "identity", position = "stack") +
  xlab('Species') + ylab('Values(mean)') + theme_light() +
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5)) +
  ggtitle("iris 누적 그래프")

position = 'stack'이 추가되었다. 가로, 세로, 누적그래프는 geom_bar 를 기반으로 옵션에 따라 달라진다. 

 

4) 점 차트

chart4 <- ggplot(mt.visual, aes(x = Group.1, y = value,
                                group = variable, color = variable))+
  geom_point(shape = 19, size = 5) + 
  xlab('Species') + ylab('Values(mean)') + theme_light()+
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))+
  labs(color = "Variable") +
  ggtitle("iris 점 차트")

geom_point() 요소를 맵핑해 점 차트를 출력했다. 

 

5) 원형 차트

visual_data2 <- visual_data
visual_data2

min(visual_data2$Sepal.Length)
max(visual_data2$Sepal.Length)
table(visual_data2$Sepal.Length)
visual_data2$Sepal.Length2[visual_data2$Sepal.Length >= 4 & visual_data2$Sepal.Length <5] <- 1 
visual_data2$Sepal.Length2[visual_data2$Sepal.Length >= 5 & visual_data2$Sepal.Length <6] <- 2
visual_data2$Sepal.Length2[visual_data2$Sepal.Length >= 6 & visual_data2$Sepal.Length <7] <- 3
visual_data2$Sepal.Length2[visual_data2$Sepal.Length >= 7 ] <- 4
pie_data1 <- as.data.frame(table(visual_data2$Sepal.Length2))
pie_data1

pie_data1$RF <- round(pie_data1$Freq/150, 3)
pie_data1

chart5 <- ggplot(pie_data1, aes(x="", y =RF, fill = Var1))+
  geom_bar(stat = "identity") + coord_polar("y") +
  theme_light() +
  
  geom_text(aes(label = paste0(round(RF*100,1),"%")),
            position = position_stack(vjust = 0.5)) +
  
  theme(text = element_text(size = 13),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5),
        axis.text.x = element_blank())+
  ylab("") + xlab("") + labs(subtitle = "Sepal.Length 범주별 비율", title = "iris 원형 그래프") +
  scale_fill_discrete(name = "범주", labels = c("4cm이상 5cm미만", "5cm이상 6cm미만", "6cm이상 7cm미만", "7cm이상"))

ggplot2로 pie chart를 그리려면 barplot을 만들어서 원형으로 변경하는 단계를 거쳐야 한다. 따라서 비율을 표시하기 위해 각 변수를 범주화하여 막대 차트를 생성하고 coord_polar를 맵핑하여 원형으로 만들었다. 

 

6) 상자 그래프(box plot)

chart9 <- ggplot(data = visual_data, aes(x = Species, y = Sepal.Length,
                                         fill = Species)) +
  theme_light()+
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))+
  geom_boxplot(aes(fill = Species), outlier.shape = 21, outlier.size= 4) + 
  ggtitle("iris 상자 그래프") +
  ylab(" ") + xlab(" ") + labs(subtitle = "Sepal.Length")

geom_boxplot을 맵핑했으며, 이상치를 쉽게 볼 수 있는 것이 boxplot의 특징이므로  outlier 옵션을 넣었다. 

shape는 아래 링크를 참고하면 된다. 

 

R plot pch symbols : The different point shapes available in R - Easy Guides - Wiki - STHDA

Statistical tools for data analysis and visualization

www.sthda.com

해당하는 숫자를 넣으면 그 모양으로 설정할 수 있다. 

 

7) 히스토그램

chart13 <- ggplot(visual_data, aes(x = Sepal.Length)) +
  theme_light()+
  geom_histogram(fill = "#FFB266", color = "white") +
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))+
  ggtitle("iris 히스토그램") +
  xlab(" ") + labs(subtitle = "Sepal.Length")

chart13

chart14 <- ggplot(visual_data, aes(x = Sepal.Width)) + 
  theme_light()+ 
  geom_histogram(fill = "#FFB266", color = "white") +
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))+
  ggtitle("iris 히스토그램") +
  xlab(" ") + labs(subtitle = "Sepal.Width")

chart15 <- ggplot(visual_data, aes(x = Petal.Length)) + 
  theme_light()+ 
  geom_histogram(fill = "#FFB266", color = "white") +
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))+
  ggtitle("iris 히스토그램") +
  xlab(" ") + labs(subtitle = "Petal.Length")

chart15

chart16 <- ggplot(visual_data, aes(x = Petal.Width)) + 
  theme_light()+ 
  geom_histogram(fill = "#FFB266", color = "white") +
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))+
  ggtitle("iris 히스토그램") +
  xlab(" ") + labs(subtitle = "Petal.Length")

chart16

gridExtra::grid.arrange(chart13, chart14, chart15, chart16, ncol = 2)

변수별 분포를 확인할 수 있는 히스토그램. 차이를 보여주기 위해 이 항목만 네 개를 첨부했다. 

(나머지 항목도 변수명만 바꿔서 확인하면 된다.)  geom_histogram 을 맵핑했고, fill 옵션을 넣어 원하는 색을 설정했다. 

 

8) 산점도 

chart17 <- ggplot(visual_data, aes(Sepal.Length, Sepal.Width, col = Species,
                                   size = 3))+
  theme_light()+
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))+
  labs(title = "iris 산점도 그래프", subtitle = "Sepal.Width & Sepal.Length") +
  geom_point()
chart17

chart18 <- ggplot(visual_data, aes(Petal.Length, Petal.Width, col = Species,
                                   size = 3))+
  theme_light()+
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))+
  labs(title = "iris 산점도 그래프", subtitle = "Petal.Width & Petal.Length") +
  geom_point()

chart18

gridExtra::grid.arrange(chart17, chart18, ncol = 2)

비슷한 특성을 가진 변수끼리 묶어서 시각화했으며, 각각 Witdth가 y축, Length가 x축이다.

Species별로 다른 색을 설정했으며, geom_point를 맵핑했다. 

 

9) 중첩자료 시각화

irisdata <- data.frame(table(visual_data$Sepal.Length, visual_data$Sepal.Width))
names(irisdata) <- c("Sepal.Length", "Sepal.Width", "freq")

chart19 <- ggplot(data = irisdata, aes(x = Sepal.Length, y = Sepal.Width)) +
  scale_size(range = c(1,20), guide = 'none') +
  geom_point(colour = "grey90", aes(size =freq)) +
  geom_point(aes(colour=freq, size=freq))+
  scale_colour_gradient(low="5", high = "blue")+
  geom_smooth(formula = y~x, method = lm, se = FALSE) +
  theme_light()+
  
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))+
  labs(title = "iris 중첩자료", subtitle = "Sepal.Width & Sepal.Length")

Sepal.Width, Sepal.Length의 중첩 빈도수(freq)를 irisdata 변수에 담은 후 각각을 x축, y축으로 설정하여 산점도를 작성했다. geom_point를 맵핑했으며 빈도수가 높을수록 사이즈가 커지도록 설정했다. scale_colour_gradient는 빈도수가 높을수록 색이 짙어지는 그라디언트 옵션이다.

 

10) 변수간의 비교 시각화(+밀도 그래프)

chart21 <- ggpairs(visual_data,
                   aes(color = Species,
                       alpha = 0.5)) + theme_bw()+
  theme(text = element_text(size = 13),
        axis.text.x = element_text(angle = 0, hjust =.5),
        plot.title = element_text(hjust = 0.5)) +
  labs(title = "iris 변수간 비교")

 pairs 기능을 사용하기 위해 ggplot2의 확장 패키지인 GGally를 이용했다. 

이 외에도 3Dscatterplot을 사용하는 방법도 있는데, 

만약 3D를 이용하려면 gg3D라는 확장 패키지를 설치해야 한다.  

 ggpairs의 결과는 아래와 같다. 

밀도 그래프 외에도 박스플롯, 산점도, 히스토그램 등 여러 가지 시각화가 포함되어 있다.

간편하다는 장점은 있으나 시간이 소요되는 편이라 빠른 처리가 필요하다면 3D를 시도해 보거나, 

ggplot2가 아니라 기본 함수인 pairs를 사용하는 게 나을 것 같다. 

댓글