6.5 필터링 조인
필터링 조인(Filtering join)은 변환 조인과 같은 방식으로 관측값을 매칭하지만 변수가 아닌 관측값에 영향을 준다. 두 가지 유형이 있다.
semi_join(x, y)
는y
와 매치되는x
의 모든 관측값을 보존한다 .anti_join(x, y)
는y
와 매치되는x
의 모든 관측값을 삭제한다 .
세미 조인(Semi-joins)은 필터링된 요약 테이블을 다시 원래 행과 매치시키는 데 유용하다. 예를 들어 가장 인기 있는 상위 10개 도착지(dest
)를 구했다고 가정해보자.
<- flights %>%
top_dest count(dest, sort = TRUE) %>%
head(10)
top_dest
## # A tibble: 10 x 2
## dest n
## <chr> <int>
## 1 ORD 17283
## 2 ATL 17215
## 3 LAX 16174
## # ... with 7 more rows
이제 그 목적지 중 한 곳(dest %in% top_dest$dest
)으로 운행한 항공편(flihts
)을 찾고 싶다면 직접 필터를 만들 수 있다.
%>%
flights filter(dest %in% top_dest$dest)
## # A tibble: 141,145 x 19
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 1 1 542 540 2 923 850
## 2 2013 1 1 554 600 -6 812 837
## 3 2013 1 1 554 558 -4 740 728
## # ... with 141,142 more rows, and 11 more variables: arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
그러나 이러한 접근 방식을 여러 변수로 확장하는 것은 어렵다. 예를 들어 평균 연착시간(average arr_delay
)이 가장 길었던 날 10일을 골라냈다고 상상해보라. year, month, day
를 사용하여 다시 항공편(flights
)과 일치시키는 필터 구문을 어떻게 작성할 수 있는가?
한편 변환 조인과 같이 두 테이블을 연결하는 세미 조인을 사용할 수 있지만, 새 열을 추가하는 대신 y
에서 일치하는 x
의 행만 보존한다.
%>%
flights semi_join(top_dest)
## Joining, by = "dest"
## # A tibble: 141,145 x 19
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 1 1 542 540 2 923 850
## 2 2013 1 1 554 600 -6 812 837
## 3 2013 1 1 554 558 -4 740 728
## # ... with 141,142 more rows, and 11 more variables: arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
세미 조인(semi-join)은 그래픽으로 다음과 같이 표현된다.
<- tribble(
x ~key, ~val_x,
1, "x1",
2, "x2",
3, "x3"
)
<- tribble(
y ~key, ~val_y,
1, "y1",
2, "y2",
4, "y3"
)
%>% semi_join(y, by="key") x
## # A tibble: 2 x 2
## key val_x
## <dbl> <chr>
## 1 1 x1
## 2 2 x2
- 매칭되었는지 여부만이 중요하다. 즉, 어떤 관측값이 매칭되는지는 중요하지 않다. 이는 필터링 조인은 뮤테이팅 조인처럼 행을 복제하지는 않는다는 것을 의미한다.
<- tribble(
x ~key, ~val_x,
1, "x1",
2, "x2",
2, "x3",
3, "x4"
)<- tribble(
y ~key, ~val_y,
1, "y1",
2, "y2",
2, "y3",
3, "y4"
)%>% semi_join(y, by="key") x
## # A tibble: 4 x 2
## key val_x
## <dbl> <chr>
## 1 1 x1
## 2 2 x2
## 3 2 x3
## 4 3 x4
세미 조인의 반대는 안티 조인(Anti-join)이다. 안티 조인은 매칭되지 않는 행을 보존한다.
<- tribble(
x ~key, ~val_x,
1, "x1",
2, "x2",
3, "x3"
) x
## # A tibble: 3 x 2
## key val_x
## <dbl> <chr>
## 1 1 x1
## 2 2 x2
## 3 3 x3
<- tribble(
y ~key, ~val_y,
1, "y1",
2, "y2",
4, "y3"
) y
## # A tibble: 3 x 2
## key val_y
## <dbl> <chr>
## 1 1 y1
## 2 2 y2
## 3 4 y3
%>% anti_join(y, by="key") x
## # A tibble: 1 x 2
## key val_x
## <dbl> <chr>
## 1 3 x3
안티 조인(Anti-join)은 조인 불일치를 진단하는 데 유용하다. 예를 들어 flights
과 planes
를 연결하는 경우, planes
에 매치되지 않는 flights
이 많다는 것을 알고 싶을 수 있다.
%>%
flights anti_join(planes, by = "tailnum") %>%
count(tailnum, sort = TRUE)
## # A tibble: 722 x 2
## tailnum n
## <chr> <int>
## 1 <NA> 2512
## 2 N725MQ 575
## 3 N722MQ 513
## # ... with 719 more rows
6.5.1 연습문제
- 항공편에
tailnum
이 없는 것은 무엇을 의미하는가?planes
에 매치되는 관측값이 없는tailnum
관측값의 공통점은 무엇인가? (힌트: 한 변수가 문제의 약 90%를 설명한다.) flights
를 필터링하여 최소 100 편의 운행을 한 여객기의 항공편만 표시하라.fueleconomy::vehicles
와fueleconomy::common
을 결합하여 가장 많은 차량 모델의 레코드만 찾아라.- 최악의 연착 시간을 가진 (1년 중) 48시간을 찾아라. 날씨 데이터와 교차 참조하라. 어떤 패턴을 볼 수 있는가?
anti_join(flights, airports, by = c("dest" = "faa"))
을 보고 무엇을 알 수 있는가?anti_join(airports, flights, by = c("faa" = "dest"))
은 어떤가?- 각 항공기는 단일 항공사에 의해 운항되므로 항공기와 항공사 간에 암묵적인 관계가 있을 것으로 예상할 수 있다. 이전 절에서 배운 도구를 사용하여 이 가설을 확인하거나 기각하라.