다른 데이터 합치기(join)
예제 데이터 생성
title
과 last rank
가 들어간 테이블을 만든다.
df1 <- data.frame(title = c('카페', '한식', '유아용품', '양식', '전자제품'), last_rank = c(1,2,3,4,5))
title
과 this rank
가 들어간 테이블을 만든다.
df2 <- data.frame(title = c('한식', '양식', '전자제품', '일식', '꽃'), this_rank = c(1,2,3,4,5))
key
어떤 것을 기준으로 데이터를 합칠 것인지를 나타낸다.
left join
left join은 왼쪽을 기준으로 join
을 한다.
left join 한 결과, 왼쪽에는 데이터는 그대로 복사해 붙여놓고 그 옆에는 올해의 데이터를 넣어준다. 일식
과 꽃
은 올해의 데이터에 있지만 작년을 기준으로 left join 하기 때문에 left join 결과에는 없다.
title
join by title
이라고 나오는데, title
을 키로 join 했다는 것이다. Left join을 할 때 by=title
이라고 수동으로 적어줘도 되고, by
를 적어주지 않으면 공통으로 변수이름이 동일한 것을 찾는다. 공통인 키가 하나면 하나로 join하고 여러 개가 있으면 여러 개를 키로 하여 join 한다.
library(dplyr)
left_join(df1, df2)
Attaching package: ‘dplyr’ The following objects are masked from ‘package:stats’: filter, lag The following objects are masked from ‘package:base’: intersect, setdiff, setequal, union Joining, by = "title" Warning message: “Column `title` joining factors with different levels, coercing to character vector”
title last_rank this_rank 1 카페 1 NA 2 한식 2 1 3 유아용품 3 NA 4 양식 4 2 5 전자제품 5 3
right join
right join은 오른쪽을 기준으로 한다.
right join 한 결과, 올해의 데이터를 다 복사해놓고, 올해의 순위는 동일하고 작년 순위는 올해에 따라 달라진다. 한식은 올해는 1등인데 작년에는 2등이다. 일식과 꽃은 작년 순위건에 없기 때문에 NA
를 채워넣는다.
right_join(df1, df2)
Joining, by = "title" Warning message: “Column `title` joining factors with different levels, coercing to character vector”
title last_rank this_rank 1 한식 2 1 2 양식 4 2 3 전자제품 5 3 4 일식 NA 4 5 꽃 NA 5
left join과 right join 비교
데이터의 순서를 바꾸고 left join 을 하면 right join과 똑같다.
full join
full은 전체를 다 가지고 join
을 하는 것이다. 왼쪽이나 오른쪽이든 하나의 기준이 아니라 전체를 가지고 한다. Full join은 모든 데이터, 서로 다른 모든 데이터에 있는 모든 행을 다 채운다고 생각하면 된다.
full_join(df1, df2)
Joining, by = "title" Warning message: “Column `title` joining factors with different levels, coercing to character vector”
title last_rank this_rank 1 카페 1 NA 2 한식 2 1 3 유아용품 3 NA 4 양식 4 2 5 전자제품 5 3 6 일식 NA 4 7 꽃 NA 5
inner join
inner join은 공통만 뽑아 낸다. 예시에서는 한식, 양식, 전자제품만 공통으로 나왔다. 공통 업종만 뽑아서 새로운 데이터를 나타낸다. Left join을 해서 na 값을 제외한 형태가 inner join과 동일한 형태가 된다.
inner_join(df1, df2)
Joining, by = "title" Warning message: “Column `title` joining factors with different levels, coercing to character vector”
title last_rank this_rank 1 한식 2 1 2 양식 4 2 3 전자제품 5 3
anti join
anti join은 거의 쓸일이 없을 것이다. 왼쪽에서 공통이 없는 부분, 예시에서는 카페, 유아용품은 올해의 데이터에 없다. 카페와 유아용품을 추출하는게 anti join 이다.
anti_join(df1, df2)
Joining, by = "title" Warning message: “Column `title` joining factors with different levels, coercing to character vector”
title last_rank 1 카페 1 2 유아용품 3
실제 데이터 불러오기 및 데이터 변수 처리
판매 데이터 불러오기
sales 데이터를 불러오고 colnames를 이용해 변수명 처리를 한다.
sales <- read.csv('sales.csv', stringsAsFactors = F,
fileEncoding = 'UTF-8')
colnames(sales) <- c('city', 'district', 'gender', 'sales.nm', 'sales.cd', 'ymd', 'sales.num')
업종 코드 데이터 불러오기
productcode 데이터를 불러오고 colnames를 이용해 변수명 처리를 한다.
products <- read.csv("productcode.csv", stringsAsFactors = F,
fileEncoding = "UTF-8")
colnames(products) <- c('products.cd', 'products.nm')
기후 데이터 불러오기
seoul_climate 데이터를 불러오고 colnames를 이용해 변수명 처리를 한다.
climates <- read.csv('seoul_climate.csv', stringsAsFactors = F,
fileEncoding = 'UTF-8')
colnames(climates) <- c('city', 'district', 'ym', 'lon', 'lat', 'rainfall')
데이터 확인
head
를 이용해 데이터를 탐색적으로 확인한다.
sales %>% head
city district gender sales.nm sales.cd ymd sales.num 1 서울특별시 강남구 남 스탑버스 12AA02 20140101 103 2 서울특별시 강남구 여 키즈랜드 100101 20140101 309 3 서울특별시 강남구 여 키즈랜드 100101 20140101 365 4 서울특별시 강남구 남 스탑버스 12AA02 20140101 421 5 서울특별시 강남구 여 스탑버스 12AA02 20140101 413 6 서울특별시 강남구 남 키즈랜드 100101 20140101 428
head
를 이용해 데이터를 탐색적으로 확인한다.
products %>% head
products.cd products.nm 1 1001 유아용품 2 1002 한식 3 1100 완구 4 12AA 카페
판매 데이터에 업종코드 변수 추가하기
판매 데이터에는 업종 코드가 없다. 그래서 점포명 코드에서 업종코드를 줘야한다. mutate
를 사용하여 추가한다.
sales <- sales %>% mutate(products.cd = substr(sales.cd, 1, 4))
판매 데이터와 업종코드 데이터 left join
판매 데이터에 생성한 products.cd
라는 변수를 키로 left join을 한다. 판매 데이터에는 업종코드가 있지만 업종명이 없다.
결과, products.cd
이외에 업종명(products.nm)이 붙어있는 것을 확인할 수 있다
sales <- left_join(sales, products, by = 'products.cd')
데이터 확인
head
를 이용해 데이터를 탐색적으로 확인한다.
기후 데이터 같은 경우에 2014년 1월에 강남구는 하나 밖에 없다. 판매 데이터를 보면 2014년 1월에 강남구에 데이터가 엄청 많다. 그러면 새로운 강수량 변수는 다 동일한 값이 붙는다. 왜냐하면 2014년 강남구는 다 동일한 강수량을 갖고 있기 때문이다.
climates %>% head
city district ym lon lat rainfall 1 서울특별시 강남구 201401 37.49666 127.063 NA 2 서울특별시 강남구 201402 37.49666 127.063 187 3 서울특별시 강남구 201403 37.49666 127.063 122 4 서울특별시 강남구 201404 37.49666 127.063 0 5 서울특별시 강남구 201405 37.49666 127.063 NA 6 서울특별시 강남구 201406 37.49666 127.063 144
head
를 이용해 데이터를 탐색적으로 확인한다.
연월일이 있는데 연월만 있는 데이터가 없다. 연월이 있는 데이터를 판매 데이터에서 만들어서 다시 판매 데이터에서 집어넣자.
결과 확인 판매 데이터를 확인하면 연월 데이터가 붙은 것을 확인할 수 있다.
sales %>% head
city district gender sales.nm sales.cd ymd sales.num products.cd 1 서울특별시 강남구 남 스탑버스 12AA02 20140101 103 12AA 2 서울특별시 강남구 여 키즈랜드 100101 20140101 309 1001 3 서울특별시 강남구 여 키즈랜드 100101 20140101 365 1001 4 서울특별시 강남구 남 스탑버스 12AA02 20140101 421 12AA 5 서울특별시 강남구 여 스탑버스 12AA02 20140101 413 12AA 6 서울특별시 강남구 남 키즈랜드 100101 20140101 428 1001 products.nm 1 카페 2 유아용품 3 유아용품 4 카페 5 카페 6 유아용품
판매 데이터에 변수 추가
판매 데이터에는 연월일이 붙어있고 연월에 해당하는 변수가 없다. 따라서 mutate
를 이용해 판매 데이터에 연월에 해당하는 변수를 만들어준다.
sales <- sales %>% mutate(ym = substr(ymd, 1, 6))
판매 데이터와 기후 데이터 left join
sales <- left_join(sales, climates)
Joining, by = c("city", "district", "ym")
Error: Can't join on 'ym' x 'ym' because of incompatible types (integer / character) Traceback: 1. left_join(sales, climates) 2. left_join.data.frame(sales, climates) 3. as.data.frame(left_join(tbl_df(x), y, by = by, copy = copy, ...)) 4. left_join(tbl_df(x), y, by = by, copy = copy, ...) 5. left_join.tbl_df(tbl_df(x), y, by = by, copy = copy, ...) 6. left_join_impl(x, y, by_x, by_y, aux_x, aux_y, na_matches, environment())
오류 발생
ym
을 기준으로 join을 하는데 district
와 city
도 들어간다. 키가 3개가 들어간다.
str
str로 데이터 타입을 확인한다. 판매 데이터에서 ym
은 캐릭터고 기후 데이터에서 ym
은 정수로 되어 타입이 맞지 않아 join시 오류가 생긴것이다.
str(sales)
'data.frame': 262800 obs. of 10 variables: $ city : chr "서울특별시" "서울특별시" "서울특별시" "서울특별시" ... $ district : chr "강남구" "강남구" "강남구" "강남구" ... $ gender : chr "남" "여" "여" "남" ... $ sales.nm : chr "스탑버스" "키즈랜드" "키즈랜드" "스탑버스" ... $ sales.cd : chr "12AA02" "100101" "100101" "12AA02" ... $ ymd : int 20140101 20140101 20140101 20140101 20140101 20140101 20140101 20140101 20140101 20140101 ... $ sales.num : int 103 309 365 421 413 428 287 363 88 117 ... $ products.cd: chr "12AA" "1001" "1001" "12AA" ... $ products.nm: chr "카페" "유아용품" "유아용품" "카페" ... $ ym : chr "201401" "201401" "201401" "201401" ...
str(climates)
'data.frame': 600 obs. of 6 variables: $ city : chr "서울특별시" "서울특별시" "서울특별시" "서울특별시" ... $ district: chr "강남구" "강남구" "강남구" "강남구" ... $ ym : int 201401 201402 201403 201404 201405 201406 201407 201408 201409 201410 ... $ lon : num 37.5 37.5 37.5 37.5 37.5 ... $ lat : num 127 127 127 127 127 ... $ rainfall: int NA 187 122 0 NA 144 0 0 0 NA ...
문제 해결하기
한 쪽을 숫자로 맞추거나 다른 쪽을 문자로 타입을 맞추면 된다. 기후 데이터가 더 적기 때문에 여기서는 문자로 맞췄다.
as.character
를 사용하여 ym
을 캐릭터로 변환한다.
climates$ym <- as.character(climates$ym)
left join
join 결과 정상적으로 오류없이 잘 붙었다.
sales <- left_join(sales, climates)
Joining, by = c("city", "district", "ym")
NA만 자르고 다시 결과 확인
join 결과, 2014년 2월은 다 187로 강수량이 나와있다.
sales %>% filter(!is.na(rainfall)) %>% head
city district gender sales.nm sales.cd ymd sales.num products.cd 1 서울특별시 강남구 남 베타문구 110002 20140205 17 1100 2 서울특별시 강남구 여 카페베타 12AA01 20140205 347 12AA 3 서울특별시 강남구 NA 원조한식 100201 20140205 203 1002 4 서울특별시 강남구 여 원조백반 100202 20140205 107 1002 5 서울특별시 강남구 NA 키즈랜드 100101 20140205 451 1001 6 서울특별시 강남구 여 @ @ 20140205 493 @ products.nm ym lon lat rainfall 1 완구 201402 37.49666 127.063 187 2 카페 201402 37.49666 127.063 187 3 한식 201402 37.49666 127.063 187 4 한식 201402 37.49666 127.063 187 5 유아용품 201402 37.49666 127.063 187 6 NA 201402 37.49666 127.063 187
기후 데이터를 다시 찍어봐 비교 확인한다. 2014년 2월이 187인 것을 알 수 있다.