[R] mutate 함수 뜯어보기 (feat. dplyr)

해당 포스트에서는 데이터 처리 전문 패키지인 dplyr의 mutate 함수 활용에 대해 소개합니다.

dplyr-mutate-in-r

INTRO

R에서 데이터 처리를 한다면 많은 분들이 dplyr 패키지를 먼저 설치하게 됩니다. 유용한 함수들이 많이 포함되어 있기도 하지만 tidyverse 생태계에 포함되어 있어 타 패키지들과의 호환성이 뛰어나다는 장점이 있습니다.

아래에서는 dplyr 패키지에서 제공되는 함수들 중 mutate() 계열의 함수들을 예제 코드와 함께 소개합니다.

mutate()?

dplyr 패키지에서 제공되는 mutate() 함수는 데이터 프레임(Data Frame)에 변수를 추가할 때 사용됩니다.

mutate 계열 함수

  • mutate() : 기존 변수를 유지하면서 새로운 변수 추가
  • transmute() : 기존 변수는 제거하고 새로운 변수 추가
  • mutate_all() : 모든 변수 변경
  • mutate_at() : 정확한 컬럼명을 기준 변수 변경
  • mutate_if() : 조건에 만족하는 변수에 대해 변경

1. mutate()

mutate() 함수는 데이터 프레임(Data Frame)에 존재하는 기존 변수는 유지하며 새로운 변수를 생성합니다.

기본 사용법

library(dplyr)

data <- mutate(new_variable = existing_variable/3)
  • data : 새롭게 생성된 데이터 프레임
  • new_variable : 새로운 변수의 이름
  • existing_variable : 현재 데이터 프레임 내 변수로 새로운 변수로 변경하려는 대상

iris 데이터에 새로운 변수 생성

아래에서는 R에서 제공되는 기본 데이터셋인 iris 데이터에 새로운 root_sepal_width 변수를 추가하는 과정을 설명합니다.

data <- head(iris)
data
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa


새로운 변수 root_sepal_width는 기존 Sepal.Width 변수에 root를 적용하여 생성합니다.

data %>% mutate(root_sepal_width = sqrt(Sepal.Width))
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species root_sepal_width
1          5.1         3.5          1.4         0.2  setosa         1.870829
2          4.9         3.0          1.4         0.2  setosa         1.732051
3          4.7         3.2          1.3         0.2  setosa         1.788854
4          4.6         3.1          1.5         0.2  setosa         1.760682
5          5.0         3.6          1.4         0.2  setosa         1.897367
6          5.4         3.9          1.7         0.4  setosa         1.974842


출력 결과를 보면, 기존 Sepal.Width 변수가 유지되면서 맨 마지막 위치에 root_sepal_width라는 새로운 변수가 추가된 것을 볼 수 있습니다.

2. transmute()

transmute() 함수는 mutate()와 같이 새로운 변수를 생성한다는 동작은 동일하지만, 과정에 사용된 기존 변수는 제거된다는 차이가 있습니다. 아래에서는 transmute() 함수를 이용해 새로운 2개의 변수를 생성하는 과정을 설명합니다.

data <- head(iris)
data
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa


위에서 확인한 iris 데이터의 Sepal.WidthPetal.Width 변수를 이용하여 2개의 새로운 변수를 생성합니다. 아래 결과를 보면 새롭게 생성된 2개 변수 외의 모든 변수가 제거된 것을 볼 수 있습니다.

data %>% transmute(root_sepal_width = sqrt(Sepal.Width),
                   root_petal_width = sqrt(Petal.Width))
  root_sepal_width root_petal_width
1         1.870829        0.4472136
2         1.732051        0.4472136
3         1.788854        0.4472136
4         1.760682        0.4472136
5         1.897367        0.4472136
6         1.974842        0.6324555

3. mutate_all()

mutate_all() 함수는 데이터 프레임 내의 모든 변수를 한번에 변경할 수 있습니다. funs() 함수와 함께 사용한다면 apply 함수처럼 적용도 가능합니다.

아래 코드는 Species 컬럼을 제외한 iris 데이터의 모든 변수를 10으로 나눈 결과입니다. 먼저, Species를 제외한 iris 데이터를data2라는 새로운 객체로 생성합니다.

