데이터 정제


누락 값, 비어있는 값 찾기

누락된 값 또는 비어있는 값을 결측치라고 합니다. 여기서는 결측치라는 단어가 쉽게 와닫지 않기 때문에, 누락 값 혹은 비어있는 값이라 표현하겠습니다.

데이터 통계를 나타내어야 하는데 데이터에 누락된 값 혹은 비어있는 값이 존재하는 경우 해당 통계 값이 정확하지 않을 수 있습니다. 이러한 경우 누락된 값을 적절히 처리해 주어야 합니다.

아래 코드 처럼 누락 값을 NA라 표현하며 데이터 프레임을 생성해봅시다.

> df_test = data.frame(sex = c("M", "F", NA, "M", "F"), score = c(5, 4, 3, 4, NA))
> df_test
   sex score
1    M     5
2    F     4
3 <NA>     3
4    M     4
5    F    NA

누락 값을 확인하기 위해서는 is.na(데이터프레임) 형태로 사용합니다. 아래 코드처럼 누락 값인 경우 TRUE를 존재하는 값이라면 FALSE를 출력하게 됩니다.

> is.na(df_test)
       sex score
[1,] FALSE FALSE
[2,] FALSE FALSE
[3,]  TRUE FALSE
[4,] FALSE FALSE
[5,] FALSE  TRUE

누락된 값이 포함된 상태에서 합, 평균 등을 계산하는 경우 NA가 출력됩니다. 아래 코드를 확인해보세요.

> sum(df_test$score)
[1] NA
> mean(df_test$score)
[1] NA

이번에는 누락 값을 제외하여 값을 구하는 방법에 대해 알아보겠습니다.

> library(dplyr)
> df_test %>% filter(!is.na(score) & !is.na(sex))
  sex score
1   M     5
2   F     4
3   M     4

위 코드에서 filter를 사용하므로 dplyr 패키지를 사용해야 합니다. filter 함수에서는 score와 sex에 대해 모두 NA가 아닌 값만 출력하도록 합니다.

다른 방법으로는 na.omit() 함수를 이용하는 것입니다. 이 함수는 filter 처럼 각 조건에 맞춰 넣어준 반면, NA를 제외하고 값을 출력하게 됩니다.

> na.omit(df_test)
  sex score
1   M     5
2   F     4
4   M     4

추가적으로 평균, 합을 구할때 누락 값이 존재하는 경우 이를 제외하여 사용하는 방법이 있습니다. na.rm = T 파라미터를 이용하여 쉽게 값을 출력할 수 있습니다. na.rm은 mean(), sum(), summrise() 등 다양하게 사용할 수 있습니다.

> sum(df_test$score, na.rm=T)
[1] 16
> mean(df_test$score, na.rm=T)
[1] 4

데이터 프레임에 NA 값을 넣는 방법도 존재합니다. 기존에 사용하던 csv_exam.csv 를 이용하여 english에 NA, 누락 값을 넣어보겠습니다.

> exam = read.csv("csv_exam.csv")
> exam[c(3, 8, 15), english] = NA
> exam[c(3, 8, 15), "english"] = NA
> exam
   id class math english science
1   1     1   50      98      50
2   2     1   60      97      60
3   3     1   45      NA      78
4   4     1   30      98      58
5   5     2   25      80      65
6   6     2   50      89      98
7   7     2   80      90      45
8   8     2   90      NA      25
9   9     3   20      98      15
10 10     3   50      98      45
11 11     3   65      65      65
12 12     3   45      85      32
13 13     4   46      98      65
14 14     4   48      87      12
15 15     4   75      NA      78
16 16     4   58      98      65
17 17     5   65      68      98
18 18     5   80      78      90
19 19     5   89      68      87
20 20     5   78      83      58

위 코드처럼 read.csv로 해당 csv 파일을 읽어오고 데이터프레임[인덱스, "속성명"] = 값 형태로 해당 속성과 인덱스에 값을 넣어줄 수 있습니다.

누락 값 대체하기

통계를 산출하기 위해서는 데이터들이 많이 필요합니다. 적은 데이터의 경우 단순히 누락 값을 제외하여 산출해도 무방한 경우가 많지만, 많은 데이터에서는 조금의 차이로 결과가 크게 달라지기 때문에 누락 값을 임의의 값으로 대체되어야 합니다.

먼저, 누락 값을 평균 값으로 대체해 보겠습니다.

앞서, english 속성의 일부 값을 NA로 설정했으므로 이 값을 나머지 값들의 평균 값으로 대체해 보겠습니다.

> exam$english = ifelse(is.na(exam$english), mean(exam$english, na.rm=T), exam$english)
> exam
   id class math  english science
