본문 바로가기
R

[혼자 공부하는 R 데이터분석] 6주차_데이터 시각화(ggplot2, ggmap)

by 섀싹 2024. 8. 19.

6-1. 그래프 그리기

데이터 시각화를 위해 R 시각화 1순위 패키지인 ggplot2 패키지를 사용한다.

 

(1) ggplot()

ggplot(데이터세트, aes(데이터속성) 그래프를 표현하는 좌표를 그리기 위한 판을 짜는 함수 aes()함수를 이용해 x축과 y축에 변수를 매핑한다.

패키지 설치
install.packages("ggplot2")
library(ggplot2)

 

ggplot(airquality, aes(x=Day, y=Temp))

 

* 작성한 그래프를 지울 때는 plot.new() 함수를 실행한다.

 

(2) 각종 그래프

매핑을 위해 작성한 ggplot() 함수 뒤에 + 를 붙여 추가로 적어주면 된다.

* 그래프를 그리는 수치형 데이터로 표현할 시 빈 범주가 생길 수 있으므로

범주화 할 수 있는 factor() 함수를 사용할 수 있다.

ggplot()    
+ geom_point() 산점도 size=3, color="red" 등으로 사이즈와 색상을 지정하는 옵션을 설정할 수 있음
+ geom_line() 선 그래프  
+ geom_bar() 막대 그래프 x 축만 지정하면 된다.
width=0.5 등으로 막대의 두께를 바꿔주는 옵션을 설정할 수 있음
+ geom_bar(aes(fill=factor(gear))) 누적 막대 그래프 gear 변수의 빈도가 막대 안에 채워진다.

*누적할 변수는 값이 비어있을 경우 누적이 제대로 표현되지 않으므로 반드시 factor() 함수를 사용해야 한다. fill 옵션을 사용하면 누적 변수의 범주별 빈도가 막대 그래프에 색상으로 채워짐.
+ geom_bar(aes(fill=factor(gear))) + coord_polar 선버스트 차트(계층 구조의 데이터를 수준별로 비율을 표시하는 그래프) theta="y" 옵션을 추가하면 가운데가 도넛처럼 비어있는 선버스트 차트가 그려짐.
+ geom_boxplot() 상자 그림 group 옵션 지정 필수
+ geom_histogram() 히스토그램 binwidth = 1 등으로 막대 구간 조정 옵션을 설정할 수 있음.

* 줄바꿈시 연산자까지 작성한 후 줄을 바꿔야 코드 한 줄로 인식됨.

* 그래프들끼리 여러개 더할 수 있음 (한 그래프가 하나의 레이어처럼 동작, 여러개 더하면 여러 레이어가 겹쳐지는 꼴)

# 산점도
ggplot(airquality, aes(x=Day, y=Temp)) + geom_point()
ggplot(airquality, aes(x=Day, y=Temp)) + geom_point(size=3, color='red')

# 선 그래프
ggplot(airquality, aes(x=Day, y=Temp)) + geom_line()

# 막대 그래프
ggplot(mtcars, aes(x=cyl)) + geom_bar(width = 0.5)

ggplot(mtcars, aes(x=factor(cyl))) + geom_bar(width = 0.5)

# 누적 막대 그래프 
ggplot(mtcars, aes(x=factor(cyl))) + geom_bar(aes(fill=factor(gear)))

# 선버스트 차트 
ggplot(mtcars, aes(x=factor(cyl))) + geom_bar(aes(fill=factor(gear))) + coord_polar()
ggplot(mtcars, aes(x=factor(cyl))) + geom_bar(aes(fill=factor(gear))) + coord_polar(theta="y")

# 상자 그림
ggplot(airquality, aes(x=Day, y=Temp, group=Day)) + geom_boxplot()

# 히스토그램
ggplot(airquality, aes(Temp)) + geom_histogram(binwidth = 1) #막대 너비

# 그래프 + 그래프 + ~~
ggplot(airquality, aes(x=Day, y=Temp)) + geom_line() + geom_point()
ggplot(airquality, aes(x=Day, y=Temp)) + geom_line(color="red") + geom_point(size=3)

# 291페이지 확인문제 2
data("diamonds")
ggplot(diamonds, aes(x=cut)) + geom_bar(width=0.5)

# 확인문제 3
ggplot(diamonds, aes(x=carat, y=price)) + geom_line()

 

6-2. 그래프에 객체 추가

그래프 위에 직선, 도형, 텍스트 객체를 추가하는 방법

(1) 사선 그리기 : geom_abline() 함수

geom_abline(intercept=절편값, slope=기울기값)

# ex)
ggplot(economics, aes(x=date, y=psavert)) + geom_line() +
  geom_abline(intercept = 12.18671, slope = -0.0005444)

 

(2) 평행선 그리기 : geom_hline() 함수

geom_hline(yintercept=y절편)

#ex)
ggplot(economics, aes(x=date, y=psavert)) + geom_line() +
  geom_hline(yintercept = mean(economics$psavert))

 

(3) 수직선 그리기 : geom_vline() 함수

geom_vline(xintercept=x절편)

# ex)
library(dplyr)

x_inter <- filter(economics, psavert == min(economics$psavert))$date

ggplot(economics, aes(x=date, y=psavert)) + geom_line() +
  geom_vline(xintercept = x_inter)

*직접 원하는 날짜값을 넣을 수 있지만 "2015-07-01" 이런 형태로 입력하면 글자로 인식되므로 as.Date() 함수를 이용해야함

geom_vline(xintercept=as.Date("2005-07-01"))

 

(4) 레이블 입력하기 : geom_text() 함수

geon_text(aes(label = 레이블, vjust = 세로 위치, hjust = 가로 위치))

# ex)
ggplot(airquality, aes(x=Day, y=Temp)) + geom_point() +
  geom_text(aes(label=Temp, vjust=0, hjust=0))

* 레이블을 입력하면 기본적으로 점 우상단에 찍히며 vjust 에 + 값 찍히면 아래로, hjust 에 + 값 찍히면 왼쪽으로 이동한다.

 

(5) 도형 및 화살표 넣기 : annotate() 함수

annotate("모양", xmin=x축 시작, xmax=x축 끝, ymin = y축 시작, ymax=y축 끝)

 

그래프에 사각형 그리기

ggplot(mtcars, aes(x=wt, y=mpg)) +
  geom_point() +
  annotate("rect", xmin=3, xmax=4, ymin=12, ymax=21,
           alpha =0.5, fill="skyblue")

* alpha : 투명도(1에 가까울수록 불투명), fill :채우기 색상 지정

 

+ 화살표 추가

+ annotate("segment", x=2.5, xend=3.7, y=10., yend=17,
           color = 'red', arrow=arrow())

* segment : 선, x와 xend 로 표현

 

+ text 추가

+ annotate("text", x=2.5, y=10, label='point')

 

출력물 >

(6) 좀 더 알아보기 1

그래프 제목 및 축 제목 추가하기 : labs() 함수

디자인 테마 적용하기 : theme() 함수 -> 여러개 존재

theme_gray() 회색 바탕과 흰 선
theme_bw() 흰 바탕과 회색 선
theme_linedraw() 흰 바탕과 가늘고 검은 선
theme_light() 밝은 회색 바탕
theme_dark() 어두운 바탕
theme_minimal() 단순한 배경
theme_classic() 눈금과 안내선이 없는 기본 바탕
theme_void() 가장 간결한 바탕

 

labs(x="x축명", y="y축명", title="그래프 제목")

# ex)
ggplot(mtcars, aes(x=gear)) + geom_bar() +
  labs(x='기어 수', y='자동차 수', title='변속기 기어별 자동차수') + 
  theme_linedraw()

 

(7) 좀 더 알아보기 2

두 변수 간 상관관계 파악하기 : cor.test() 함수

cor.test(테이블명$변수명1, 테이블명$변수명2)

# ex)
library(readxl)
exdata1 <- read_excel("C:/Rstudy/Sample1.xlsx")
exdata1

cor.test(exdata1$Y20_CNT, exdata1$Y21_CNT)

엑셀로 파일을 불러오고 두 변수간의 상관관계를 cor.test 함수로 비교한다.

cor 값은 0.7582, p-value 값은 0.000107 이므로 통계적으로 유의하고 양의 상관관계가 있으며 이는 20년 카드 이용건수가 오를수록 21년 이용건수도 증가한다고 해석할 수 있다.

 

회귀분석하기 : lm() 함수

lm(종속변수~독립변수, data = 데이터세트)

# ex)
reg_result <- lm(Y21_CNT~Y20_CNT, data=exdata1)
reg_result

y 절편이 0.7014, 기울기가 0.7864다.

즉 y(21년 카드 이용건수) = 0.7104 + 0.7864 * x(20년 카드 이용건수) 로 회귀함수를 도출할 수 있다.

 

시각화하기

ggplot(exdata1, aes(x=Y20_CNT, y=Y21_CNT)) + geom_line() +
  geom_abline(intercept = 0.7104, slope = 0.7864)

 

(8) 확인문제

# 307페이지 확인문제 1번
cor.test(iris$Sepal.Length, iris$Petal.Length)
# 통계적으로 유의하며 양의 상관관계가 있음.

# 2번
iris_result <- lm(Petal.Length~Sepal.Length, data=iris)
iris_result

# 3번
library(ggplot2)
ggplot(iris, aes(x=Sepal.Length, y=Petal.Length)) + geom_line() +
  geom_abline(intercept =  -7.101, slope = 1.858)

 

6-3. 지도 시각화 : ggmap 패키지

지도 상에 위치 데이터를 표시하여 보여주는 것이 지도 시각화!

R에서는 지도를 API(Application Programming Interface)로 불러와 시각화를 할 수 있다.

(구글 지도, 오픈스트리트맵, 스테이먼 맵 등 지원)

이 중 구글 지도는 ggmap 패키지로 불러올 수 있다.

시작하기 위해 구글 지도 플랫폼에서 미리 API 키를 발급받아 와야한다.

http://mapsplatform.google.com

 

Google Maps Platform - Location and Mapping Solutions

 

mapsplatform.google.com

실습을 위해 API 키 보호는 [나중에] 클릭.

API 미리 복사해두지 않아도 key&credentials 파트에 가보면 확인할 수 있음.

 

이하 ggmap 패키지 사용법.

 

(1) resister_google(key="사용자 API 키")

발급받은 구글 지도 API 키를 등록하는 함수

 

사용자 API 키 부분에 위에서 각자 발급받은 개인 API 코드를 입력하면 된다.

 

(2) get_googlemap(지명 or 위도경도값, maptype="지도 유형")

설정한 위치를 지도로 가져오는 함수

 

1) 지명 or 위도경도값

 

