본문 바로가기
R

[R] 데이터 시각화 및 EDA

by 빵으니 2020. 7. 8.
Chap04-2

시각화

EDA 연습

상관관계가 높은 변수쌍 찾기

Data set - mtcars - R 기본 내장

  • Motor Trend Car Road Test
  • Motor Trend 잡지로 부터 추출된 자료
  • 1973~1974년도 각기 종류가 다른 32대의 자동차 자료
  • mpg(Miles/gallon) : 연비
  • cyl(Number of cylinders) : 실린더 수
  • disp(Displacement) : 배기량
  • hp(Gross horsepower) : 마력
  • drat(Rear axle ratio) : 후방 차축 비율
  • wt(Weight) : 차체 무게
  • qsec (1/4 mile time) : 400m 까기 걸리는 시간
  • vs(V/S)
  • am (Transmission 0 = auto, 1 = manual)
  • gear (Number of forward gears) : 전진장치 개수
  • carb (Number of carburetors) : 기화기 수
In [2]:
# 데이터 로드
# mtcars R
df <- mtcars
head(df)
mpgcyldisphpdratwtqsecvsamgearcarb
Mazda RX421.0 6 160 110 3.90 2.62016.460 1 4 4
Mazda RX4 Wag21.0 6 160 110 3.90 2.87517.020 1 4 4
Datsun 71022.8 4 108 93 3.85 2.32018.611 1 4 1
Hornet 4 Drive21.4 6 258 110 3.08 3.21519.441 0 3 1
Hornet Sportabout18.7 8 360 175 3.15 3.44017.020 0 3 2
Valiant18.1 6 225 105 2.76 3.46020.221 0 3 1
In [4]:
str(df)
# 11개의 변수 32개의 데이터
'data.frame':	32 obs. of  11 variables:
 $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
 $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
 $ disp: num  160 160 108 258 360 ...
 $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
 $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
 $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
 $ qsec: num  16.5 17 18.6 19.4 17 ...
 $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
 $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
 $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
 $ carb: num  4 4 1 1 2 1 4 2 2 4 ...
In [5]:
# 모든 변수 산점도 그리기
plot(df[,c(1:5)])
plot(df[,c(6:11)])
In [6]:
# 위 산점도 분석 결과 mpg~disp 상관관계가 있어보이므로 따로 그려보기
plot(df$mpg ~ df$disp)
In [8]:
# 상관계수 구하기 - 상관계수 높음, 두 변수 좀 더 자세히 분석
# -1 < 상관계수 < 1
cor(df$mpg, df$disp)
-0.847551379262479
In [10]:
# mpg 아웃라이어 확인
boxplot(df$mpg)

# 아웃라이어는 없고 데이터가 위쪽에 좀 더 분포되어 있음
In [13]:
# 히스토그램 - 분산 상태 확인
hist(df$mpg)
In [14]:
# 히스토그램 - 분산 상태 확인 2
hist(df$mpg, breaks = 10)
In [15]:
# disp 아웃라이어 확인 
boxplot(df$disp)
# 아웃라이어는 없고 110~320에 몰려있음
In [16]:
# 히스토그램
hist(df$disp)

mpg, disp

  • 두 변수 모두 이상점 없음
  • 두 변수 상관관계가 있음을 방해하는 요소는 없어 보임
  • 확증을 하기 위해서는 가설검증과 회귀분석 진행
  • EDA 단계는 증거를 수집하고 특징을 찾는 것

다이아몬드 데이터 분석하기 - 가격에 영향을 미치는 것은?

DataSet - diamonds

  • ggplot2 패키지에 포함
  • 캐럿, 가격, 컷팅방법, 컬러등 다이아몬드 정보
