태그 보관물: ggplot2

무선통신서비스 가입회선 통계

과학기술정보통신부 홈페이지에 방문하면 무선통신서비스 가입회선 통계 데이터를 제공하고 있어서 아무나 받아서 사용할 수 있습니다.   수작업으로 하는 것이라서 이전 달의 자료를 다음 달 말일 정도에 업데이트 해줍니다.

그러니까 2월달 자료는 3월말경에 업데이트가 됩니다.

자료가 올라오는 시기가 1개월 가까이 차이가 있어서  이전 달의 내용을 달이 바뀌고 나서 바로 볼 수 없는 것이 흠입니다만
없는 것 보다는 훨씬 낫습니다.  PDF로 제공하는 것도 좀 불편합니다. 포맷을 바꾸기가 조금 번거롭습니다.
엑셀 파일로 해주셨으면 더 좋았을텐데요.

이 자료 얘기를하는 것은 최근에 업무와 관련해서 통신서비스 관련 분석 작업을 조금하게 되었는데 작업을 하고난 김에 저 데이터를 예제로 간단한 시각화 예제를 만들어 보기로 했습니다.

실제 업무에서는 저 데이터와 다른 데이터를 결합해서 확인하거나 하는 것이지만 이 포스트에서는 저 데이터만 이용해서 아주 간단한 EDA작업을 해보겠습니다.

2018년 3월까지의 데이터를 사용했습니다.

이 글을 쓰는 시점은 2018년 5월입니다

소스 코드

플롯(plot)을 그리는데 ggplot2를 사용했고 데이터 랭글링(data wrangling)은 dplyr와 tidyr를 사용했습니다. tidyverse 패키지에 몽땅 같이 들어 있으므로 한 번에 묶음 패키지를 통째로설치하고 싶으면  tidyverse만 설치하면 됩니다.

tidyverse는 ggplot2를 포함한 몇개의 유용한 패키지 를 묶어 놓은 것입니다.

아래 코드에 주석을 적어 두었습니다. 그래서 코드 설명은 따로 하지 않겠습니다.  dplyr와 tidyr에 익숙하지 않은 분들은 패키지 사용법을 잠깐 살펴봐야 할 수있습니다.  이것도 여기서는 설명하지 않겠습니다.  너무 길어집니다.

전체 코드는 다음과 같습니다.

# 무선 통신 서비스
# msu : mobile service users
library(tidyverse)
msu <- read.csv(file="./2018년 3월 기준 - 무선통신서비스 가입회선 통계.csv")
colnames(msu)
msu_molten <- msu %>% gather(월, 가입자, -구분, -통신사)

# 월의 문자열을 날짜 타입으로 바꿉니다
msu_molten <- msu_molten %>% mutate(월=as.Date(paste0(월, ".1"), format="X%Y.%m월.%d"))
msu_molten <- msu_molten %>% filter(구분 != "합 계" & 통신사 != "소계")

# 데이터를 잘 집계해서 플롯을 몇개 그려봅니다

가입구분별_데이터 <- msu_molten %>% group_by(구분, 월) %>% summarise(가입자=sum(가입자))
ggplot(가입구분별_데이터, aes(x=월, y=가입자, fill=구분)) +
   geom_area(colour="black", size=.2, alpha=.4) +
  scale_fill_brewer(breaks=rev(levels(가입구분별_데이터$구분)))

통신사별_데이터 <- msu_molten %>% group_by(통신사, 월) %>% summarise(가입자=sum(가입자))
ggplot(통신사별_데이터, aes(x=월, y=가입자, colour=통신사)) +
  geom_line() +
  scale_fill_brewer(breaks=rev(levels(통신사별_데이터$통신사)))

통신사별_3월_합계 <- msu_molten %>% filter(월=="2018-03-01") %>% group_by(통신사, 월) %>% summarise(가입자=sum(가입자))
ggplot(통신사별_3월_합계, aes(x=통신사, y=가입자, fill=통신사)) + 
  geom_bar(stat="identity")

월별_3월 <- msu_molten %>% filter(월=="2018-03-01" & 구분 != "합 계" & 통신사 != "소계") %>% mutate(구분=as.character(구분), 통신사=as.character(통신사))

# 모자이크 플롯
library(ggmosaic)
ggplot(data=월별_3월) +
  geom_mosaic(aes(weight=가입자, x=product(통신사), fill=구분))

# 카이제곱 검정
표 <- 월별_3월 %>% select(-월) %>% spread(통신사, 가입자) %>% select(-구분)
chisq.test(as.matrix(표))

한글 변수도 몇개 사용했고 줄이 길어서 조금 복잡해 보일텐데요. 복사해서 sublime text 같은 편집기나 Rstudio에서 보세요. 원래 한글 변수명은 잘 안쓰지만 한 번 해보고 싶었습니다.  가끔은 일탈이 필요해요.