* 위도와 경도값으로 가져오기

get_googlemap(c(lon=127, lat=37.6), maptype = "roadmap")

 

* 위치를 포함하는 문자열로 가져오기

get_googlemap("seoul, south korea", maptype="roadmap)

 교재에서는 seoul 만 적혀있으나 R에서는 south korea 까지 써주는걸 추천한다.

 

2) maptype="지도 유형"

terrain 지형 (기본값)
satellite 인공위성
roadmap 로드맵
hybrid 인공위성 + 로드맵

 

(3) ggmap()

위치 데이터 지도로 시각화

 

(4) geocode() 

위치를 포함하는 문자열(지명 혹은 주소)을 위도와 경도 값으로 반환

 

(5) 사용 예시 1

install.packages("ggmap")
library(ggmap)

ggmap 패키지 설치 후 세팅해주기

 

register_google(key="개인 API 값")

gg_seoul <- get_googlemap("seoul, south korea", maptype = "roadmap")
ggmap(gg_seoul)

발급받은 API 값 등록하고, 서울 지명을 넣고 roadmap 타입으로 지도 가져와서 gg_seoul에 저장해준다.

ggmap() 함수를 이용하여 변수에 할당된 위치데이터로 구글 지도 가져오기.

굳이 이중으로 안하고 ggmap() 함수 안에서 get_googlemap 해줘도 된다. 