In [17]:
library('ggplot2')
Warning message:
"package 'ggplot2' was built under R version 3.6.3"
In [19]:
# 데이터 로드
df <- diamonds
str(df)
# tibble의 형태로 데이터 저장되어 있음
tibble [53,940 x 10] (S3: tbl_df/tbl/data.frame)
 $ carat  : num [1:53940] 0.23 0.21 0.23 0.29 0.31 0.24 0.24 0.26 0.22 0.23 ...
 $ cut    : Ord.factor w/ 5 levels "Fair"<"Good"<..: 5 4 2 4 2 3 3 3 1 3 ...
 $ color  : Ord.factor w/ 7 levels "D"<"E"<"F"<"G"<..: 2 2 2 6 7 7 6 5 2 5 ...
 $ clarity: Ord.factor w/ 8 levels "I1"<"SI2"<"SI1"<..: 2 3 5 4 2 6 7 3 4 5 ...
 $ depth  : num [1:53940] 61.5 59.8 56.9 62.4 63.3 62.8 62.3 61.9 65.1 59.4 ...
 $ table  : num [1:53940] 55 61 65 58 58 57 57 55 61 61 ...
 $ price  : int [1:53940] 326 326 327 334 335 336 336 337 337 338 ...
 $ x      : num [1:53940] 3.95 3.89 4.05 4.2 4.34 3.94 3.95 4.07 3.87 4 ...
 $ y      : num [1:53940] 3.98 3.84 4.07 4.23 4.35 3.96 3.98 4.11 3.78 4.05 ...
 $ z      : num [1:53940] 2.43 2.31 2.31 2.63 2.75 2.48 2.47 2.53 2.49 2.39 ...
In [25]:
# 관측치가 많아 data 임의갯수 추출 - sample(10,2) 10개 중 2개 추출
Sample <- df[sample(nrow(df), 300),]   # 53940개 중 300개 추출
attach(Sample)
The following objects are masked from Sample (pos = 3):

    carat, clarity, color, cut, depth, price, table, x, y, z

The following objects are masked from Sample (pos = 4):

    carat, clarity, color, cut, depth, price, table, x, y, z

In [26]:
str(Sample)
tibble [300 x 10] (S3: tbl_df/tbl/data.frame)
 $ carat  : num [1:300] 1.63 0.36 0.85 1.01 0.51 0.51 0.5 0.77 0.42 1.04 ...
 $ cut    : Ord.factor w/ 5 levels "Fair"<"Good"<..: 5 3 1 1 4 5 4 4 4 4 ...
 $ color  : Ord.factor w/ 7 levels "D"<"E"<"F"<"G"<..: 4 3 5 5 1 4 2 1 4 6 ...
 $ clarity: Ord.factor w/ 8 levels "I1"<"SI2"<"SI1"<..: 5 5 1 3 3 4 5 4 4 3 ...
 $ depth  : num [1:300] 61.7 61.3 61 65.3 62.7 61.7 62.2 61.3 59.8 62.5 ...
 $ table  : num [1:300] 55 54 61 61 59 57 58 60 58 62 ...
 $ price  : int [1:300] 15840 781 1324 3869 1574 1438 1675 3428 847 4252 ...
 $ x      : num [1:300] 7.6 4.63 6.2 6.23 5.08 5.12 5.03 5.92 4.86 6.45 ...
 $ y      : num [1:300] 7.56 4.65 6 6.18 5.06 5.15 5.06 5.89 4.9 6.39 ...
 $ z      : num [1:300] 4.68 2.84 3.73 4.05 3.18 3.17 3.14 3.62 2.92 4.01 ...
In [27]:
# 가격 분석
boxplot(price)
In [28]:
# 가격 이상치 - EDA로 원인 찾기
# price와 관련된 그래프 그리기
par(mfrow = c(3,3))
plot(data=Sample, price~.) # y축(종속변수) price
In [29]:
# price에 carat, x, y, z 등이 영향이 있어 보임
par(mfrow = c(2,2))
plot(price~carat + x + y + z)
In [30]:
# 상관 계수 구하기
Sample2 <- data.frame(price, carat, x, y ,z)
cor(Sample2)
pricecaratxyz
price1.00000000.93293800.90003600.90266530.8899867
carat0.93293801.00000000.97485680.97304690.9681682
x0.90003600.97485681.00000000.99605650.9844891
y0.90266530.97304690.99605651.00000000.9916431
z0.88998670.96816820.98448910.99164311.0000000
  • price에 carat, y, x, z 순으로 영향을 미치는 것으로 보임
  • x, y는 상관계수 거의 1
  • 원인을 찾는 것이 더 어려움, 잠정적 결론
  • EDA는 결론보다 탐색하면서 궁금증을 가지고 원인을 찾는 것
In [31]:
# price, carat, x 특징 파악
par(mfrow = c(1,3))
boxplot(price, main='price')
boxplot(carat, main='carat')
boxplot(x, main='x')
price, carat에 이상치가 많음 -> carat이 price에 이상치가 생기도록 영향을 미쳤을 수 있음
In [32]:
# carat 오름차순 정렬
reCarat <- carat[order(carat)]
par(mfrow = c(1,1))
plot(reCarat)
  • carat 이 2차 함수와 비슷
  • carat 이 올라갈수록 값이 급격히 커짐
  • 이런 성향 때문에 이상치 발생 예상
