개발자가 배우는 R : 4강, 데이터프레임 가공하기

개요

이번 포스팅에는 R에서 가장 많이 쓰이는 데이터프레임을 가공하는 방법을 알아본다. 이를 위해 데이터프레임을 조작하는 방법과 관련된 외부 패키지 reshape 사용법을 알아본다.

코드중심의 설명이기 때문에 본문 보다는 코드의 주석이 집중적으로 추가되어 있으니 참고 바란다.

데이터프레임 조작하기

데이터프레임 예제 #1 : leadership

임의로 leadership 객체를 만들어 데이터프레임 조작을 알아보자.

leadership 데이터프레임 생성

우선 객체를 아래와 같은 코드로 생성 해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> manager <- c(12345)
> date <- c("10/24/08""10/28/08""10/1/08""10/12/08""5/1/09")
> gender <- c("M""F""F""M""F")
> age <- c(3245253999)
> q1 <- c(53332)
> q2 <- c(45532)
> q3 <- c(52541)
> q4 <- c(555, NA, 2)
> q5 <- c(552, NA, 1)
> leadership <- data.frame(manager, date, gender, age, q1, q2, q3, q4, q5, stringsAsFactors = FALSE)
> leadership
  manager     date gender age q1 q2 q3 q4 q5
1       1 10/24/08      M  32  5  4  5  5  5
2       2 10/28/08      F  45  3  5  2  5  5
3       3  10/1/08      F  25  3  5  5  5  2
4       4 10/12/08      M  39  3  3  4 NA NA
5       5   5/1/09      F  99  2  2  1  2  1

데이터 프레임 열 추가하기

1
2
3
4
5
6
7
8
9
10
11
>  leadership$agecat[leadership$age > 75] <- "Elder" # 새로 agecat 열을 만드는데 leadership의 나이가 75보다 크면 Elder를 넣는다.
>  leadership$agecat[leadership$age > 45 & # &를 붙이면 라인을 이어서 다음 라인에 명령을 추가로 입력 할 수 있다.
+  leadership$age <= 75] <- "Middle Aged" # leadership의 나이가 45보다 크고 75살 보다 작거나 같으면 Middle Aged를 넣는다.
> leadership$agecat[leadership$age <= 45] <- "Young" # 나이가 45보다 작거나 같으면 Young을 넣는다.
> leadership # leadership을 출력해보면 agecat이 나이에 따라 값이 생겼다.
  manager     date gender age q1 q2 q3 q4 q5 agecat
1       1 10/24/08      M  32  5  4  5  5  5  Young
2       2 10/28/08      F  45  3  5  2  5  5  Young
3       3  10/1/08      F  25  3  5  5  5  2  Young
4       4 10/12/08      M  39  3  3  4 NA NA  Young
5       5   5/1/09      F  99  2  2  1  2  1  Elder

변수명 불러오기 및 바꾸기