에어리어 플롯 – area plot

가입유형별 시계열 에어리어 플롯(time-series area plot)입니다. 케이크 차트(cake chart)라고도 부릅니다.

월별 집계이기 때문에 월별로 가입유형의 변화추세를 볼 수 있습니다.
신규가입자와 기기변경이 많네요.
이전 달에 비해서 큰 폭으로 늘었다는 것을 볼 수 있습니다.

시계열 플롯 – time-series plot

통신사별 시계열 라인플롯입니다.  통신사별, 월별로 가입자를 모두 취합했습니다.

SKT의 가입자가 월등히 많은 것을 볼 수 있습니다.  증가폭도 큽니다. 다른 통신사와  MVNO도 큰폭으로 상승하긴 했습니다.

2월에 가입자가 조금 적은데 어떤 이슈가 있었거나 3월에 있을 이벤트를 사람들이 기다렸을 가능성이 큽니다.
봄 철에는 여러 이벤트가 많은 편인데 새모델이 출시된다거나 요금할인이 된다거나 또는 대학신입생들의 입학 기념품이거나 신학기 행사이거나요. 그래서 2월에는 가입을 하지 않고 3월까지 기다렸을 가능성이 큽니다.
반대로 해석하면 기업들은 통상 3월부터 이벤트를 많이합니다. 주변정보 탐색을 해보지 않았고 부가정보가 없어서 모르지만 상식만으로 그렇게 추측해 봅니다.

위의 가설은 실제로 데이터를 확인하거나 서베이를 해서 확인해 보지 않았기 때문에 논리에 기반한  소설일 뿐입니다

바 플롯 – bar plot

색깔은 기본값으로 막 칠했습니다. 알록달록하게. 나이 먹으면 알록달록한게 좋아집니다.

그냥 2018년 3월의 가입자수를 통신사별로 수치 비교 하기 위해 바 플롯을 그린 것입니다.  바 플롯(bar plot)이라고도 하지만 그냥 막대 차트(bar chart)라고 더 많이 부릅니다. 어쨌는 플롯을 보면 SKT의 가입자가 월등히 많네요.

모자이크 플롯 – mosaic plot

통신사별 구분별로 모자이크 플롯을 그렸습니다.
2차원으로 된 것으로 빈도의 비중을 비교할 때 유용한 플롯입니다.

크기가 큰 것이 많은 것입니다. 사각형의 크기를 보고 비중을 보면 됩니다.

아 쉽다. 전 이런게 좋아요. 쉬운거

그림을 보면 SKT의 기기변경 사용자가 가장 많습니다. 그 다음은 비교하기 애매하지만 KT의 기기변경과 SKT의 신규가입자가 많은 것 같습니다.
MVNO는 신규가입자의 비율이 매우 높습니다. (왜 그럴까요??)
SKT의 기기변경 비율이 다른 통신사에 비해서 높습니다.
KT는 신규가입자의 비율이 다른 통신사에 비해서 높습니다.

2018년 3월은 SKT에 기기변경으로 가입한 사람이 많고 KT는 처음 진입한 사람이 많다고 볼 수 있습니다.  모든 통신사에 걸쳐 처음 가입했다고 하면 이제 막 성인이 되었거나 외국에서 왔거나 일 것 같습니다.

어쨌든 뭐로 보든 SKT 가입자가 많군요. SKT는 통신사 중에서 무선 점유율이 가장 높은 회사로 알려져 있습니다.
여전히 장사 잘되나 봅니다.

마지막으로 소스코드에서 카이제곱 검정(chi-square test)을 했습니다만 별 의미 없는 것입니다.  결과는 귀무가설 기각으로 통신사 구분과 가입종류의 구분은 서로 독립이 아니다. 즉 “영향이 있다” 정도입니다. 이건 가설검정을 하지 않아도 모자이크 플롯으로 봐도 쉽게 알 수 있긴합니다.  하지만 검정법을 사용해서 뭐든 확실하게 한 번 보는게 좋습니다.

여기까지입니다.
사실 너무 대충 하다만 EDA입니다만 데이터를 보고 요약을 정리해 나가다 보면 뜻하지 않는 인사이트를 발견하기도 합니다. 물론 이 데이터는 집계가 너무 많이 되어 있어서 주변정보가 없는 상태에서 특별한 인사이트를 얻기는 어렵습니다.

데이터는 아래 링크를 클릭해서 받으세요.

파일 다운로드: 2018-3-mobile-user-data

R ggplot2 – 경제인구동향 그래프 찍기