In [45]:
# carat 값 급격히 커지는 부분 제거
Sample2 <- subset(Sample, subset = (Sample$carat < 0.3))
par(mfrow = c(1,2))
boxplot(Sample$carat, main='carat 0.3 포함')
boxplot(Sample2$carat, main='carat 0.3 미포함')
In [47]:
# 가격 분석 - 0.3 carat 넘으면 가격 이상치 발생
boxplot(Sample2$price)

자료를 탐색하고 의문점이 생기면 그 원인을 찾는 것이 탐색적 자료 분석 (EDA)

섬세한 그래프를 그려 데이터 분석하기 : ggplot()

In [48]:
# 데이터 확인
library('ggplot2')
library('ggthemes')
str(diamonds)
Warning message:
"package 'ggthemes' was built under R version 3.6.3"
tibble [53,940 x 10] (S3: tbl_df/tbl/data.frame)
 $ carat  : num [1:53940] 0.23 0.21 0.23 0.29 0.31 0.24 0.24 0.26 0.22 0.23 ...
 $ cut    : Ord.factor w/ 5 levels "Fair"<"Good"<..: 5 4 2 4 2 3 3 3 1 3 ...
 $ color  : Ord.factor w/ 7 levels "D"<"E"<"F"<"G"<..: 2 2 2 6 7 7 6 5 2 5 ...
 $ clarity: Ord.factor w/ 8 levels "I1"<"SI2"<"SI1"<..: 2 3 5 4 2 6 7 3 4 5 ...
 $ depth  : num [1:53940] 61.5 59.8 56.9 62.4 63.3 62.8 62.3 61.9 65.1 59.4 ...
 $ table  : num [1:53940] 55 61 65 58 58 57 57 55 61 61 ...
 $ price  : int [1:53940] 326 326 327 334 335 336 336 337 337 338 ...
 $ x      : num [1:53940] 3.95 3.89 4.05 4.2 4.34 3.94 3.95 4.07 3.87 4 ...
 $ y      : num [1:53940] 3.98 3.84 4.07 4.23 4.35 3.96 3.98 4.11 3.78 4.05 ...
 $ z      : num [1:53940] 2.43 2.31 2.31 2.63 2.75 2.48 2.47 2.53 2.49 2.39 ...
In [49]:
# x와 price 산점도 그리기
ggplot(diamonds, aes(x=x, y=price)) + geom_point()
In [51]:
# clarity 변수, 컬러에 추가
ggplot(diamonds, aes(x=x, y=price, colour=clarity)) + geom_point()
# clarity는 여러 값에 분포되어 있어 price에 영향은 없는 것으로 보임
# 노란색이 아래, 진한색이 위쪽으로 분포하면 가격에 영향이 있을 것임
In [52]:
# 테마 적용
ggplot(diamonds, aes(x=x, y=price, colour=clarity)) + geom_point() + theme_solarized_2()
In [54]:
# 데이터 겹침 조절 - alpha
ggplot(diamonds, aes(x=x, y=price, colour=clarity)) + 
geom_point(alpha=0.03) +
guides(colour = guide_legend(override.aes = list(alpha=1))) + 
theme_solarized_2()
In [56]:
# x축 범위 조절(3~9), 수평선으로 평균 표시 geom_hline()
ggplot(diamonds, aes(x=x, y=price, colour=clarity)) +
geom_point(alpha=0.03) +
geom_hline(yintercept=mean(diamonds$price), color="turquoise3", alpha=.8) + 
guides(colour = guide_legend(override.aes = list(alpha = 1))) +
xlim(3,9) +
theme_solarized_2()
Warning message:
"Removed 50 rows containing missing values (geom_point)."

시계열 데이터, 라인 그래프로 나타내기

In [57]:
# 데이터 로드 - 간단한 시간대별 매출 자료
TS <- read.csv('R-ggagi-data/example_ts.csv')
str(TS)
head(TS)
'data.frame':	24 obs. of  2 variables:
 $ Date : num  2014 2014 2014 2014 2014 ...
 $ Sales: int  2000 2300 2400 2500 2800 3100 2900 3000 3300 3400 ...