1   1     1   50 98.00000      50
2   2     1   60 97.00000      60
3   3     1   45 86.94118      78
4   4     1   30 98.00000      58
5   5     2   25 80.00000      65
6   6     2   50 89.00000      98
7   7     2   80 90.00000      45
8   8     2   90 86.94118      25
9   9     3   20 98.00000      15
10 10     3   50 98.00000      45
11 11     3   65 65.00000      65
12 12     3   45 85.00000      32
13 13     4   46 98.00000      65
14 14     4   48 87.00000      12
15 15     4   75 86.94118      78
16 16     4   58 98.00000      65
17 17     5   65 68.00000      98
18 18     5   80 78.00000      90
19 19     5   89 68.00000      87
20 20     5   78 83.00000      58

평균은 mean() 함수로 구할 수 있는 것을 배웠습니다. 이 함수를 이용해서 exam의 english 값의 평균을 구하는데, NA 값을 제외하여 구합니다. 구한 평균 값을 이제 NA에 넣어주어야 하므로, ifelse를 이용하여 is.na() 함수가 TRUE인 경우 해당 위치의 값이 NA이므로 평균 값을 넣어주고 아니라면 원래 그대로의 ㄱ밧을 넣어주게 됩니다.

비정상 값 처리하기

비정상 값이라함은, 특정 속성에서 나타날 수 없는 값을 말합니다. 이는 이상치라고 표현하는데, 여기서는 비정상 값으로 표현하겠습니다.

가령 sex 속성의 경우 남자는 1, 여자는 2로 표현하기로 약속했습니다. 하지만 어떤 이유로 3이라는 값이 포함되었다면 이 값을 제거해 주어야 합니다.

따라서 비정상 값은 먼저 누락 값으로 변경하고 누락 값을 제외하여 통계를 산출하면 됩니다.

이번에는 아래와 같은 데이터 프레임이 존재할때 남자(1)의 점수 평균과 여자(2)의 점수 평균을 구해보도록 하겠습니다. 점수는 1~5 점 사이의 값이어합니다.

> df_test = data.frame(sex=c(1, 2, 3, 2, 2, 1, 1), score=c(3, 3, 6, 2, 2, 1, 2))
> df_test
  sex score
1   1     3
2   2     3
3   3     6
4   2     2
5   2     2
6   1     1
7   1     2

위 코드의 결과를 살펴보면 sex에는 3이라는 비정상 값과 score에는 6이라는 비정상 값이 있습니다. 이러한 경우 먼저 누락 값으로 변경해 주어야 합니다.

> df_test$sex = ifelse(df_test$sex != 1 & df_test$sex !=2, NA, df_test$sex)
> df_test
  sex score
1   1     3
2   2     3
3  NA     6
4   2     2
5   2     2
6   1     1
7   1     2
> df_test$score = ifelse(df_test$score >= 0 & df_test$score <= 5, df_test$score, NA)
> df_test
  sex score
1   1     3
2   2     3
3  NA    NA
4   2     2
5   2     2
6   1     1
7   1     2

ifelse를 이용하여 sex의 값이 1도 아니면서 2도 아닌 경우는 NA로 변경하도록 하였고, score는 0보다 크거나 같으면서 5보다 작거나 같은 경우가 아니라면 NA로 변경했습니다.

이 상태에서 남자와, 여자의 평균을 구해보겠습니다.

> library(dplyr)
> df_test %>% filter(!is.na(sex) & !is.na(score)) %>% group_by(sex) %>% summarise(mean = mean(score))
# A tibble: 2 x 2
    sex  mean
  <dbl> <dbl>
1     1  2   
2     2  2.33

filter를 이용하기 위해 dplyr 패키지를 넣어주었으며 score와 sex가 NA가 아닌 경우에 대해 score의 평균을 구했습니다.

극단 값 제거하기

극단 값은 논리적, 상식적으로 해당 결과치가 존재할 수 있으나 드문 경우의 값을 극단 값이라 합니다. 몸무게가 200kg인 사람이 존재할 수 있으나 200kg인 사람이 극히 드물수 있으므로 논리적, 상식적으로 생각하여 이 값을 극단 값이라 정하여 제거하게 됩니다.

기존에 사용하던 mpg 데이터 프레임을 이용해 boxplot()함수를 이용하여 hwy 값을 표현하면 아래와 같습니다.

boxplot

> boxplot(mpg$hwy)$stats
     [,1]
[1,]   12
[2,]   18
[3,]   24
[4,]   27
[5,]   37
attr(,"class")
        1 
"integer"

그림으로는 정확한 값을 알 수 없으므로 $stats를 이용하여 결과를 확인합니다. 1은 아래 극단 값 경계, 2는 하위 25%, 3은 중앙 값, 4는 하위 75%, 5는 윗쪽 극단 값 경계를 말합니다.

그렇다면 12~37 사이의 값을 제외한 값은 극단 값이므로 이를 제외하여 통계를 산출하면 됩니다.




© 2017. by k3y6reak

Powered by k3y6reak