1
2
3
4
5
6
7
8
9
10
11
> names(leadership) # 데이터 프레임 변수명 불러오기
 [1"manager" "date"    "gender"  "age"     "q1"      "q2"      "q3"     
 [8"q4"      "q5"      "agecat"
> names(leadership)[2] <- "testDate" # 2번째 열의 변수명 바꾸기
> leadership
  manager testDate gender age q1 q2 q3 q4 q5 agecat
1       1 10/24/08      M  32  5  4  5  5  5  Young
2       2 10/28/08      F  45  3  5  2  5  5  Young
3       3  10/1/08      F  25  3  5  5  5  2  Young
4       4 10/12/08      M  39  3  3  4 NA NA  Young
5       5   5/1/09      F  99  2  2  1  2  1  Elder

데이터프레임 예제 #2 : newdata

leadership 객체에서 NA 데이터 처리를 처리한 newdata 데이터프레임을 만든다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
> leadership # 현재 leadership에는 4번째 행이 NA값을 가지고 있다.
  manager testDate gender age q1 q2 q3 q4 q5 agecat
1       1 10/24/08      M  32  5  4  5  5  5  Young
2       2 10/28/08      F  45  3  5  2  5  5  Young
3       3  10/1/08      F  25  3  5  5  5  2  Young
4       4 10/12/08      M  39  3  3  4 NA NA  Young
5       5   5/1/09      F  99  2  2  1  2  1  Elder
> is.na(leadership[, 6:10]) # is로 시작하는 함수는 무엇인지 아닌지 검사하는 함수로 na값인지 아닌지를 bollean으로 출력한다.
        q2    q3    q4    q5 agecat
[1,] FALSE FALSE FALSE FALSE  FALSE
[2,] FALSE FALSE FALSE FALSE  FALSE
[3,] FALSE FALSE FALSE FALSE  FALSE
[4,] FALSE FALSE  TRUE  TRUE  FALSE
[5,] FALSE FALSE FALSE FALSE  FALSE
> newdata <- na.omit(leadership) # na값을 버리고 데이터를 만든다.
> newdata
  manager testDate gender age q1 q2 q3 q4 q5 agecat
1       1 10/24/08      M  32  5  4  5  5  5  Young
2       2 10/28/08      F  45  3  5  2  5  5  Young
3       3  10/1/08      F  25  3  5  5  5  2  Young
5       5   5/1/09      F  99  2  2  1  2  1  Elder

is함수와 as 함수 알아보기

간단히 설명하자면 is로 시작하는 함수는 무엇인가를 검사하는 함수고 as로 시작하는 함수는 변환을 시키는 함수이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> a <- c(1,2,3)
> a
[11 2 3
> is.numeric(a)
[1] TRUE
> is.vector(a)
[1] TRUE
> a <- as.character(a) # a를 숫자형 벡터에서 문자형 벡터로 변환함
> a
[1"1" "2" "3"
> is.numeric(a)
[1] FALSE
> is.vector(a)
[1] TRUE
> is.character(a)
[1] TRUE

데이터 프레임 정렬

1
2
3
4
5
6
> newdata
  manager testDate gender age q1 q2 q3 q4 q5 agecat
1       1 10/24/08      M  32  5  4  5  5  5  Young
2       2 10/28/08      F  45  3  5  2  5  5  Young
3       3  10/1/08      F  25  3  5  5  5  2  Young
5       5   5/1/09      F  99  2  2  1  2  1  Elder

아래와 같이 정렬을 시킬수 있는데 이해하는데 주의할 점은 값 자체를 정렬시키는 것이 아니라 보여주는 결과만 정렬하여 보여준다. 엑셀처럼 기존 데이터가 바뀌지 않고 보유줄때만 정렬이 바뀐다고 생각하면 된다. 그 증거가 index번호가 바뀌지 않는 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> newdata <- leadership[order(leadership$age),] # 나이순으로 정렬을 시킴
> newdata
  manager testDate gender age q1 q2 q3 q4 q5 agecat
3       3  10/1/08      F  25  3  5  5  5  2  Young
1       1 10/24/08      M  32  5  4  5  5  5  Young
4       4 10/12/08      M  39  3  3  4 NA NA  Young
2       2 10/28/08      F  45  3  5  2  5  5  Young
5       5   5/1/09      F  99  2  2  1  2  1  Elder
> newdata <- leadership[order(leadership$gender, -leadership$age),] # 2가지 조건의 정렬을 파라미터로 순서대로 입력하면 된다. 내림차순은 -를 붙이면 딘다.
> newdata
  manager testDate gender age q1 q2 q3 q4 q5 agecat
5       5   5/1/09      F  99  2  2  1  2  1  Elder
2       2 10/28/08      F  45  3  5  2  5  5  Young
3       3  10/1/08      F  25  3  5  5  5  2  Young
4       4 10/12/08      M  39  3  3  4 NA NA  Young
1       1 10/24/08      M  32  5  4  5  5  5  Young

데이터프레임 예제객체 #3 : mtcars

R에는 내장되어 있거나 패키지 설치시 같이 설치되는 많은 샘플 데이터들이 존재한다. 그리고 이 데이터들은 대부분 데이터프레임 형식을 취하고 있다. 이중에서 차종별 정보를 담은 mtcars를 살펴보자.

R의 샘플데이터 정보

mtcars를 알아보기 전에 하나 소개하자면 R에서 기본 제공되는 예제 데이터 목록은 아래의 명령어로 알아 볼 수 있다.

1
> data()

mtcars 정보

mtcars는 아래와 같은 도표의 정보를 담고 있다.

mtcars 커맨드 확인해 보기

R에서 아래와 같이 커맨드를 통해 확인해 볼 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
> mtcars
                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2

mtcars 관련 help 조회

mtcars에 대한 정보는 아래의 명령어로 조회해 볼 수 있다.

1
> help(mtcars)

head 명령

데이터는 상위 n개만 확인 할 때는 head 명령어를 쓰면 된다.

1
2
3
4
5
6
7
8
9
10
> head(mtcars, n=6)
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1class(mtcars) # 제공하는 데이터셋이 무엇인지 확인해보면 데이터프레임임을 알 수 있다.
[1] "data.frame"

데이터프레임 전치(Transpose)

데이터 프레임의 일부를 행렬처럼 전치 시킬 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> cars <- mtcars[1:51:4]
> cars
                   mpg cyl disp  hp
Mazda RX4         21.0   6  160 110
Mazda RX4 Wag     21.0   6  160 110
Datsun 710        22.8   4  108  93
Hornet 4 Drive    21.4   6  258 110
Hornet Sportabout 18.7   8  360 175
> t(cars) # 행렬을 전치 시킨다.
     Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive Hornet Sportabout
mpg         21            21       22.8           21.4              18.7
cyl          6             6        4.0            6.0               8.0
disp       160           160      108.0          258.0             360.0
hp         110           110       93.0          110.0             175.0

Aggregate 함수

데이터프레임을 다룰 때 많이 쓰는 유용한 함수인 Aggregate를 알아보자.

문법은 x는 대상, by는 어떤것을 기준으로 그룹핑 할 것인지, FUN은 함수이다.

1
aggregate(x, by, FUN)

실제로 예제를 보면 실린더와 기어값을 기준으로 그룹핑일 한 뒤 mtcars 데이터의 평균값을 계산한다. 주의할 점은 na값은 삭제하는데 mean함수에 대한 옵션이므로 평균을 구할 대상이 되는 데이터의 na값 삭제 여부를 의미한다.

명령어의 + 표시는 다음줄에서 이어서 명령어를 입력할때 나타나는 기호이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
> aggdata <- aggregate(mtcars, by=list(mtcars$cyl, mtcars$gear),
+  FUN=mean, na.rm=TRUE)
> aggdata
  Group.1 Group.2    mpg cyl     disp       hp     drat       wt    qsec  vs
1       4       3 21.500   4 120.1000  97.0000 3.700000 2.465000 20.0100 1.0
2       6       3 19.750   6 241.5000 107.5000 2.920000 3.337500 19.8300 1.0
3       8       3 15.050   8 357.6167 194.1667 3.120833 4.104083 17.1425 0.0
4       4       4 26.925   4 102.6250  76.0000 4.110000 2.378125 19.6125 1.0
5       6       4 19.750   6 163.8000 116.5000 3.910000 3.093750 17.6700 0.5
6       4       5 28.200   4 107.7000 102.0000 4.100000 1.826500 16.8000 0.5
7       6       5 19.700   6 145.0000 175.0000 3.620000 2.770000 15.5000 0.0
8       8       5 15.400   8 326.0000 299.5000 3.880000 3.370000 14.5500 0.0
    am gear     carb
1 0.00    3 1.000000
2 0.00    3 1.000000
3 0.00    3 3.083333
4 0.75    4 1.500000
5 0.50    4 4.000000
6 1.00    5 2.000000
7 1.00    5 6.000000
8 1.00    5 6.000000

reshape 패키지

R에서 데이터프레임 조작 시 많이 사용하는 reshape 패키지를 설치, 사용하는 방법을 알아보자.

reshape 패키지 설치

아래와 같은 명령어로 reshape를 설치한다.

1
> install.packages("reshape")

reshape 패키지 사용

reshape 라이브러리를 선택한다.

1
> library(reshape)

Melt 함수

데이터 프레임을 다룰때 데이터 구조를 행의 키값을 기준으로 나머지를 변수화 하여 담아버리는 것을 melt 또는 melting한다고 표현한다. 한국어로 의역하자면 데이터를 입맛에 맞게끔 녹인다고 볼 수 있다.

예제 데이터 프레임 준비하기 : mydata

1
2
3
4
5
6
7
8
9
10
11
> id <- c(1,1,2,2)
> time <- c(1212)
> x1 <- c(5362)
> x2 <- c(6514)
> mydata <- data.frame(id, time, x1, x2)
> mydata
  id time x1 x2
1  1    1  5  6
2  1    2  3  5
3  2    1  6  1
4  2    2  2  4

melt 적용

mydata를 melt하여 x1, x2 칼럼으로 나타냈던 데이터셋을 variable, value 2개로 직렬화하였다. 키값은 id, time의 조합(combination)이 키값이고 기존의 x1, x2 칼럼은 변수화되어 key-value 형태로 저장된다.

melt의 장점은 칼럼이 얼마 없을때 보다 칼럼이 굉장히 많을때나 각 칼럼 값을 변수로 직렬화 하여 데이터를 조작할 때 편리하다.

1
2
3
4
5
6
7
8
9
10
11
> md <- melt(mydata, id=(c("id""time")))
> md
  id time variable value
1  1    1       x1     5
2  1    2       x1     3
3  2    1       x1     6
4  2    2       x1     2
5  1    1       x2     6
6  1    2       x2     5
7  2    1       x2     1
8  2    2       x2     4

Cast 함수

cast의 기본 문법은 아래와 같다.

md는 melt된 데이터, formular는 원하는 결과, FUN에는 적용할 함수를 선택한다.

1
newdata <- cast(md, formula, FUN)

cast 함수 사용 도식

cast 함수는 아래의 그림이 이해가 훨씬 빠를것이다.

물결 표시 앞쪽은 행으로 사용할 값을 정하는데 여러개일때 +로 연결한다.

물결표시 뒤쪽은 열로 사용할 값을 정하고 여러개일때 마찬가지로 +로 연결한다.

FUN에 함수를 지정하면 왼쪽과 같이 평균값 들을 구할 수 있고,


Popit은 페이스북 댓글만 사용하고 있습니다. 페이스북 로그인 후 글을 보시면 댓글이 나타납니다.