DateSales
2014.012000
2014.022300
2014.032400
2014.042500
2014.052800
2014.063100
In [59]:
# 시각화 geom_line()
ggplot(TS, aes(x=Date, y=Sales)) + geom_line()
In [61]:
# x 축에 날짜 모두 표시하기 - factor()
# group=1 하나의 라인으로 연속적으로 그릴 때 사용
ggplot(TS, aes(x=factor(Date), y=Sales, group=1)) + geom_line()
In [62]:
# 점 추가 geom_point()
ggplot(TS, aes(x=factor(Date), y=Sales, group=1)) + geom_line() + geom_point()
In [63]:
# 테마 적용
ggplot(TS, aes(x=factor(Date), y=Sales, group=1)) + geom_line() + geom_point() + theme_light()
In [64]:
# 디자인 값 변경
ggplot(TS, aes(x=factor(Date), y=Sales, group=1)) + 
geom_line(colour="orange1", size=1) + 
geom_point(colour="orangered2", size=4) + 
theme_light()
In [65]:
# title, x, y 축 이름 추가
ggplot(TS, aes(x=factor(Date), y=Sales, group=1)) +
geom_line(colour="orange1", size=1) + 
geom_point(colour="orangered2", size=4) + 
xlab("년도")+ ylab("매출") + ggtitle("A기업 월별 매출") + 
theme_light()

# x label, y label

dplyr 패키지로 데이터 선택해 그래프로 나타내기 : filter()

  • ggplot2를 만든 Hadley Wickham 교수가 data.frame 객체를 쉽게 다루기 위해 만든 패키지
In [66]:
install.packages('dplyr')
package 'dplyr' successfully unpacked and MD5 sums checked
Warning message:
"cannot remove prior installation of package 'dplyr'"Warning message in file.copy(savedcopy, lib, recursive = TRUE):
"C:\Users\205\.conda\envs\r_study\Lib\R\library\00LOCK\dplyr\libs\x64\dplyr.dll를 C:\Users\205\.conda\envs\r_study\Lib\R\library\dplyr\libs\x64\dplyr.dll로 복사하는데 문제가 발생했습니다: Permission denied"Warning message:
"restored 'dplyr'"
The downloaded binary packages are in
	C:\Users\205\AppData\Local\Temp\Rtmp6hBIfL\downloaded_packages
In [67]:
library('dplyr')
library('ggplot2')
library('ggthemes')
Warning message:
"package 'dplyr' was built under R version 3.6.3"
Attaching package: 'dplyr'

The following objects are masked from 'package:stats':

    filter, lag

The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union

In [71]:
# 데이터 로드 - 전국 인구조사 자료
DF <- read.csv('R-ggagi-data/example_population_f.csv')
DF <- DF[,-1] # 첫번째 열을 ID 숫자이므로 삭제
DF <- tbl_df(DF) # tbl_df ( tibble diff라고도 함 ) 데이터 프레임의 변형, dataframe + dplyr 속성추가
head(DF)
ProvincesCityPopulationHouseholdsPersInHouMaleFemaleSexRatio
서울특별시종로구 155695 72882 2.14 76962 78733 0.98
서울특별시중구 126817 59614 2.13 63292 63525 1.00
서울특별시용산구 235186 108138 2.17 114119 121067 0.94
서울특별시성동구 298145 126915 2.35 148265 149880 0.99
서울특별시광진구 362197 158769 2.28 177946 184251 0.97
서울특별시동대문구 362604 160110 2.26 181825 180779 1.01
In [72]:
# 충청도 도시들의 인구 그래프 그리기 - filter() 조건 vs subset()
DF2 <- filter(DF, Provinces=='충청북도' | Provinces=='충청남도')
head(DF2)
ProvincesCityPopulationHouseholdsPersInHouMaleFemaleSexRatio
충청북도 청주시 832387 334276 2.49 417505 414882 1.01
충청북도 청주시 상당구 178536 70873 2.52 89037 89499 0.99
충청북도 청주시 서원구 222817 88212 2.53 110729 112088 0.99
충청북도 청주시 흥덕구 251652 101572 2.48 126533 125119 1.01
충청북도 청주시 청원구 179382 73619 2.44 91206 88176 1.03
충청북도 충주시 208173 87078 2.39 104828 103345 1.01
In [73]:
# 그래프 그리기
Graph <- ggplot(DF2, aes(x=City, y=Population, fill=Provinces)) + 
geom_bar(stat='identity') + theme_wsj()
Graph
In [75]:
# 오름차순 정렬 - reorder()
GraphReorder <- ggplot(DF2, aes(x=reorder(City, Population), y=Population, fill=Provinces))+
geom_bar(stat='identity') + theme_wsj()
GraphReorder
In [78]:
# 남자비율이 높고 1인가구가 많은 도시
DF3 <- filter(DF, SexRatio > 1, PersInHou < 2)
DF3
ProvincesCityPopulationHouseholdsPersInHouMaleFemaleSexRatio
인천광역시옹진군 20825 11172 1.86 11715 9110 1.29
강원도 화천군 26790 13433 1.99 14989 11801 1.27
강원도 고성군 30066 15485 1.94 16109 13957 1.15
충청북도 괴산군 38027 19145 1.99 19309 18718 1.03
전라남도 신안군 43566 22248 1.96 22899 20667 1.11
경상북도 울릉군 10304 5365 1.92 5518 4786 1.15
In [80]:
# 시각화
Graph <- ggplot(DF3, aes(x=City, y=SexRatio, fill=Provinces)) + 
geom_bar(stat='identity') + theme_wsj()
Graph

