[R] 8. 데이터 합치기 (join)
반응형
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. 데이터 합치기
- 이번 포스팅에서는 식별 변수를 중심으로 여러 데이터들을 합치는 방법에 대해 소개합니다.
- SQL에서 LEFT OUTER JOIN, INNER JOIN 등과 같이 테이블간 조인을 시도할 때 ON절 이하 구문을 기준으로 식별 변수를 정의합니다.
- 마찬가지로
tidyverse
에서도 해당 쿼리들과 같은 기능을 갖는 함수들이 존재합니다. - SQL에서는 ON이 있듯, 여기서는
by
옵션을 통해 기준 변수를 설정합니다. - 하나 함수 포맷 예시를 들면 아래와 같습니다.
inner_join(데이터1, 데이터2, by = c("기준변수1", "기준변수2", ...))
tidyverse
라이브러리에서 지원하는 데이터 결합 관련 함수는 아래와 같습니다.- 사전에 SQL 지식이 있다면 이해하기 더욱 더 쉽습니다.
- 조인 함수와 관련하여 자세한 설명은 검색을 활용하시면 더 쉽고 상세하게 풀어 놓은 설명들이 많으니 참고하시길 바랍니다.
함수명 설명 inner_join()
두 데이터간 공통적으로 속하는 사례만 출력 full_join()
두 데이터에서 최소 한 번 이상 등장하는 사례(합집합 개념, UNION) left_join()
첫 번째 input되는 데이터 사례와 공통적으로 속하는 사례들이 포함되어 출력 right_join()
두 번째 input되는 데이터 사례와 공통적으로 속하는 사례들이 미함되어 출력 semi_join()
두 번째 input되는 데이터에 존재하는 첫 번째 input 데이터만 출력 anti_join()
두 번쨰 input되는 데이터에 존재하는 첫 번째 Input 데이터를 배제하고 남은 데이터만 출력
- 여기서는 아래 성별/곡별 스트리밍 통계량을 가지고 임의로 전처리한 데이터를 사용하겠습니다.
t1 <- temp %>%
filter(user_gender == "남성") %>%
group_by(song_id) %>%
summarise(
male_user_count = n_distinct(user_id),
male_streaming_count = sum(streaming_count)
) %>%
ungroup() %>%
filter(!song_id %in% c("b", "d", "e"))
t2 <- temp %>%
filter(user_gender == "여성") %>%
group_by(song_id) %>%
summarise(
female_user_count = n_distinct(user_id),
female_streaming_count = sum(streaming_count)
) %>%
ungroup()
t1
## # A tibble: 12 x 3
## song_id male_user_count male_streaming_count
## <chr> <int> <int>
## 1 a 2 43
## 2 c 2 33
## 3 f 5 98
## 4 g 7 146
## 5 h 3 50
## 6 i 3 48
## 7 j 2 45
## 8 k 1 24
## 9 l 2 47
## 10 m 3 60
## 11 n 1 16
## 12 o 3 42
t2
## # A tibble: 15 x 3
## song_id female_user_count female_streaming_count
## <chr> <int> <int>
## 1 a 6 104
## 2 b 1 21
## 3 c 2 37
## 4 d 2 35
## 5 e 4 74
## 6 f 4 63
## 7 g 5 100
## 8 h 4 69
## 9 i 1 19
## 10 j 4 82
## 11 k 2 42
## 12 l 7 153
## 13 m 3 65
## 14 n 5 108
## 15 o 4 71
2. left_join()
- 대상이 되는 데이터(왼쪽)를 기준으로 결합이 발생되기에 데이터의 기준도 왼쪽 데이터가 기준이 됩니다.
# song_id를 기준 변수로 하여 left_join(t1, t2)
t1 %>%
left_join(t2, by = "song_id")
## # A tibble: 12 x 5
## song_id male_user_count male_streaming_co… female_user_cou… female_streaming…
## <chr> <int> <int> <int> <int>
## 1 a 2 43 6 104
## 2 c 2 33 2 37
## 3 f 5 98 4 63
## 4 g 7 146 5 100
## 5 h 3 50 4 69
## 6 i 3 48 1 19
## 7 j 2 45 4 82
## 8 k 1 24 2 42
## 9 l 2 47 7 153
## 10 m 3 60 3 65
## 11 n 1 16 5 108
## 12 o 3 42 4 71
# song_id를 기준 변수로 하여 left_join(t2, t1)
t2 %>%
left_join(t1, by = "song_id")
## # A tibble: 15 x 5
## song_id female_user_count female_streaming… male_user_count male_streaming_c…
## <chr> <int> <int> <int> <int>
## 1 a 6 104 2 43
## 2 b 1 21 NA NA
## 3 c 2 37 2 33
## 4 d 2 35 NA NA
## 5 e 4 74 NA NA
## 6 f 4 63 5 98
## 7 g 5 100 7 146
## 8 h 4 69 3 50
## 9 i 1 19 3 48
## 10 j 4 82 2 45
## 11 k 2 42 1 24
## 12 l 7 153 2 47
## 13 m 3 65 3 60
## 14 n 5 108 1 16
## 15 o 4 71 3 42
- 오른쪽 데이터에 왼쪽 기준 변수에 있는 데이터가 없다면 결측처리가 됩니다.
3. inner_join()
inner_join()
의 경우 기준 변수가 매칭이 되는 변수만 식별하여 결합이 발생되기에 데이터 조인의 순서를 바꾸어도 결과는 같습니다.
# song_id를 기준 변수로 하여 inner_join(t1, t2)
t1 %>%
inner_join(t2, by = "song_id")
## # A tibble: 12 x 5
## song_id male_user_count male_streaming_co… female_user_cou… female_streaming…
## <chr> <int> <int> <int> <int>
## 1 a 2 43 6 104
## 2 c 2 33 2 37
## 3 f 5 98 4 63
## 4 g 7 146 5 100
## 5 h 3 50 4 69
## 6 i 3 48 1 19
## 7 j 2 45 4 82
## 8 k 1 24 2 42
## 9 l 2 47 7 153
## 10 m 3 60 3 65
## 11 n 1 16 5 108
## 12 o 3 42 4 71
# song_id를 기준 변수로 하여 inner_join(t2, t1)
t2 %>%
inner_join(t1, by = "song_id")
## # A tibble: 12 x 5
## song_id female_user_count female_streaming… male_user_count male_streaming_c…
## <chr> <int> <int> <int> <int>
## 1 a 6 104 2 43
## 2 c 2 37 2 33
## 3 f 4 63 5 98
## 4 g 5 100 7 146
## 5 h 4 69 3 50
## 6 i 1 19 3 48
## 7 j 4 82 2 45
## 8 k 2 42 1 24
## 9 l 7 153 2 47
## 10 m 3 65 3 60
## 11 n 5 108 1 16
## 12 o 4 71 3 42
4. full_join()
full_join()
은 SQL에서 UNION 역할을 한다고 이해하면 쉽습니다.
# song_id를 기준 변수로 하여 full_join(t1, t2)
t1 %>%
full_join(t2, by = "song_id")
## # A tibble: 15 x 5
## song_id male_user_count male_streaming_co… female_user_cou… female_streaming…
## <chr> <int> <int> <int> <int>
## 1 a 2 43 6 104
## 2 c 2 33 2 37
## 3 f 5 98 4 63
## 4 g 7 146 5 100
## 5 h 3 50 4 69
## 6 i 3 48 1 19
## 7 j 2 45 4 82
## 8 k 1 24 2 42
## 9 l 2 47 7 153
## 10 m 3 60 3 65
## 11 n 1 16 5 108
## 12 o 3 42 4 71
## 13 b NA NA 1 21
## 14 d NA NA 2 35
## 15 e NA NA 4 74
# song_id를 기준 변수로 하여 full_join(t2, t1)
t2 %>%
full_join(t1, by = "song_id")
## # A tibble: 15 x 5
## song_id female_user_count female_streaming… male_user_count male_streaming_c…
## <chr> <int> <int> <int> <int>
## 1 a 6 104 2 43
## 2 b 1 21 NA NA
## 3 c 2 37 2 33
## 4 d 2 35 NA NA
## 5 e 4 74 NA NA
## 6 f 4 63 5 98
## 7 g 5 100 7 146
## 8 h 4 69 3 50
## 9 i 1 19 3 48
## 10 j 4 82 2 45
## 11 k 2 42 1 24
## 12 l 7 153 2 47
## 13 m 3 65 3 60
## 14 n 5 108 1 16
## 15 o 4 71 3 42
5. anti_join()
anti_join()
은 왼쪽 데이터를 오른쪽 데이터로 빼는 차집합 개념이라고 이해하면 됩니다.
# song_id를 기준 변수로 하여 anti_join(t1, t2)
t1 %>%
anti_join(t2, by = "song_id")
## # A tibble: 0 x 3
## # … with 3 variables: song_id <chr>, male_user_count <int>,
## # male_streaming_count <int>
# song_id를 기준 변수로 하여 anti_join(t2, t1)
t2 %>%
anti_join(t1, by = "song_id")
## # A tibble: 3 x 3
## song_id female_user_count female_streaming_count
## <chr> <int> <int>
## 1 b 1 21
## 2 d 2 35
## 3 e 4 74
5. semi_join()
semi_join()
은 왼쪽 데이터를 기준으로 식별 변수가 매칭된 왼쪽 데이터만 출력합니다. 교집합 느낌으로 이해하시면 됩니다.
# song_id를 기준 변수로 하여 semi_join(t1, t2)
t1 %>%
semi_join(t2, by = "song_id")
## # A tibble: 12 x 3
## song_id male_user_count male_streaming_count
## <chr> <int> <int>
## 1 a 2 43
## 2 c 2 33
## 3 f 5 98
## 4 g 7 146
## 5 h 3 50
## 6 i 3 48
## 7 j 2 45
## 8 k 1 24
## 9 l 2 47
## 10 m 3 60
## 11 n 1 16
## 12 o 3 42
# song_id를 기준 변수로 하여 semi_join(t2, t1)
t2 %>%
semi_join(t1, by = "song_id")
## # A tibble: 12 x 3
## song_id female_user_count female_streaming_count
## <chr> <int> <int>
## 1 a 6 104
## 2 c 2 37
## 3 f 4 63
## 4 g 5 100
## 5 h 4 69
## 6 i 1 19
## 7 j 4 82
## 8 k 2 42
## 9 l 7 153
## 10 m 3 65
## 11 n 5 108
## 12 o 4 71
6. 기타 특이사항
- 주의하실 점을 하나 언급드리자면, 어떠한 join 함수를 쓰던간에 조인하고자 하는 두 데이터에 공통된 이름을 갖는 변수명이 있어야합니다.
- 기준 식별변수로 식별되지 않는 공통된 이름을 갖는 변수는 조인 이후
변수명.x
(왼쪽 데이터),변수명.y
(오른쪽 데이터)와 같이 출력됩니다. anti_join()
이나semi_join()
함수는 사실상 조인 함수와filter()
함수를 동반한 역할을 합니다.
분석하는 맥락에 따라서 두 조인 함수를 적절하게 이용하면 효율적으로 처리하실 수 있습니다.
반응형
'tidyverse' 카테고리의 다른 글
[R] 10. 피어슨 상관계수(Pearson's Corrleation) (0) | 2021.07.06 |
---|---|
[R] 9. 기술통계분석 (0) | 2021.07.05 |
[R] 7. 데이터 형태 변환 (0) | 2021.07.05 |
[R] 6. 날짜 및 시간 변수 (lubridate) (3) | 2021.07.05 |
[R] 5. mutate() (0) | 2021.07.05 |
TAGS.