R 테이블 합치기(병합)

  • R

R에서 데이터 프레임이 흩어져있을 때 그것들을 합치는, 즉 병합 방법에 대해 알아본다.

데이터프레임을 병합하는 건 생각보다 단순하지가 않다. 병합할 때 기준이 되는 값을 무엇으로 삼을 것인지, 어디서 어디로 가져올지, 공통적인 값만 가져올지 혹은 다 가져올지(없는 건 그냥 공백으로 남기더라도) 등을 결정해야 하기 때문이다.

본 포스팅에서는 테이블 병합에 주로 활용되는 아래의 함수/메서드들을 소개한다.

  • inner_join()
  • full_join()
  • left_join(), right_join()
  • bind_rows()

물론 SQL 같은 걸 다뤄보았다면 제목만 봐도 어느정도 다 아는 내용일 거다.


Inner Join

inner join은 공통이 되는 값(교집합)만 가져오는 거다. 공통으로 가져올 기준이 없다면 버려진다.

그림으로 설명하면 이런 느낌?

inner join

dplyr에 있는 inner_join()을 쓰면 된다. 이렇게.

df_1 %>%
  inner_join(df_2)

예를 들어 df_1에는 컬럼 A와 B가 있고, df_2에는 컬럼 A와 C가 있었다면, 병합된 테이블은 컬럼 A, B, C로 구성될 거다.

dplyr에 있는 inner_join()을 쓰면 된다. 이렇게.

inner_join(df_1, df_2)

이렇게 써도 되고.

df_1 %>%
  inner_join(df_2)

예를 들어 df_1에는 컬럼 A와 B가 있고, df_2에는 컬럼 A와 C가 있었다면, 병합된 테이블은 컬럼 A, B, C로 구성될 거다.

파이프 %>%로 연결하면 3개 이상의 테이블을 손쉽게 연결할 수 있다. 이렇게.

joined_df <- df_1 %>%
  inner_join(df_2) %>%
  inner_join(df_3)

각 테이블에 병합의 기준으로 삼을 열이 있는 경우, 즉 일치하는 컬럼명이 존재하는 경우에는 위에 제시된 방법으로 해도 아무런 문제가 없다.

그러나 기준이 되는 열 이름이 다를 수가 있다.

※ 병합의 기준이 되는 열을 지정해야 할 때

아래와 같은 두 개의 테이블이 있다고 해보자.

주문 테이블 Orders에 적힌 고객 아이디(customer_id)가 고객 테이블 Customers에 적힌 아이디(id)와 같은 것이니 이걸 기준으로 삼아야 한다. (Orders 테이블의 id는 주문 정보다. 다른 거다.)

방법 1. 컬럼 이름을 변경해서 맞춰준다.

dplyr의 컬럼 명을 바꿔주는 함수 rename()을 사용해서 공통의 컬럼으로 만들어준 후에 병합을 시키면 된다.

customers <- customers %>%
  rename(customer_id = id)

inner_join(orders, customers)

방법 2. by를 사용해서 기준 컬럼을 직접 지정한다.

inner_join() 함수를 호출할 때 by 인자를 사용해서 병합의 기준이 되는 컬럼을 지정해도 된다.

이렇게.

orders %>% 
  inner_join(customers,
             by = c('customer_id' = 'id'))

그런데 이렇게 되면 id라는 같은 이름을 가진 열이 2개 존재하는 꼴이기 때문에 병합된 테이블에는 id_x, id_y 이런 식으로 표시가 된다.

그래서 공통된 이름이 생길 경우를 대비해 suffix를 지정해서 아래와 같이 해결할 수 있다.

orders %>% 
  inner_join(customers,
             by = c('customer_id' = 'id'),
             suffix = c('_order','_customer'))

id_orders, id_customers 로 생성된 걸 알 수 있다.


Full Join

위에서 설명한 inner join 방식은 공통이 되는 값을 찾아 병합하기 때문에 값들이 누락될 수 있다.

예를 들어 orders 테이블에 customer_id가 5라는 값을 가진 행이 있었는데, customer 테이블에서 id가 5인 고객이 없다면 애초에 orders에 있던 그 행은 병합 과정에서 사라지는 거다.

그래서 누락되는 값 없이 모두(합집합) 가져오는 방식이 바로 full join이다. 모든 행이 다 보존된다.

그림으로 설명하면 이런 느낌?

full join

방법은 inner_join()과 마찬가지다. full_join()을 쓰면 된다.

df_1 %>%
  full_join(df_2)

공통으로 찾을 수 없는 항목은 NA가 들어간다.


Left Join & Right Join

병합할 때 특정 테이블을 기준으로 삼을 수도 있다. 특정 테이블에 있는 건 일단 모두 살려두고, 이것과 겹치는 게 있는 경우에만 가져와서 병합하는 방식이다.

left_join() 혹은 right_join()을 사용하면 된다.

left join
right join

사용법은 간단하다.

left_1_2 <- df_1 %>%
  left_join(df_2)

좌우 바뀌는 건 어렵지 않으니 right_join()은 현실적으로 크게 의미 없다. 그냥 left_join()만 알아도 된다.


Bind Rows

이건 위에서 살펴본 테이블 병합과는 조금 개념이 다르다.

그냥 말 그대로 데이터 세트가 여러개로 쪼개져 있을 때 같은 구조로 행만 덧붙이기 위해 사용하는 방법이다. 당연히 모든 열이 동일한 이름을 가지고 있어야 한다.

dplyr의 bind_rows() 함수. 사용 방법은 아래와 같다.

df_all <- df_1 %>%
  bind_rows(df_2)

어려울 게 하나도 없다.


R로 데이터프레임, 테이블 합치는 방법은 여기까지.

추천 글

댓글 남기기