dplyr 패키지로 데이터 만들고 그래프로 나타내기 - mutate()

In [89]:
library('dplyr')
library('ggplot2')
library('ggthemes')
In [90]:
# 데이터 로드 - 전국 인구조사 자료
DF <- read.csv('R-ggagi-data/example_population_f.csv')
DF <- DF[,-1] # 첫번째 열은 ID 숫자이므로 삭제
DF <- tbl_df(DF) 
# tbl_df (tibble diff) 데이터 프레임의 변형, dataframe + dplyr 속성 추가

head(DF)
ProvincesCityPopulationHouseholdsPersInHouMaleFemaleSexRatio
서울특별시종로구 155695 72882 2.14 76962 78733 0.98
서울특별시중구 126817 59614 2.13 63292 63525 1.00
서울특별시용산구 235186 108138 2.17 114119 121067 0.94
서울특별시성동구 298145 126915 2.35 148265 149880 0.99
서울특별시광진구 362197 158769 2.28 177946 184251 0.97
서울특별시동대문구 362604 160110 2.26 181825 180779 1.01
In [99]:
# 남녀 비율 문자로 나타내는 변수 추가 - mutate() vs cbind()
DF <- mutate(DF,
            SexF = ifelse(SexRatio < 1, '여자 비율 높음', 
                          ifelse(SexRatio > 1, '남자 비율 높음','남여 비율 같음')))
                   # if(조건, A, B) : 참 이면 A 아니면 B

head(DF)
ProvincesCityPopulationHouseholdsPersInHouMaleFemaleSexRatiosexFSexF
서울특별시 종로구 155695 72882 2.14 76962 78733 0.98 여자 비율 높음여자 비율 높음
서울특별시 중구 126817 59614 2.13 63292 63525 1.00 남여 비율 같음남여 비율 같음
서울특별시 용산구 235186 108138 2.17 114119 121067 0.94 여자 비율 높음여자 비율 높음
서울특별시 성동구 298145 126915 2.35 148265 149880 0.99 여자 비율 높음여자 비율 높음
서울특별시 광진구 362197 158769 2.28 177946 184251 0.97 여자 비율 높음여자 비율 높음
서울특별시 동대문구 362604 160110 2.26 181825 180779 1.01 남자 비율 높음남자 비율 높음
In [102]:
# sexF 순서있는 변수로 변환
DF$SexF <- factor(DF$SexF)
DF$SexF <- ordered(DF$SexF, c('여자 비율 높음', '남여 비율 같음', '남자 비율 높음'))
In [103]:
# 경기도 데이터 적재
DF2 <- filter(DF, Provinces=='경기도')
In [105]:
# 시각화 - 경기도 남자 비율 높음
Graph <- ggplot(DF2, aes(x=City, y=(SexRatio-1), fill=SexF)) + 
geom_bar(stat='identity') + theme_wsj()
Graph
In [106]:
# 서울 데이터 적재
DF3 <- filter(DF, Provinces=='서울특별시')
In [107]:
# 시각화 - 서울 여자 비율 높음
Graph2 <- ggplot(DF3, aes(x=City, y=(SexRatio-1), fill=SexF)) + 
geom_bar(stat='identity') + theme_wsj()
Graph2

reshape2 패키지 melt()이용. 데이터 가공 후 그래프 나타내기

  • melt() : 명목형 변수로 만들어 줌