R에서 ggplot2경제활동인구찍기를 해봤습니다.
사실은 다른 것을 플로팅해보려다가 원하는 자료를 다운로드 받는 것이 만만치 않아서
대충 지나가다가 통계청 데이터중에 처음 보는 것을 가지고 찍어본 것입니다.
우선은 데이터를 가져와야 합니다. 통계청에 가시면 여러가지 통계데이터를 제공하고 있습니다.
아래 사이트에 가서 경제활동인구동향데이터를 긁어 옵니다.
http://kosis.kr/feature/feature_0103List.jsp?mode=getList&menuId=03&NUM=180

CSV로 다운로드 받아서 해도 되겠지만 데이터가 크지 않으므로 그냥 소스코드에 집어넣기 위해서 copy&paste를 해버립니다.
사이트에서 바로 복사하면 컬럼간의 구분이 Tab으로 되어 있을텐데요.
편집기에서 제가 Tab문자를 쓰지 않아서 Tab을 모두 세미콜론(;)으로 바꿨습니다. 그리고 header를 month와 population으로 해서 column 이름을 아예 데이터에서 지정해버렸습니다.

코드는 아래와 같습니다.
economic_activity_population <- "month;population
2009.09;24,630
2009.10;24,655
2009.11;24,625
2009.12;24,063
2010.01;24,082
2010.02;24,035
2010.03;24,382
2010.04;24,858
2010.05;25,099
2010.06;25,158
2010.07;25,232
2010.08;24,836
2010.09;24,911
2010.10;25,004
2010.11;24,847
2010.12;24,538
2011.01;24,114
2011.02;24,431
2011.03;24,918
2011.04;25,240
2011.05;25,480
2011.06;25,592
2011.07;25,473
2011.08;25,257
2011.09;25,076
2011.10;25,409
2011.11;25,318
2011.12;24,880
2012.01;24,585
2012.02;24,825
2012.03;25,210
2012.04;25,653
2012.05;25,939
2012.06;25,939
2012.07;25,901
2012.08;25,623"

자 이제 data.frame으로 로딩합니다.

