R에서 다양한 탐색적 데이터분석을 위한 팩키지와 함수가 다수 제공되고 있지만, 데이터과학자에게 딱 이거다하는 도구를 찾기는 힘들다. 특히 요약통계량을 통해 탐색적 데이터분석을 시작할 때 더욱 그렇다.
탐색적 데이터 분석에서 가장 먼저 구조를 살펴보는 것으로 작업을 시작한다. str
, summary
함수가 큰 역할을 수행한다. str
, summary
함수가 제공하는 기능을 tidyverse 팩키지 glimpse
함수가 대신하기도 한다.
한걸음 더 들어가면 숫자형에 대해서는 나름 충분한 정보가 명령어 하나로 제공되지만, 범주형 변수가 섞여 있거나 숫자형 변수에 대해 세밀히 살펴보려면 mosaic::favstats()
함수를 사용해야 하는 번거러음도 존재한다.
# 2. 텍스트 기반 데이터분석 동기 ---------------------------------------
# https://rawgit.com/ropenscilabs/skimr/master/blog.html
## 2.1 구조분석
str(mtcars)
'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 ...
summary(mtcars)
mpg cyl disp hp
Min. :10.40 Min. :4.000 Min. : 71.1 Min. : 52.0
1st Qu.:15.43 1st Qu.:4.000 1st Qu.:120.8 1st Qu.: 96.5
Median :19.20 Median :6.000 Median :196.3 Median :123.0
Mean :20.09 Mean :6.188 Mean :230.7 Mean :146.7
3rd Qu.:22.80 3rd Qu.:8.000 3rd Qu.:326.0 3rd Qu.:180.0
Max. :33.90 Max. :8.000 Max. :472.0 Max. :335.0
drat wt qsec vs
Min. :2.760 Min. :1.513 Min. :14.50 Min. :0.0000
1st Qu.:3.080 1st Qu.:2.581 1st Qu.:16.89 1st Qu.:0.0000
Median :3.695 Median :3.325 Median :17.71 Median :0.0000
Mean :3.597 Mean :3.217 Mean :17.85 Mean :0.4375
3rd Qu.:3.920 3rd Qu.:3.610 3rd Qu.:18.90 3rd Qu.:1.0000
Max. :4.930 Max. :5.424 Max. :22.90 Max. :1.0000
am gear carb
Min. :0.0000 Min. :3.000 Min. :1.000
1st Qu.:0.0000 1st Qu.:3.000 1st Qu.:2.000
Median :0.0000 Median :4.000 Median :2.000
Mean :0.4062 Mean :3.688 Mean :2.812
3rd Qu.:1.0000 3rd Qu.:4.000 3rd Qu.:4.000
Max. :1.0000 Max. :5.000 Max. :8.000
## 2.2 숫자형과 범주형 변수 요약 통계량 한계 ---------------------------
summary(mtcars$mpg) # 숫자형 좋아요
Min. 1st Qu. Median Mean 3rd Qu. Max.
10.40 15.43 19.20 20.09 22.80 33.90
summary(mtcars$cyl) # 범주형 이건 뭐죠???
Min. 1st Qu. Median Mean 3rd Qu. Max.
4.000 4.000 6.000 6.188 8.000 8.000
### 범주형에 대한 충분한 설명이 부족
mosaic::tally(~cyl, data=mtcars)
cyl
4 6 8
11 7 14
table(mtcars$cyl, mtcars$vs) ## 범주에 대한 라벨도 없음
0 1
4 1 10
6 3 4
8 14 0
### 그래서 다음과 같은 팩키지에 함수가 지원되지만, 뭔가 엉뚱한 곳에 가있는 듯한 느낌
mosaic::favstats(~mpg, data=mtcars)
min Q1 median Q3 max mean sd n missing
10.4 15.425 19.2 22.8 33.9 20.09062 6.026948 32 0
skimr
팩키지가 이런 갈증을 해소시킬 수 있을 것으로 보인다.
skim(chickwts)
: 숫자형과 범주형 변수를 구분하고 각 변수 유형에 맞춰 의미있는 요약통계량을 한눈에 제공한다.skimr::skim(chickwts) %>% dplyr::filter(stat == "hist")
: 데이터프레임으로 저장되어 이를 다시 뽑아 사용하기도 유용하다.skim(babynames)
: 문자형에도 잘 동작한다.# 2. 치킨 무게 데이터 --------------------------------------
skim(chickwts)
Numeric Variables
# A tibble: 1 x 13
var type missing complete n mean sd min `25% quantile` median `75% quantile` max hist
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1 weight numeric 0 71 71 261.3099 78.0737 108 204.5 258 323.5 423 ▂▇▂▇▇▃▇▆▂▂
Factor Variables
# A tibble: 1 x 7
var type complete missing n n_unique stat
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr>
1 feed factor 71 0 71 6 casein: 12 horsebean: 10 linseed: 12 meatmeal: 11 soybean: 14 sunflower: 12 NA: 0
skimr::skim(chickwts) %>%
dplyr::filter(stat == "hist")
# A tibble: 1 x 5
var type stat level value
<chr> <chr> <chr> <chr> <dbl>
1 weight numeric hist ▂▇▂▇▇▃▇▆▂▂ 0
# 3. 자동차 데이터 --------------------------------------
skim(mtcars) %>% dplyr::filter(stat=="hist") %>%
as_tibble() %>%
print.listof(locale = locale(encoding = "UTF-8")) %>%
do.call(cbind, .)
var :
[1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear"
[11] "carb"
type :
[1] "numeric" "numeric" "numeric" "numeric" "numeric" "numeric" "numeric"
[8] "numeric" "numeric" "numeric" "numeric"
stat :
[1] "hist" "hist" "hist" "hist" "hist" "hist" "hist" "hist" "hist" "hist"
[11] "hist"
level :
[1] "▂▅▇▇▇▃▁▁▂▂" "▆▁▁▁▃▁▁▁▁▇" "▇▇▅▁▁▇▃▂▁▃" "▆▆▇▂▇▂▃▁▁▁" "▃▇▂▂▃▆▅▁▁▁"
[6] "▂▂▂▂▇▆▁▁▁▂" "▂▃▇▇▇▅▅▁▁▁" "▇▁▁▁▁▁▁▁▁▆" "▇▁▁▁▁▁▁▁▁▆" "▇▁▁▁▆▁▁▁▁▂"
[11] "▆▇▂▁▇▁▁▁▁▁"
value :
[1] 0 0 0 0 0 0 0 0 0 0 0
var type stat level value
[1,] "mpg" "numeric" "hist" "▂▅▇▇▇▃▁▁▂▂" "0"
[2,] "cyl" "numeric" "hist" "▆▁▁▁▃▁▁▁▁▇" "0"
[3,] "disp" "numeric" "hist" "▇▇▅▁▁▇▃▂▁▃" "0"
[4,] "hp" "numeric" "hist" "▆▆▇▂▇▂▃▁▁▁" "0"
[5,] "drat" "numeric" "hist" "▃▇▂▂▃▆▅▁▁▁" "0"
[6,] "wt" "numeric" "hist" "▂▂▂▂▇▆▁▁▁▂" "0"
[7,] "qsec" "numeric" "hist" "▂▃▇▇▇▅▅▁▁▁" "0"
[8,] "vs" "numeric" "hist" "▇▁▁▁▁▁▁▁▁▆" "0"
[9,] "am" "numeric" "hist" "▇▁▁▁▁▁▁▁▁▆" "0"
[10,] "gear" "numeric" "hist" "▇▁▁▁▆▁▁▁▁▂" "0"
[11,] "carb" "numeric" "hist" "▆▇▂▁▇▁▁▁▁▁" "0"
# 4. 붓꽃 데이터 ------------------------------------------
skim(iris)
Numeric Variables
# A tibble: 4 x 13
var type missing complete n mean sd min `25% quantile` median `75% quantile` max hist
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1 Petal.Length numeric 0 150 150 3.758000 1.7652982 1.0 1.6 4.35 5.1 6.9 ▇▃▁▁▂▆▆▃▂▁
2 Petal.Width numeric 0 150 150 1.199333 0.7622377 0.1 0.3 1.30 1.8 2.5 ▇▂▁▂▅▃▁▅▂▃
3 Sepal.Length numeric 0 150 150 5.843333 0.8280661 4.3 5.1 5.80 6.4 7.9 ▂▇▅▇▆▆▅▂▂▂
4 Sepal.Width numeric 0 150 150 3.057333 0.4358663 2.0 2.8 3.00 3.3 4.4 ▁▁▃▃▇▃▂▂▁▁
Factor Variables
# A tibble: 1 x 7
var type complete missing n n_unique stat
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr>
1 Species factor 150 0 150 3 setosa: 50 versicolor: 50 virginica: 50 NA: 0
# 4. 아기 이름 데이터 --------------------------------------
library(babynames)
skim(babynames)
Numeric Variables
# A tibble: 3 x 13
var type missing complete n mean sd min `25% quantile` median `75% quantile` max hist
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1 n integer 0 1858689 1858689 1.833830e+02 1555.3570871 5.000000e+00 7.000000e+00 1.200000e+01 3.200000e+01 9.96800e+04 ▇▁▁▁▁▁▁▁▁▁
2 prop numeric 0 1858689 1858689 1.391443e-04 0.0011702 2.259872e-06 3.900959e-06 7.348183e-06 2.324258e-05 8.15463e-02 ▇▁▁▁▁▁▁▁▁▁
3 year numeric 0 1858689 1858689 1.973376e+03 33.6978783 1.880000e+03 1.950000e+03 1.983000e+03 2.002000e+03 2.01500e+03 ▁▁▂▂▂▂▃▅▆▇
Character Variables
# A tibble: 2 x 9
var type complete missing empty n min max n_unique
* <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 name character 1858689 0 0 1858689 2 15 95025
2 sex character 1858689 0 0 1858689 1 1 2
윈도우 스파크 히스토드램(spark histogram) 표시 문제
“▂▅▇” 기호가 “
<U+2582><U+2585><U+2587>
”으로 표기되는 문제가 있다. 고질적인 문제로 윈도우 환경에서는 아직까지 해결책은 없다. 다만,Sys.setlocale( locale='Chinese' )
명령어를 실행한 후에View
명령어로 확인하는 방법과,print.listof(locale = locale(encoding = "UTF-8"))
명령어를 사용하는 방법이 편법으로 존재한다. 1
GUI가 일반화되기 이전에 데이터를 분석한 경험이 있는 분은 아마도 콘솔에서 그래프를 그려본 향수가 느껴질 수도 있다. 탐색적 데이터분석을 콘솔에서 가볍게 실행해 보는 방법을 살펴보자. 활용될 팩키지는 다음과 같다.
범주형 변수 시각화를 위한 막대그래프, 연속형 단변량 변수 시각화를 위한 분포(density), 히스토그램(histogram), 상자그림(boxplot)이 우선 떠오르고, 시계열 데이터를 위한 자기상관 그래프, 변수간 관계를 일별할 수 있는 산점도가 있다.
# 0. 환경설정 -------------------------------------------------
# devtools::install_github("hadley/colformat")
# devtools::install_github("ropenscilabs/skimr")
# install.packages("txtplot")
library(skimr)
library(tidyverse)
library(txtplot)
## 2.1. 수식 그래프 --------------------------------------
txtcurve(log(x), 0.1, 4, xlab = "Log")
++-------------+-------------+-------------+-------------+--+
| ************** |
1 + ************ +
| ********* |
| ******* |
0 + **** +
| **** |
| *** |
-1 + ** +
| ** |
| * |
-2 + ** +
| * |
++-------------+-------------+-------------+-------------+--+
0 1 2 3 4
Log
txtcurve(x^2, -4, 4, xlab = "x^2")
+--+------------+-------------+-------------+------------+--+
15 + * * +
| ** ** |
| ** * |
| ** ** |
10 + ** ** +
| ** ** |
| ** ** |
| ** ** |
5 + ** ** +
| *** *** |
| **** **** |
0 + *************** +
+--+------------+-------------+-------------+------------+--+
-4 -2 0 2 4
x^2
## 2.2. 막대 그래프 --------------------------------------
votes <- factor(c("기호1번", "기호1번", "기호1번", "기호2번", "기호2번", "기호3번"))
txtbarchart(votes, pch="+", width = round(options()$width*0.7))
+-+-----------+-----------+-----------+-----------+-+
50 + + +
| + |
40 + + +
| + + |
30 + + + +
| + + |
20 + + + + +
| + + + |
10 + + + + +
| + + + |
0 +-+-----------+-----------+-----------+-----------+-+
1 1.5 2 2.5 3
Legend: 1=기호1번, 2=기호2번, 3=기호3번
## 2.3. 상자그림 그래프 --------------------------------------
txtboxplot(rnorm(1000,0,0.5), rnorm(100, 1))
-1 0 1 2 3
|-----+----------+----------+-----------+----------+----------|
+--+---+
1 -----------| | |------------
+--+---+
+------+--------+
2 ------------------| | |-------------------
+------+--------+
Legend: 1=rnorm(1000, 0, 0.5), 2=rnorm(100, 1)
## 2.4. 분포 그래프 ------------------------------------------
txtdensity(rnorm(500), pch = "+")
+--------+---------+--------+---------+---------+--------+-+
| +++++ |
0.4 + ++ ++ +
| ++ ++ |
| ++ +++ |
0.3 + ++ ++++ +
| +++ ++ |
| +++ ++ |
0.2 + ++ +++ +
| ++ +++ |
| ++ +++ |
0.1 + ++ +++ +
| ++++++++ ++++ |
| +++ +++++++ |
0 +--------+---------+--------+---------+---------+--------+-+
-2 -1 0 1 2 3
## 2.5. 히스토그램 ------------------------------------------
nos.hist(rnorm(500), freq=TRUE)
+---------+----------+---------+---------+----------+----+
100 + o +
| o o |
F 80 + o o +
r | o o o |
e | o o o o |
q 60 + o o o o +
u | o o o o o o |
e 40 + o o o o o o +
n | o o o o o o |
c | o o o o o o o |
y 20 + o o o o o o o o +
| o o o o o o o o o |
0 + o o o o o o o o o o o +
+---------+----------+---------+---------+----------+----+
-3 -2 -1 0 1 2
## 2.6. 자기상관 그래프 ------------------------------------------
txtacf(arima.sim(list(ar = 0.7), n = 100))
+--+------------+------------+-------------+------------+--+
1 + * +
| * |
| * |
| * * |
| * * |
0.5 + * * * +
| * * * |
| * * * * |
| * * * * * * * * * * |
| * * * * * * * * * * * * * |
0 + * * * * * * * * * * * * * * * * * * * * * +
| * * * * * * |
| * * * * * |
+--+------------+------------+-------------+------------+--+
0 5 10 15 20
## 2.7. 산점도 ------------------------------------------
txtplot(iris$Sepal.Length, iris$Sepal.Width, xlab="Sepal.Length", ylab="Sepal.Width")
4.5 +------------+-------------+-------------+--------------++
| * |
S | * * |
e 4 + * * +
p | * ** * * * |
a 3.5 + * * ** * * * +
l | * * ** * * * ** * |
. 3 + ** ** ** * * * * *** ** *** ** ** ** +
W | * * ** ** ** ** * * ** * |
i | * ** ** ** * * * |
d 2.5 + * * ** * * * +
t | * * * * ** |
h 2 + * +
+------------+-------------+-------------+--------------++
5 6 7 8
Sepal.Length