In [124]:
library('dplyr')
library('ggplot2')
library('ggthemes')
library('reshape2')
In [125]:
# 데이터 로드 - 전국 인구조사 자료
DF <- read.csv('R-ggagi-data/example_population_f.csv')
DF <- DF[,-1]
DF <- tbl_df(DF)
head(DF)
ProvincesCityPopulationHouseholdsPersInHouMaleFemaleSexRatio
서울특별시종로구 155695 72882 2.14 76962 78733 0.98
서울특별시중구 126817 59614 2.13 63292 63525 1.00
서울특별시용산구 235186 108138 2.17 114119 121067 0.94
서울특별시성동구 298145 126915 2.35 148265 149880 0.99
서울특별시광진구 362197 158769 2.28 177946 184251 0.97
서울특별시동대문구 362604 160110 2.26 181825 180779 1.01
In [126]:
# 도별 합계 - 도시별(group by) 계산 summarise() 합계 sum()
group <- group_by(DF, Provinces) # 도시별
DF2 <- summarise(group, SumPopulation=sum(Population), Male=sum(Male), Female=sum(Female))
DF2
`summarise()` ungrouping output (override with `.groups` argument)
ProvincesSumPopulationMaleFemale
강원도 1547166 780487 766679
경기도 18723822 9401705 9322117
경상남도 4428762 2235747 2193015
경상북도 3215695 1616853 1598842
광주광역시 1476974 731808 745166
대구광역시 2491137 1239275 1251862
대전광역시 1525656 763262 762394
부산광역시 3517491 1737975 1779516
서울특별시 10078850 4962774 5116076
울산광역시 1169768 602945 566823
인천광역시 2914271 1464320 1449951
전라남도 1902638 950693 951945
전라북도 2523806 1252574 1271232
제주특별자치도 615250 308627 306623
충청남도 2671383 1355937 1315446
충청북도 2414568 1215413 1199155
In [127]:
# melt(DF2, measure.vars=바꿀 변수들) - 성별은 하나의 명목형 변수로 처리하고 싶을 때
DF3 <- melt(DF2, measure.vars = c('Male','Female'))
In [128]:
DF2
DF3
ProvincesSumPopulationMaleFemale
강원도 1547166 780487 766679
경기도 18723822 9401705 9322117
경상남도 4428762 2235747 2193015
경상북도 3215695 1616853 1598842
광주광역시 1476974 731808 745166
대구광역시 2491137 1239275 1251862
대전광역시 1525656 763262 762394
부산광역시 3517491 1737975 1779516
서울특별시 10078850 4962774 5116076
울산광역시 1169768 602945 566823
인천광역시 2914271 1464320 1449951
전라남도 1902638 950693 951945
전라북도 2523806 1252574 1271232
제주특별자치도 615250 308627 306623
충청남도 2671383 1355937 1315446
충청북도 2414568 1215413 1199155
ProvincesSumPopulationvariablevalue
강원도 1547166 Male 780487
경기도 18723822 Male 9401705
경상남도 4428762 Male 2235747
경상북도 3215695 Male 1616853
광주광역시 1476974 Male 731808
대구광역시 2491137 Male 1239275
대전광역시 1525656 Male 763262
부산광역시 3517491 Male 1737975
서울특별시 10078850 Male 4962774
울산광역시 1169768 Male 602945
인천광역시 2914271 Male 1464320
전라남도 1902638 Male 950693
전라북도 2523806 Male 1252574
제주특별자치도 615250 Male 308627
충청남도 2671383 Male 1355937
충청북도 2414568 Male 1215413
강원도 1547166 Female 766679
경기도 18723822 Female 9322117
경상남도 4428762 Female 2193015
경상북도 3215695 Female 1598842
광주광역시 1476974 Female 745166
대구광역시 2491137 Female 1251862
대전광역시 1525656 Female 762394
부산광역시 3517491 Female 1779516
서울특별시 10078850 Female 5116076
울산광역시 1169768 Female 566823
인천광역시 2914271 Female 1449951
전라남도 1902638 Female 951945
전라북도 2523806 Female 1271232
제주특별자치도 615250 Female 306623
충청남도 2671383 Female 1315446
충청북도 2414568 Female 1199155
In [130]:
# 컬럼명 변경 - colnames
colnames(DF3)[3] <- 'Sex'
colnames(DF3)[4] <- 'Population'
head(DF3)
ProvincesSumPopulationSexPopulation
강원도 1547166 Male 780487
경기도 18723822 Male 9401705
경상남도 4428762 Male 2235747
경상북도 3215695 Male 1616853
광주광역시 1476974 Male 731808
대구광역시 2491137 Male 1239275
In [132]:
# 새 변수 추가(남녀 비율 추가) - mutate()
DF4 <- mutate(DF3, Ratio = Population/SumPopulation)

