R을 통한 시각화와 탐색적 데이터 분석(EDA)
R을 통한 시각화와 탐색적 데이터 분석(EDA)
시각화는 데이터 패턴을 직관적으로 이해하는 핵심 도구입니다. 오늘은 R의 ggplot2의 레이어 구조를 이용하여 복잡한 데이터를 시각화를 통해 체계적으로 구성해보도록 하겠습니다.
➤ 시각화의 목적
- 비교(Comparison)
- 구성(Composition)
- 분포(Distribution)
- 관계(Relationship)
➤ ggplot2의 구성 요소
| 함수 | 설명 |
|---|---|
qplot() | 기하학적 객체와 미적 요소 매핑으로 스케일링 |
ggplot() | 미적 요소 매핑에 레이어 관련 함수 추가하여 플로팅, 미적 요소 재사용 |
ggsave() | 해상도 적용하여 다양한 형식의 이미지 파일 저장 |
ggplot2 핵심 구조
- Data
- Function
- Coordinates
- Mapping
- Geometries
- Scales
- Facets
- Themes
주요 시각화 도구
기본 차트 유형
- 단변량 분석:
barplot,pie,stemhistogram,qqnorm
- 다변량 분석:
plot,boxplot,pairs,curve
그래프 요소 추가 함수
title,lines,points,abline,text,segments,polygonlegend(범례),axis,box
ggplot2 작동 원리
- 데이터:
data.frame형식 사용 (범주형 데이터 요약 가능) - 좌표계 종류:
- 직교 좌표계 (Cartesian)
- 극좌표계 (Polar)
- 원통형 좌표계
- 구형 좌표계
- Geoms: 기하학적 객체 (예:
points,lines,polygons) - Aesthetics(미적 요소):
- 위치(
position), 크기(size), 색상(color), 모양(shape), 투명도(alpha), 채움(fill)
- 위치(
- 통계적 변환(Stats):
counts,means,median, 회귀선(regression lines) 등 집계 함수 적용
- Facets: 화면 분할을 통한 다중 차트 생성
- Themes: 그래프 스타일 커스터마이징
예제
# 기본 데이터 로드 data(cars) plot(cars$speed, type="l", main="속도 변화", xlab="측정 순서", ylab="속도") plot(cars, type="b", pch=22, cex=1.5, col="red") 다중 플롯 레이아웃
# 화면 분할 예제 opar <- par(mfrow=c(1,2)) hist(cars$speed, main="속도 분포") boxplot(cars$dist, main="제동거리 분포") par(opar) ggplot2를 이용한 고급 시각화
기본 레이어 구조
library(ggplot2) ggplot(mtcars, aes(x=wt, y=mpg)) + geom_point(aes(color=factor(cyl)), size=3) + labs(title="차량 중량 대비 연비", x="중량(톤)", y="연비(mpg)") 다중 차원 시각화
# 페이셋을 이용한 그룹별 시각화 ggplot(mpg, aes(displ, hwy)) + geom_point() + facet_wrap(~class, ncol=4) + geom_smooth(method="lm", se=FALSE) 지도 시각화
library(maps) asia <- map_data("world", region=c("South Korea", "Japan")) ggplot(asia, aes(long, lat, group=group, fill=region)) + geom_polygon(colour="black") + scale_fill_brewer(palette="Set3") 데이터 전처리
결측치 처리
# 결측치 확인 및 처리 sum(is.na(weatherAUS_d)) weather_clean <- na.omit(weatherAUS_d) 이상치 처리
# 박스플롯을 이용한 이상치 탐지 numeric_columns <- sapply(weatherAUS_d, is.numeric) re <- boxplot(numeric_columns) re # 이상치 확인 for (col_name in names(weatherAUS_d)[numeric_columns]) { outliers <- boxplot.stats(weatherAUS_d[[col_name]])$out weatherAUS_d[[col_name]][weatherAUS_d[[col_name]] %in% outliers] <- NA } weatherAUS_d<-na.omit(weatherAUS_d) re # 이상치 잘 제거 되었는지 확인 문자열 처리
정규표현식 활용
# 주 이름에서 'k'가 포함된 주 찾기 states <- rownames(USArrests) grep("k", states, value=TRUE, ignore.case=TRUE) # 문자열 패턴 대체 gsub("\\d", "_", "Secret Code: 007") stringr 패키지 활용
library(stringr) str_c("Data", "Science", sep=" ") # 문자열 결합 str_detect(c("apple", "banana"), "a") # 패턴 검출 샘플링과 예측 모델링
데이터 분할
# 70-30 샘플링 set.seed(100) train_idx <- sample(1:nrow(weatherAUS_d), 0.7*nrow(weatherAUS_d)) train_data <- weatherAUS_d[train_idx,] test_data <- weatherAUS_d[-train_idx,] 시각화를 통한 인사이트 발굴
# 습도와 강수 관계 시각화 ggplot(train_data, aes(Humidity3pm, Temp3pm)) + geom_point(aes(color=RainTomorrow), alpha=0.6) + labs(title="오후 3시 기상 조건과 강수 예측", x="습도(%)", y="온도(℃)") 고급 시각화 테크닉
다중 그래프 배열
library(gridExtra) g1 <- ggplot(mtcars, aes(factor(cyl))) + geom_bar() g2 <- ggplot(mtcars, aes(wt, mpg)) + geom_point() grid.arrange(g1, g2, ncol=2) 밀도
library(ggplot2) library(gridExtra) g1=ggplot(mtcars, aes(x=qsec)) + geom_density(fill="slateblue") # 밀도 # theme : 그래프의 모양과 스타일을 커스터마이징, legend.position : 범례의 위치 g2=ggplot(mtcars, aes(x=drat, y=qsec, colour = cyl)) + geom_point(size=5) + theme(legend.position = "none") g3=ggplot(mtcars, aes(x=factor(cyl), y=qsec, fill = cyl)) + geom_boxplot() + theme(legend.position = "none") g4=ggplot(mtcars, aes(x=factor(cyl), fill = factor(cyl))) + geom_bar() grid.arrange(g1,g2,g3,g4, ncol=2,nrow=2) # 2열 2행 grid.arrange(g2, arrangeGrob(g3,g4,ncol=2),nrow=2) # g3,g4열로 2개, 2행 grid.arrange(g1,g2,g3, nrow=3) grid.arrange(g2, arrangeGrob(g3,g4,ncol=2),nrow=1) 수학 표현식 사용
# 그리스 문자 포함 축 레이블 ggplot(data.frame(x=1:10), aes(x)) + stat_function(fun=dnorm) + labs(x=expression(mu + sigma), y=expression(frac(1, sqrt(2*pi*sigma^2)))) 선형회귀
# formula (종속변수 ~ 독립변수와의 관계) (m<-lm(dist ~ speed, data=cars)) (m<-lm(dist ~ speed, cars)) plot(cars) # 산점도 abline(m) # 보조 시각화 함수(선 추가, 회귀선(선형회귀)) (p<-predict(m, interval="confidence")) # predict : 예측 / 주로 선형 회귀 모델, 로지스틱 회귀 모델, 의사결정 트리 등 다양한 모델에서 활용 head(p) # lwr:하한값, upr:상한값 : fit +- 1.96 * 표준오차(표준변차/sqrt(n)) x<-c(cars$speed, tail(cars$speed, 1), rev(cars$speed), cars$speed[1]) # rev: reverse(역순으로) y<-c(p[, "lwr"], tail(p[, "upr"],1), rev(p[, "upr"]), p[, "lwr"][1]) # x,y 값으로 box 그리는 과정 polygon(x,y,col=rgb(.7,.7,.7,.5)) # (x축 : speed 값, y축 : 상하한값), rgb : (r,g,b, 투명도) (1,1,1 => 흰색 / 0,0,0 => 검정) 비선형회귀
opar <- par(mfrow=c(1,1)) plot(cars) lines(lowess(cars)) # lowess : 비선형회귀 이렇듯 2차원에서 여러 특징을 나타내는 법에 대해 간단히 알아보았습니니다. 이번 포스팅과 저번 포스팅에 배운 것을 이용하면 큰 데이터에서 적절하게 데이터를 샘플링하여 각 요소별로 결과에 어떤 영향을 주는지 분석해 볼 수 있을 것입니니다. 날씨 데이터에서 오후3시 날씨와 습도가 다음날 비가 오는데 영향을 주는지 ggplot2로 한번 나타내 보세요요. 이때, geom_density를 이용하면 그 영향을 보기 더 편할 것입니다.
This post is licensed under CC BY 4.0 by the author.