(6) 사용 예시 2

library(dplyr)
library(ggplot2)

밑에서 %>% 기호를 사용해줄 것이므로 dplyr 패키지 로드

그래프 사용할 것이므로 ggplot2 로드

geo_code <- enc2utf8("대전역") %>% geocode()
geo_code

enc2utf8 함수는 인코딩을 UTF-8로 변환하는 함수이다. Windows 운영체제는 기본적으로 CP949 라서 위치 데이터를 한글 문자열로 가져오려면 UTF-8 로 변환해주는 과정을 거쳐야 한다.

위는 그렇게 utf8 로 한글을 입력받은 뒤 geocode() 함수를 통해 경도와 위도값이 나오게 되는데,

이 경우 데이터 프레임 형태로 저장된다.

 

geo_data <- as.numeric(geo_code)
geo_data

 

데이터 프레임 형태의 경우 get_googlemap 에서 인식을 할 수 없으므로 이 데이터 프레임을 숫자형 벡터로 변환한다.

 

get_googlemap(center = geo_data, maptype = "roadmap", zoom=13) %>% ggmap()+
  geom_point(data=geo_code, aes(x=lon, y=lat))

 get_googlemap()의 경우 숫자형 벡터를 받지만, 그래프를 그리기 위한 geom_point 의 경우 데이터프레임 형태를 받는다. 각각 다른 데이터 형태가 요구된다는 것 알고 가기!

zoom 의 경우 지도를 확대하거나 축소하는 옵션이다.

위처럼 하게되면 최종적으로 아래와 같은 결과값이 나온다.

(7) 확인문제

# 321페이지 확인문제 3번
get_googlemap(c(lon=127.0276, lat=37.49795), maptype="roadmap", zoom=15) %>% ggmap()

# 확인문제 4번
library(ggmap)
resister_google(key="AIzaSyDElVnICNMybUM_mAlqS85n1zBUysvo4_c")

gg_busan <- get_googlemap("busan, south korea", maptype="roadmap")
ggmap(gg_busan)

 

 

6-4. 과제

 

[기본 과제]

ggplot(airquality, aes(x=Day, y=Temp)) + geom_line() + geom_point()
ggplot(airquality, aes(x=Day, y=Temp)) + geom_line(color="red") + geom_point(size=3)

 

[추가 과제]

geo_code1 <- enc2utf8("남산 타워") %>% geocode()
geo_data1 <- as.numeric(geo_code1)
get_googlemap(geo_data1, maptype="roadmap", zoom=15) %>% ggmap() +
  geom_point(data=geo_code1, aes(x=lon, y=lat))