# round() 함수 사용해서 소숫점 몇 자리 까지 나타낼 지 설정
DF4$Ratio <- round(DF4$Ratio, 3) 
head(DF4)
ProvincesSumPopulationSexPopulationRatio
강원도 1547166 Male 780487 0.504
경기도 18723822 Male 9401705 0.502
경상남도 4428762 Male 2235747 0.505
경상북도 3215695 Male 1616853 0.503
광주광역시 1476974 Male 731808 0.495
대구광역시 2491137 Male 1239275 0.497
In [138]:
# 시각화
G1 <- ggplot(DF4, aes(x=Provinces, y=Ratio, fill=Sex)) + 
geom_bar(stat='identity') +
# coord_cartesian(ylim=c(0.45, 0.55)) +  # 0.45~0.55 범위만 확대해서 보자
theme_wsj()

G2 <- geom_text(aes(y=Ratio, label=Ratio), colour='white')

G1 + G2
In [139]:
# 시각화 - coord_cartesian() 부분 확대
G1 <- ggplot(DF4, aes(x=Provinces, y=Ratio, fill=Sex)) + 
geom_bar(stat='identity') +
coord_cartesian(ylim=c(0.45, 0.55)) +  # 0.45~0.55 범위만 확대해서 보자
theme_wsj()

G2 <- geom_text(aes(y=Ratio, label=Ratio), colour='white')

G1 + G2
In [140]:
# 비율값 위치 조정
DF4 <- mutate(DF4, Position = ifelse(Sex == 'Male', 0.475, 0.525))
head(DF4)
ProvincesSumPopulationSexPopulationRatioPosition
강원도 1547166 Male 780487 0.504 0.475
경기도 18723822 Male 9401705 0.502 0.475
경상남도 4428762 Male 2235747 0.505 0.475
경상북도 3215695 Male 1616853 0.503 0.475
광주광역시 1476974 Male 731808 0.495 0.475
대구광역시 2491137 Male 1239275 0.497 0.475
In [141]:
# 시각화 - geom_text()
G1 <- ggplot(DF4, aes(x=Provinces, y=Ratio, fill=Sex)) + 
geom_bar(stat='identity') + 
coord_cartesian(ylim = c(0.45, 0.55)) + theme_wsj()

G2 <- geom_text(aes(y=Position, label=Ratio), colour='white')

G1 + G2

클리블랜드 점 그래프 그리기

In [142]:
require("dplyr")
require("ggplot2")
require("ggthemes")
In [143]:
# 데이터 로드 - 전국 인구조사 자료
DF <- read.csv('R-ggagi-data/example_population_f.csv')
DF <- DF[,-1] 
DF <- tbl_df(DF) 
head(DF)
ProvincesCityPopulationHouseholdsPersInHouMaleFemaleSexRatio
서울특별시종로구 155695 72882 2.14 76962 78733 0.98
서울특별시중구 126817 59614 2.13 63292 63525 1.00
서울특별시용산구 235186 108138 2.17 114119 121067 0.94
서울특별시성동구 298145 126915 2.35 148265 149880 0.99
서울특별시광진구 362197 158769 2.28 177946 184251 0.97
서울특별시동대문구 362604 160110 2.26 181825 180779 1.01
In [144]:
# 남녀비율 명목형 변수로 만들기
DF2 <- mutate(DF, SexF = ifelse(SexRatio > 1, '남자 비율 높음',
                               ifelse(SexRatio == 1, '남녀 비율 같음', '여자 비율 높음')))
In [145]:
# 경기도 데이터 적재
DF3 <- filter(DF2, Provinces=='경기도')
In [146]:
# 시각화 - geom_segment() 
# x 축 시작위치 : xend = 0, y축 명목형 변수 : yend = City
Graph <- ggplot(DF3, aes(x=(SexRatio-1), y=reorder(City, SexRatio))) + 
geom_segment(aes(yend=City), xend=0, colour='grey50') + 
geom_point(size=4, aes(colour=SexF)) + theme_minimal()
Graph

시간에 따른 연령별 인구 변화 그래프 그리기

  • DataSet : 통계청 사이트에서 Download (www.kosis.or.kr)
