[R] 7. 데이터 형태 변환
반응형
0. 예시로 쓰일 데이터 예제
set.seed(2021)
# 임의로 데이터를 생성한다. (100명의 유저가 특정 곡을 스트리밍한 이력)
temp <- tibble(
user_id = c(10000:10099),
user_age = sample(x = round(runif(n = 100, min = 18, max = 50), 0), size = 100, replace = TRUE),
user_gender = sample(x = c("남성", "여성"), size = 100, replace = TRUE),
song_id = sample(x = letters[1:15], size = 100, replace = TRUE),
streaming_count = rpois(n = 100, lambda = 20)
) %>%
mutate(
song_class_flag = case_when(
song_id %in% c("d", "e", "f") ~ "인기곡",
TRUE ~ "비인기곡"
)
)
temp
## # A tibble: 100 x 6
## user_id user_age user_gender song_id streaming_count song_class_flag
## <int> <dbl> <chr> <chr> <int> <chr>
## 1 10000 49 여성 i 19 비인기곡
## 2 10001 49 여성 m 28 비인기곡
## 3 10002 26 여성 f 21 인기곡
## 4 10003 48 남성 e 14 인기곡
## 5 10004 49 여성 o 17 비인기곡
## 6 10005 37 여성 h 22 비인기곡
## 7 10006 48 여성 n 15 비인기곡
## 8 10007 43 남성 g 22 비인기곡
## 9 10008 22 남성 m 28 비인기곡
## 10 10009 34 여성 g 18 비인기곡
## # … with 90 more rows
1. 데이터 형태
- 데이터의 형태를 크게 두 가지로 구분한다면 테이블 자체가 긴 형태(long format)와 옆으로 넓은 형태(wide format)으로 구분지을 수 있습니다.
tidyverse
를 적극 잘 활용하시려면 이 두 가지 데이터 형태에 대해 가볍게라도 어떤 형태인지 인지할 필요가 있습니다.- 이해를 쉽게하지 위해 우리가 흔히 보는 데이터를 행렬 형태(matrix format)로 빗대어 표현했을 때 아래와 같이 이해하셔도 됩니다.
- long format: rows > columns
- wide format: rows < columns
- 우리는 아래 user_gender, song_id별 sum(streaming_count) 값을 가지고 데이터 형태를 변환하도록 하겠습니다.
temp2 <- temp %>%
group_by(user_gender, song_id) %>%
summarise(total_streaming_count = sum(streaming_count)) %>%
ungroup()
## `summarise()` has grouped output by 'user_gender'. You can override using the `.groups` argument.
temp2
## # A tibble: 30 x 3
## user_gender song_id total_streaming_count
## <chr> <chr> <int>
## 1 남성 a 43
## 2 남성 b 127
## 3 남성 c 33
## 4 남성 d 65
## 5 남성 e 44
## 6 남성 f 98
## 7 남성 g 146
## 8 남성 h 50
## 9 남성 i 48
## 10 남성 j 45
## # … with 20 more rows
2. spread()
: long format ~> wide format
spread()
함수는 long format을 wide format으로 변환해주는 함수이며 포맷은 아래와 같습니다.
spread(
data = 데이터,
key = "넓은 형태로 나열하게 될 변수",
value = "key 변수에 대한 값"
)
data %>%
spread(
key = "넓은 형태로 나열하게 될 변수",
value = "key 변수에 대한 값"
)
# song_id를 기준으로 wide formatting
temp2_spread <- temp2 %>%
spread(key = "song_id", value = "total_streaming_count")
temp2_spread
## # A tibble: 2 x 16
## user_gender a b c d e f g h i j k
## <chr> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
## 1 남성 43 127 33 65 44 98 146 50 48 45 24
## 2 여성 104 21 37 35 74 63 100 69 19 82 42
## # … with 4 more variables: l <int>, m <int>, n <int>, o <int>
- key나 value 파라미터로 받지 않은 변수들은 기존 형태를 유지하되,
key를 파라미터로 받은 변수는 옆으로 나열하게 되고, value를 파라미터로 받은 변수는 key 변수 값으로 매칭됩니다.
3. gather()
: wide format ~> long format
gather()
함수는 wide format을 long format으로 변환해주는 함수이며 포맷은 아래와 같습니다.
gather(
data = 데이터,
key = "긴 형태로 나열하게 될 변수명",
value = "key 변수에 대한 값 변수명",
-var1, -var2, ... # 고려하지 않는 변수
)
data %>%
gather(
key = "긴 형태로 나열하게 될 변수명",
value = "key 변수에 대한 값 변수명",
-var1, -var2, ... # 고려하지 않는 변수
)
# 위에서 살펴본 wide format 데이터를 다시 long format으로 변환
temp2_gather <- temp2_spread %>%
gather(key = "song_id", value = "streaming_value", -user_gender)
temp2_gather
## # A tibble: 30 x 3
## user_gender song_id streaming_value
## <chr> <chr> <int>
## 1 남성 a 43
## 2 여성 a 104
## 3 남성 b 127
## 4 여성 b 21
## 5 남성 c 33
## 6 여성 c 37
## 7 남성 d 65
## 8 여성 d 35
## 9 남성 e 44
## 10 여성 e 74
## # … with 20 more rows
- 위 코드에서도 보였듯,
spread()
와 차이가 있다면, 고려하지 않는 변수는-변수명
을 따로 입력해주는 구조입니다. - 즉, wide format에서 user_gender를 제외하고 나머지들을 다시 long format으로 변환하되
key 변수명은 song_id, 그 key 값에 대한 변수명은 streaming_value로 재정의한 것과 같습니다.
4. 두 가지 이상 교차 변수의 spread()
, gather()
- 두 가지 이상 변수를
unite()
함수를 사용하요 교차한 후 wide format 변환도 가능합니다.unite()
함수는 여러 개의 변수 값을 하나로 뭉쳐주는 함수입니다.
temp3 <- temp %>%
unite(col = song, c("song_class_flag", "song_id"), sep = "_") %>%
spread(key = "song", value = "streaming_count")
temp3
## # A tibble: 100 x 18
## user_id user_age user_gender 비인기곡_a 비인기곡_b 비인기곡_c 비인기곡_g
## <int> <dbl> <chr> <int> <int> <int> <int>
## 1 10000 49 여성 NA NA NA NA
## 2 10001 49 여성 NA NA NA NA
## 3 10002 26 여성 NA NA NA NA
## 4 10003 48 남성 NA NA NA NA
## 5 10004 49 여성 NA NA NA NA
## 6 10005 37 여성 NA NA NA NA
## 7 10006 48 여성 NA NA NA NA
## 8 10007 43 남성 NA NA NA 22
## 9 10008 22 남성 NA NA NA NA
## 10 10009 34 여성 NA NA NA 18
## # … with 90 more rows, and 11 more variables: 비인기곡_h <int>,
## # 비인기곡_i <int>, 비인기곡_j <int>, 비인기곡_k <int>, 비인기곡_l <int>,
## # 비인기곡_m <int>, 비인기곡_n <int>, 비인기곡_o <int>, 인기곡_d <int>,
## # 인기곡_e <int>, 인기곡_f <int>
- 위에서 나왔던 결과를 반대로
separate()
함수를 사용하여 재변환도 가능합니다.separate()
함수는unite()
와 반대로 여러 개의 변수 값 또는 특정 값이나 구분자로 되어 있는 데이터를 분리하는 역할을 합니다.
temp4 <- temp3 %>%
gather(key = "song", value = "streaming_count", -user_id, -user_age, -user_gender, na.rm = TRUE) %>%
separate(col = song, c("song_class_flag", "song_id"), sep = "_")
temp4
## # A tibble: 100 x 6
## user_id user_age user_gender song_class_flag song_id streaming_count
## <int> <dbl> <chr> <chr> <chr> <int>
## 1 10019 19 여성 비인기곡 a 12
## 2 10025 21 남성 비인기곡 a 19
## 3 10035 49 여성 비인기곡 a 24
## 4 10036 33 여성 비인기곡 a 19
## 5 10047 31 여성 비인기곡 a 8
## 6 10058 20 여성 비인기곡 a 25
## 7 10086 19 남성 비인기곡 a 24
## 8 10092 48 여성 비인기곡 a 16
## 9 10018 43 남성 비인기곡 b 18
## 10 10022 32 남성 비인기곡 b 11
## # … with 90 more rows
- 위 코드를 보시면 아시다시피
gather()
함수에 key, value 값 외에na.rm = TRUE
옵션이 있습니다. - 해당 옵션을 붙이면 넓은 형태의 데이터를 긴 형태의 데이터로 변환하는 과정에서 결측값을 제거한 후 데이터를 변환시킵니다.
반응형
'tidyverse' 카테고리의 다른 글
[R] 9. 기술통계분석 (0) | 2021.07.05 |
---|---|
[R] 8. 데이터 합치기 (join) (0) | 2021.07.05 |
[R] 6. 날짜 및 시간 변수 (lubridate) (3) | 2021.07.05 |
[R] 5. mutate() (0) | 2021.07.05 |
[R] 4. select(), filter(), group_by(), summarise(), arrange(), rename() (0) | 2021.07.05 |
TAGS.