statdata <- read.table(file=textConnection(econonic_activity_population), header = TRUE, sep = ";", quote = ""'", as.is=TRUE,colClasses=c("character", "character"))

그리고 나서
statdata$month 컬럼을 Date형식으로 바꿔줍니다. 그러지 않으면 나중에 곤란해집니다. 궁금하시면 직접해 보시구요.
년도와 날짜로만 되어 있는 문자열을 날짜형으로 바꾸기 위해서 강제로 01을 붙여서 그달의 첫째날로 바꿔버립니다.
그리고 바꿀때 타임존(tz)을 서울(Asia/Seoul)로 해줍니다. 안해주면 가끔 날짜가 UTC로 바뀌는 경우가 있습니다.


statdata$month <- as.Date(paste(statdata$month, ".01", sep=""), "%Y.%m.%d", tz="Asia/Seoul")

그리고 statdata$population을 숫자형으로 바꿔줍니다. 그런데 숫자데이터에 콤머가 있으므로 콤머를 다 제거해주고 숫자형으로 바꿉니다.

코드는 아래와 같습니다.

statdata$population <- as.numeric(gsub(",", "", statdata$population))

자 이제 플로팅을 해보죠. ggplot2를 로딩한 다음에 바로 찍습니다. ggplot2를 설치하지 않으셨으면 먼저 설치하셔야 합니다.

install.packages("ggplot2") # 설치를 안했으면 먼저 설치부터...

library(ggplot2) # 로딩
ggplot(statdata, aes(x=month, y=population)) + geom_line()

플로팅한 그림은 아래와 같습니다.

나왔네요. 그런데 회색배경에 검은선이라 이쁘지 않네요.
선에 색을 넣어 봅니다.

ggplot(statdata, aes(x=month, y=population)) + geom_line(colour="blue")

조금 낫긴하지만 역시 허전합니다.
아래가 비어서 그런것 같으니 선을 그리지 말고 채우기를 이용해서 그려보죠.
사실 이런류의 데이터는 색을 채우지 않고 선으로 보는 것이 데이터를 보기에는 더 좋습니다만 누군가에게 던져 줄때는 예쁘게 출력하는 것도 중요합니다.
본인이 보는 그래프는 선으로 된 것이면 충분하지만 누군가에게 보여주는 그래프는 알록달록해야 합니다.


gplot(statdata, aes(x=month, y=population)) + geom_area()

찍었습니다. 그런데 어라? 그래프의 모양이 바뀐것 같습니다. 자세히 보니 Y축이 영역(range)가 바뀐것 같은데 그것 때문에 밋밋해진 것이군요.
geom_area는 기본적으로 Y축의 0값부터 채워 넣기 때문에 geom_line과는 다르게 반응합니다.
그래서 Y축의 레인지를 강제로 고쳐줘야 합니다. 밑부분의 넙다란 부분을 잘라서 없애버리는 것입니다.


ggplot(statdata, aes(x=month, y=population)) + geom_area() + coord_cartesian(ylim = c(23500, 26500))

그럴듯하게 나오네요. 그런데 여전히 색이 단조롭네요.
테두리의 선색과 채울때 쓴 색을 다르게 줘서 입체감을 조금 살려보죠. 조금 옅은 회색과 조금 진한 회색을 써보겠습니다.


ggplot(statdata, aes(x=month, y=population)) + geom_area(colour="gray10", fill="gray50") + coord_cartesian(ylim = c(23500, 26500))

조금 괜찮아졌습니다만 역시 흑백보다는 칼라를 넣는 것이 좋을 것 같네요.
삷이 우울해질것만 같습니다.
제가 좋아하는 보라색을 넣어봅니다.

ggplot(statdata, aes(x=month, y=population)) + geom_area(colour="gray10", fill="gray50") + coord_cartesian(ylim = c(23500, 26500))

유후~ 괜찮아졌네요.
자. 이제 대충 색은 되었고 나머지를 조금 더 손을 봐보죠.
Y축의 값은 단위를 천명으로 한 숫자입니다. 통계청 데이터의 설명에 그렇게 나와 있습니다.
원래 숫자대로 바꿔보죠. 값에 곱하기 1000을 해서 원래 숫자로 바꿉니다.
귀찮으니 이쯤에서 처음부터 데이터를 다시 로딩해서 바꿔버립니다. 기존 데이터에 그냥해도 무방합니다.

statdata <- read.table(file=textConnection(econonic_activity_population), header = TRUE, sep = ";", quote = ""'", as.is=TRUE,colClasses=c("character", "character"))

statdata$month <- as.Date(paste(statdata$month, ".01", sep=""), "%Y.%m.%d", tz="Asia/Seoul")
statdata$population <- as.numeric(gsub(",", "", statdata$population)) * 1000

네 바꿨습니다. Y축 레인지를 조절하는 값도 1000을 곱해서 바꿔줘야 하는것을 기억하시구요.
이제 Y축의 레이블값의 숫자들에게 콤머를 찍어줍니다. 콤머를 찍으려면 scales 패키지를 로딩해야 합니다.

library(scales)
ggplot(statdata, aes(x=month, y=population)) + geom_area(colour="#5c0ab9", fill="#8a4fcd") + coord_cartesian(ylim = c(23500000, 26500000)) + scale_y_continuous(labels=comma)

이제 X축의 레이블들을 수정해봅니다. 2011-01 처럼 되어 있는 것을 2011년 011월 이렇게 바꿔줄 것입니다.
한글 폰트를 지정해 주시는 것을 잊지 말아야 합니다.. 저는 맥을 사용하므로 애플산돌고딕네오를 적었습니다만 Windows 사용자라면 “맑은 고딕”같은 것을 사용해주세요. 폰트를 정확히 지정하지 않으면 한글이 출력되지 않습니다.


ggplot(statdata, aes(x=month, y=population)) + geom_area(colour="#5c0ab9", fill="#8a4fcd") + coord_cartesian(ylim = c(23500000, 26500000)) + scale_y_continuous(labels=comma) + scale_x_date(labels = date_format("%Y년 %m월")) + theme(axis.text.x = element_text(family="Apple SD Gothic Neo"))

자! 되었습니다.
이제 마지막으로 X축과 Y축의 타이틀을 한글로 바꿔줍니다.
month와  population을 년/월과 경제활동인구라는 말로 바꿔줄 것입니다.
그러면서 코드를 좀 깔끔하게 정리해 보죠. 한줄에 너무 덕지덕지 다 붙여 놓으면 나중에 찾아서 고치기가 어렵습니다.


ggp <- ggplot(statdata, aes(x=month, y=population))
ggp <- ggp + geom_area(colour="#5c0ab9", fill="#8a4fcd")
ggp <- ggp + coord_cartesian(ylim = c(23500000, 26500000))
ggp <- ggp + scale_y_continuous(labels=comma)
ggp <- ggp + scale_x_date(labels = date_format("%Y년 %m월"))
ggp <- ggp + xlab("년도/월") + ylab("경제활동인구")
theme.title <- element_text(family="Apple SD Gothic Neo", face="bold", size=12, angle=00, hjust=0.54, vjust=0.5)
theme.text <- element_text(family="Apple SD Gothic Neo", size=10)
ggp <- ggp + theme(axis.title.x = theme.title, axis.title.y = theme.title, axis.text.x = theme.text)
ggp
rm(theme.title)
rm(theme.text)
gc()

드디어 완성입니다.
아주 이쁘지는 않지만 그럭저럭 보여줄만한 수준이 되는 것 같습니다.

다음 포스트에서는 플롯의 영역별로 색을 지정하는 것을 해보죠.