In [147]:
library("dplyr")
library("ggplot2")
library("ggthemes")
library("reshape2")
library("scales") # 2e_07 => 200,000 표시
Warning message:
"package 'scales' was built under R version 3.6.3"
In [148]:
# 데이터 로드 - 시간별 인구변화 자료
DF <- read.csv('R-ggagi-data/example_population2.csv')
DF <- tbl_df(DF)
In [149]:
head(DF)
TimeSexPopulationage0to4age5to9age10to14age15to19age20to24age25to29age30to34...age60to64age65to69age70to74age75to79age80to84age85to89age90to94age95to99age100to104age105to109
1960 Male 125506912383544 1733443 1358903 1248858 1171363 960543 738376 ... 230431 141661 80707 45335 NA NA NA NA NA NA
1960 Female 124616832207268 1617090 1287335 1169586 1151342 972537 817952 ... 288034 204014 129687 65864 NA NA NA NA NA NA
1961 Male 129365832452879 1864580 1402613 1240278 1188724 1017695 765035 ... 239434 141887 84914 47111 NA NA NA NA NA NA
1961 Female 128290902276565 1736162 1332220 1145417 1175745 1010896 844596 ... 296408 202677 139524 69374 NA NA NA NA NA NA
1962 Male 133209832500793 1983775 1448949 1255899 1204229 1065655 793285 ... 241992 148284 86420 49893 NA NA NA NA NA NA
1962 Female 131920472323482 1846082 1369542 1150735 1192695 1051348 874853 ... 296126 212423 140591 76638 NA NA NA NA NA NA
In [150]:
# 남녀를 합쳐 새로운 dataframe 생성 
# 5세 => 10세 단위로 변경
group <- group_by(DF, Time)
DF2 <- summarise(group, s0=sum(age0to4, age5to9),
                 s10=sum(age10to14, age15to19),
                 s20=sum(age20to24, age25to29),
                 s30=sum(age30to34, age35to39),
                 s40=sum(age40to44, age45to49),
                 s50=sum(age50to54, age55to59),
                 s60=sum(age60to64, age65to69),
                 s70=sum(age70to74, age75to79),
                 s80=sum(age80to84, age85to89),
                 s90=sum(age90to94, age95to99),
                 s100=sum(age100to104, age105to109))
`summarise()` ungrouping output (override with `.groups` argument)
In [151]:
head(DF2)
Times0s10s20s30s40s50s60s70s80s90s100
1960 794134550646824255785292645321049641474230864140 321593 NA NA NA
1961 833018651205284393060298791621546271492633880406 340923 NA NA NA
1962 865413252251254513927306129722106971527018898825 353542 NA NA NA
1963 895578653750684590600314863422735711576341911748 357878 NA NA NA
1964 915579755987694640279327114123280241623340912204 379013 NA NA NA
1965 926093859248804654662340090323859981665823934334 397242 NA NA NA
In [154]:
# melt() -여러 컬럼으로 나열된 측정치들을 variable, value의 두 개 컬럼을 사용해 
# 여러 행으로 변환하는 것이 melt( )의 역할
DF3 <- melt(DF2, measure.vars = c('s0', 's10', 's20', 's30', 's40', 's50',
                                 's60', 's70', 's80', 's90', 's100'))
head(DF3)

colnames(DF3) <- c('Time', 'Generation', 'Population')
head(DF3)
Timevariablevalue
1960 s0 7941345
1961 s0 8330186
1962 s0 8654132
1963 s0 8955786
1964 s0 9155797
1965 s0 9260938
TimeGenerationPopulation
1960 s0 7941345
1961 s0 8330186
1962 s0 8654132
1963 s0 8955786
1964 s0 9155797
1965 s0 9260938
In [155]:
# 시각화 -geom_area() 영역 그래프
G1 <- ggplot(DF3, aes(x=Time, y=Population, colour=Generation, fill=Generation)) + 
geom_area(alpha=.6) + theme_wsj()
G1
Warning message:
"Removed 141 rows containing missing values (position_stack)."
In [157]:
# y축 값 변경 - scale_y_continuous(lables = comma)
G2 <- ggplot(DF3, aes(x=Time, y=Population, colour=Generation, fill=Generation)) + 
geom_area(alpha=.6) + theme_wsj()

G2 + scale_y_continuous(labels = comma)
# label 인자를 사용해 y축 레이블을 천 단위마다 콤마로 표시
Warning message:
"Removed 141 rows containing missing values (position_stack)."
In [ ]:

'R' 카테고리의 다른 글

[R] D3js 와 js를 활용한 시각화  (0) 2020.07.09
[R] R 필수 패키지 설치 및 기초  (0) 2020.07.08
[R] 데이터 시각화  (0) 2020.07.08
[R] 기술통계 - 실전예제  (0) 2020.07.08
[R] 기술통계  (0) 2020.07.08

댓글