data2 <- head(iris) %>% select(-Species)
data2
  Sepal.Length Sepal.Width Petal.Length Petal.Width
1          5.1         3.5          1.4         0.2
2          4.9         3.0          1.4         0.2
3          4.7         3.2          1.3         0.2
4          4.6         3.1          1.5         0.2
5          5.0         3.6          1.4         0.2
6          5.4         3.9          1.7         0.4


데이터 프레임(Data Frame)의 모든 변수를 10으로 나누어 줍니다.

data2 %>% mutate_all(funs(./10))
  Sepal.Length Sepal.Width Petal.Length Petal.Width
1         0.51        0.35         0.14        0.02
2         0.49        0.30         0.14        0.02
3         0.47        0.32         0.13        0.02
4         0.46        0.31         0.15        0.02
5         0.50        0.36         0.14        0.02
6         0.54        0.39         0.17        0.04


위와 같은 출력 결과를 얻었으나 하단에 경고 메시지가 출력되었을 겁니다. 아래 경고 메세지는 dplyr 패키지의 버전이 0.8.0부터는 funs() 함수가 지원되지 않을 예정이라는 내용으로, 변경된 사용법을 안내합니다.

Warning message:
`funs()` was deprecated in dplyr 0.8.0.
Please use a list of either functions or lambdas: 

  # Simple named list: 
  list(mean = mean, median = median)

  # Auto named with `tibble::lst()`: 
  tibble::lst(mean, median)

  # Using lambdas
  list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))

4. mutate_at()

mutate_at()는 선택한 컬럼들을 부분적으로 변경할 수 있습니다. 아래 예시는 2개의 컬럼(Sepal.Length, Sepal.Width)에만 나누기 10을 적용하고 컬럼명 뒤에 _mod를 붙이는 코드입니다.

data2 %>% mutate_at(c("Sepal.Length", "Sepal.Width"), funs(mod = ./10))
  Sepal.Length Sepal.Width Petal.Length Petal.Width Sepal.Length_mod Sepal.Width_mod
1          5.1         3.5          1.4         0.2             0.51            0.35
2          4.9         3.0          1.4         0.2             0.49            0.30
3          4.7         3.2          1.3         0.2             0.47            0.32
4          4.6         3.1          1.5         0.2             0.46            0.31
5          5.0         3.6          1.4         0.2             0.50            0.36
6          5.4         3.9          1.7         0.4             0.54            0.39

5. mutate_if()

mutate_if()는 조건에 부합하는 변수들을 선택적으로 변경할 수 있습니다. 아래 코드는 데이터 프레임(Data Frame)에서 변수의 타입(type)이 factor인 경우 character로 변경해 줍니다.

data <- head(iris)
sapply(data, class)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
   "numeric"    "numeric"    "numeric"    "numeric"     "factor" 


위 결과를 보면 Species 변수의 타입(type)이 factor인 것을 알 수 있습니다. 이제 mutate_if() 함수를 사용해 해당 컬럼의 타입을 변경해 보겠습니다.

new_data <- data %>% mutate_if(is.factor, as.character)
sapply(new_data, class)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
   "numeric"    "numeric"    "numeric"    "numeric"  "character" 


또한 mutate_if() 함수는 숫자형 변수들에만 반올림 함수(round())를 적용할 수 있습니다.

data <- head(iris)
data
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
data %>% mutate_if(is.numeric, round, digits = 0)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1            5           4            1           0  setosa
2            5           3            1           0  setosa
3            5           3            1           0  setosa
4            5           3            2           0  setosa
5            5           4            1           0  setosa
6            5           4            2           0  setosa

마무리

이번 포스트에서는 dplyr에서 많이 사용되는 mutate 계열 함수들의 사용법을 설명하였습니다. 기본형인 mutate로도 많은 처리를 수행할 수 있으나 패키지에서 제공되는 함수들을 공부하고 활용한다면 보다 효율적인 코딩 및 분석이 가능합니다.

관련 링크

[1] [R-bloggers] How to Use Mutate function in R