[R스터디:RQuestions] 첫 번째 시간/alluvial plot
WeGetRQuestions(22/02/19)
첫 번째 시간
첫 번째 시간에 세 분이 참석하셨습니다. 두 분은 질문을 가지고 오셨는데, 그 질문에 대해 알아봅시다.
파일 인코딩
read.csv(file, fileEncoding = 'UTF-8-BOM')
인코딩이 UTF-8-BOM
인 경우에 파일을 읽기 위해 거의 이틀을 헤맸다고 하셨습니다. 솔직히 이런 경우는 조금 안타깝습니다. 주변에 물어볼 사람이 있으면 금방 해결되는 문제이니까요. 저는 read_csv()
과 Rstudio의 File – Import Dataset – From Text (readr) 을 추천해드렸습니다. read_csv()
의 파일 인코딩 기본값은 UTF-8이고 문의를 주셨던 파일에 적용하니 그냥 읽혔습니다. File – Import Dataset – From Text (readr)를 사용하면 여러 가지 설정 사항을 적용하고 그 결과를 직접 확인해 볼 수 있어서 편합니다.
alluvial plot
두 번째 질문은 시각화 관련 질문이었습니다.
library(dplyr)
library(alluvial)
data(mtcars)
mtcars <- mtcars %>%
mutate(gear = factor(gear),
am = factor(am, labels=c('automatic', 'manual')),
vs = factor(vs, labels=c('V-shaped', 'straight')))
mtcars$freq = 1
dat <- aggregate(freq ~ gear + am + vs,
mtcars, length)
alluvial(dat$gear, dat$am, dat$vs, freq = dat$freq,
col = dat$gear)
alluvial plot이란 범주형 데이터에 대해 각 변수의 관계를 시각화하는 방법입니다. 하지만 언제나 전처리하는 게 문제입니다. mtcars의 경우는 다음과 같이 여러 방법으로 각 범주와 빈도를 계산할 수 있습니다.
mtcars$freq = 1
dat <- aggregate(freq ~ gear + am + vs,
mtcars, length)
dat
## gear am vs freq
## 1 3 automatic V-shaped 12
## 2 4 manual V-shaped 2
## 3 5 manual V-shaped 4
## 4 3 automatic straight 3
## 5 4 automatic straight 4
## 6 4 manual straight 6
## 7 5 manual straight 1
dat2 <-
mtcars %>%
select(gear, am, vs) %>%
table %>%
as.data.frame %>%
rename(freq = Freq)
dat2
## gear am vs freq
## 1 3 automatic V-shaped 12
## 2 4 automatic V-shaped 0
## 3 5 automatic V-shaped 0
## 4 3 manual V-shaped 0
## 5 4 manual V-shaped 2
## 6 5 manual V-shaped 4
## 7 3 automatic straight 3
## 8 4 automatic straight 4
## 9 5 automatic straight 0
## 10 3 manual straight 0
## 11 4 manual straight 6
## 12 5 manual straight 1
table()
로 시작할 경우엔 마지막에 %>% filter(freq > 0)
을 덧붙여주는 게 좋을 것 같네요.
dat3 <-
mtcars %>%
select(am, gear, vs) %>%
table %>%
as.data.frame %>%
rename(freq = Freq) %>%
filter(freq > 0)
dat3
## am gear vs freq
## 1 automatic 3 V-shaped 12
## 2 manual 4 V-shaped 2
## 3 manual 5 V-shaped 4
## 4 automatic 3 straight 3
## 5 automatic 4 straight 4
## 6 manual 4 straight 6
## 7 manual 5 straight 1
사실 저는 크게 와닿지는 않습니다. 왜냐하면 사실 2차원 이상을 정확하게 인지하기란 어렵기 때문입니다. alluvial plots과 같은 경우에 사람의 인지적 한계가 어디까지인지 에 대한 연구가 있을지도 모르죠. (아무리 사람이 다양한 색을 구분할 수 있다고 해도 범주형 시각화에서 4-5개 이상의 색을 쓰면 시각화된 정보를 사람이 정확하고 빠르게 받아들이기는 힘든 법입니다.)
범주형 시각화에서 제가 선호하는 방법은 모자이크 플롯입니다.
library(ggmosaic)
ggplot(data = mtcars) +
geom_mosaic(mapping = aes(x = product(am, vs), fill=am))
## Warning: `unite_()` was deprecated in tidyr 1.2.0.
## Please use `unite()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
위의 그림을 보면 x축의 vs를 통해 V-shaped
와 straight
엔진의 비율을 확인할 수 있습니다. y
축의 automatic
, manual
를 통해 수동기어와 자동 기어의 비율도 확인할 수 있고요. 그리고 V-shaped
안의 automatic
, manual
의 구분을 통해 V-shaped
일 때 automatic
과 manual
의 비율(조건부 확률)도 확인할 수 있습니다. 만약 전체적인 비율과 조건부 비율이 같다면 색깔 구분은 수평선으로 나타나게 됩니다.
그래도 요즘에 자주 쓰인다고 하니 alluvial plots을 그릴 수 있는 방법에 대해 알아봅니다. alluvial
이란 패키지와 ggalluvial
이란 패키지를 사용할 수 있습니다. ggplot2
와 ggalluvial
을 활용하는 방법을 알아봅시다.
ggalluvial
w/ 가로형 데이터
가로형 자료는 컬럼에 각 변수가 그리고 빈도가 포함되어야 합니다. 예를 들어 위에서 전처리가 완성된 dat3
를 보면 다음과 같습니다. 아래 결과를 보면 automatic
에 gear
3, V-shaped
인 경우는 12개 있습니다.
head(dat3)
## am gear vs freq
## 1 automatic 3 V-shaped 12
## 2 manual 4 V-shaped 2
## 3 manual 5 V-shaped 4
## 4 automatic 3 straight 3
## 5 automatic 4 straight 4
## 6 manual 4 straight 6
library(ggplot2)
library(ggalluvial)
ggplot(dat3,
aes(y=freq, axis1=gear, axis2=am, axis3=vs)) +
geom_alluvium() +
geom_stratum(width = 1/3) +
geom_text(stat = "stratum", aes(label = after_stat(stratum))) +
scale_x_discrete(limits = c("gear", "am", 'vs'), expand = c(.1, .1))
이 플롯의 몇 가지 특성을 확인해봅시다. 위의 플롯에는 automatic
이면서 V-shaped
인 경우 3
과 4
의 구분이 없습니다. 어떤 블로그는 이런 점이 alluvial plot의 특성이며, 구분이 가능한 경우는 parallel sets plot이라고 구분하고 있습니다. 그렇지만 현재 모두가 인정하는 용어 정립은 되어 있지 않은 듯 보입니다.
사실 ggalluvial
을 사용해서도 위에서 얘기한 parallel sets plot을 그릴 수 있습니다. 일단 geom_alluvium()
에 aes(fill=gear)
만 해줘도 3
,4
의 구분이 가능합니다.
library(ggplot2)
library(ggalluvial)
ggplot(dat3,
aes(y=freq, axis1=gear, axis2=am, axis3=vs)) +
geom_alluvium(aes(fill=gear)) +
geom_stratum(width = 1/3) +
geom_text(stat = "stratum", aes(label = after_stat(stratum))) +
scale_x_discrete(limits = c("gear", "am", 'vs'), expand = c(.1, .1))
ggalluvial
w/ 세로형 데이터
위의 예와 같이 가로형은 alluvial()
함수와 비슷하게 사용할 수 있지만 fill
설정에 한계가 있습니다. stratum에서 새롭게 색깔을 정의할 수 없다는 얘기죠. 세로형 데이터로 바꾼 후 geom_flow()
를 사용한다면 stratum에서 새롭게 색깔을 지정할 수 있습니다.
먼저 세로형을 만듭시다. ggalluvial
에서 친히 to_loads_form()
이라는 함수를 만들어줬네요.
dat$Cohort = 1:nrow(dat)
dat2 <- to_lodes_form(dat,
axes = 1:3,
id = "Cohort")
head(dat2)
## freq Cohort x stratum
## 1 12 1 gear 3
## 2 2 2 gear 4
## 3 4 3 gear 5
## 4 3 4 gear 3
## 5 4 5 gear 4
## 6 6 6 gear 4
library(tidyr)
dat2b <- gather(dat, key='x', value='stratum', gear:vs)
## Warning: attributes are not identical across measure variables;
## they will be dropped
head(dat2b)
## freq Cohort x stratum
## 1 12 1 gear 3
## 2 2 2 gear 4
## 3 4 3 gear 5
## 4 3 4 gear 3
## 5 4 5 gear 4
## 6 6 6 gear 4
결과 dat2
와 dat2b
를 비교해보면 컬럼의 클래스(문자열형 또는 팩터형)을 제외하고는 동일함을 확인할 수 있습니다.
cbind(dat2 %>% arrange(Cohort, x, stratum),
dat2b %>% arrange(Cohort, x, stratum)) %>%
head()
## freq Cohort x stratum freq Cohort x stratum
## 1 12 1 gear 3 12 1 am automatic
## 2 12 1 am automatic 12 1 gear 3
## 3 12 1 vs V-shaped 12 1 vs V-shaped
## 4 2 2 gear 4 2 2 am manual
## 5 2 2 am manual 2 2 gear 4
## 6 2 2 vs V-shaped 2 2 vs V-shaped
이제 다시 alluvial plots를 그려봅니다.
ggplot(data = dat2,
mapping =
aes(x = x, y=freq,
stratum = stratum,
alluvium = Cohort,
fill= stratum,
label=stratum)) +
#geom_alluvium(aes(fill=stratum)) +
geom_flow(alpha=0.5) +
geom_stratum(alpha=0.5) +
geom_text(stat='stratum', aes(label = after_stat(stratum))) +
guides(fill='none')
## Warning: `spread_()` was deprecated in tidyr 1.2.0.
## Please use `spread()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
## Warning: The `.dots` argument of `group_by()` is deprecated as of dplyr 1.0.0.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
====
유료 R STUDY 안내
- 관심이 있다면 링크를 클릭하세요!
// add bootstrap table styles to pandoc tables function bootstrapStylePandocTables() { $('tr.odd').parent('tbody').parent('table').addClass('table table-condensed'); } $(document).ready(function () { bootstrapStylePandocTables(); });
Leave a comment