두 개의 데이터 프레임이 주어지면 :
df1 = data.frame(CustomerId = c(1:6), Product = c(rep("Toaster", 3), rep("Radio", 3)))
df2 = data.frame(CustomerId = c(2, 4, 6), State = c(rep("Alabama", 2), rep("Ohio", 1)))
df1
# CustomerId Product
# 1 Toaster
# 2 Toaster
# 3 Toaster
# 4 Radio
# 5 Radio
# 6 Radio
df2
# CustomerId State
# 2 Alabama
# 4 Alabama
# 6 Ohio
데이터베이스 스타일, 즉 SQL 스타일을 조인하려면 어떻게해야합니까? 즉, 어떻게 얻을 수 있습니까?
- 내부 조인 의
df1
과df2
:
왼쪽 테이블에 오른쪽 테이블에 키를 일치 한있는 돌아 행만. - 외부 조인 의
df1
과df2
:
두 테이블에서 반환 모든 행은 오른쪽 테이블에 일치하는 키가 왼쪽에서 레코드를 가입 할 수 있습니다. - A는 외부 조인 (또는 간단히 왼쪽에 가입) 왼쪽 의
df1
및df2
우측 테이블에서 키를 일치하는 반환 왼쪽 테이블의 모든 행과 행을. - 오른쪽 외부 조인 의
df1
와df2
왼쪽 테이블에서 키를 일치하는 오른쪽 테이블의 모든 행과 행을 반환.
추가 크레딧 :
SQL 스타일 select 문을 어떻게 수행 할 수 있습니까?
답변
merge
기능 및 선택적 매개 변수 를 사용하여 다음을 수행하십시오.
내부 조인 : merge(df1, df2)
R은 공통 변수 이름으로 프레임을 자동으로 조인하기 때문에 이러한 예제에서 작동하지만merge(df1, df2, by = "CustomerId")
원하는 필드에서만 일치하도록 지정하려고합니다. 일치하는 변수의 이름이 다른 데이터 프레임에서 다른 경우by.x
및by.y
매개 변수를사용할 수도 있습니다.
외부 조인 : merge(x = df1, y = df2, by = "CustomerId", all = TRUE)
왼쪽 바깥 쪽 : merge(x = df1, y = df2, by = "CustomerId", all.x = TRUE)
오른쪽 바깥 쪽 : merge(x = df1, y = df2, by = "CustomerId", all.y = TRUE)
크로스 조인 : merge(x = df1, y = df2, by = NULL)
내부 조인과 마찬가지로 일치 변수로 “CustomerId”를 R에 명시 적으로 전달할 수 있습니다. 거의 항상 병합하려는 식별자를 명시 적으로 언급하는 것이 가장 좋습니다. 입력 데이터 프레임이 예기치 않게 변경되고 나중에 읽기가 더 안전합니다.
by
벡터 를 제공 하여 여러 열을 병합 할 수 있습니다 ( 예 🙂 by = c("CustomerId", "OrderId")
.
병합에 열 이름에 동일하지 않으면, 당신은, 예를 들어, 지정할 수 있습니다 by.x = "CustomerId_in_df1", by.y = "CustomerId_in_df2"
경우 CustomerId_in_df1
첫 번째 데이터 프레임의 열 이름이고, CustomerId_in_df2
두 번째 데이터 프레임의 열 이름입니다. 여러 열에서 병합해야하는 경우 벡터가 될 수도 있습니다.
답변
Gabor Grothendieck의 sqldf package를 확인하여 이러한 작업을 SQL로 표현할 수 있습니다.
library(sqldf)
## inner join
df3 <- sqldf("SELECT CustomerId, Product, State
FROM df1
JOIN df2 USING(CustomerID)")
## left join (substitute 'right' for right join)
df4 <- sqldf("SELECT CustomerId, Product, State
FROM df1
LEFT JOIN df2 USING(CustomerID)")
SQL 구문이 R과 동등한 것보다 간단하고 자연 스럽다는 것을 알았습니다 (그러나 이것은 내 RDBMS 편향을 반영 할 수 있습니다).
조인에 대한 자세한 내용 은 Gabor의 sqldf GitHub 를 참조하십시오.
답변
내부 조인 에는 data.table 접근 방식이 있으며 시간과 메모리 효율성이 뛰어나며 더 큰 데이터 프레임에 필요합니다.
library(data.table)
dt1 <- data.table(df1, key = "CustomerId")
dt2 <- data.table(df2, key = "CustomerId")
joined.dt1.dt.2 <- dt1[dt2]
merge
data.tables에서도 작동합니다 (일반적이고 호출하기 때문에 merge.data.table
)
merge(dt1, dt2)
stackoverflow에 문서화 된 data.table :
data.table 병합 작업을 수행하는 방법
외래 키의 SQL 조인을 R data.table 구문으로 변환 중대형 데이터
를 병합하는 효율적인 대안 프레임 R 데이터
와 기본 왼쪽 외부 조인을 수행하는 방법 R에?
또 다른 옵션은 plyr 패키지 join
에있는 기능입니다
library(plyr)
join(df1, df2,
type = "inner")
# CustomerId Product State
# 1 2 Toaster Alabama
# 2 4 Radio Alabama
# 3 6 Radio Ohio
옵션 type
: inner
, left
, right
, full
.
From ?join
:와 달리 merge
[ join
]는 어떤 조인 유형이 사용 되더라도 x 순서를 유지합니다.
답변
Hadley Wickham의 멋진 dplyr 패키지를 사용하여 조인을 수행 할 수도 있습니다 .
library(dplyr)
#make sure that CustomerId cols are both type numeric
#they ARE not using the provided code in question and dplyr will complain
df1$CustomerId <- as.numeric(df1$CustomerId)
df2$CustomerId <- as.numeric(df2$CustomerId)
조인 변경 : df2의 일치 항목을 사용하여 df1에 열 추가
#inner
inner_join(df1, df2)
#left outer
left_join(df1, df2)
#right outer
right_join(df1, df2)
#alternate right outer
left_join(df2, df1)
#full join
full_join(df1, df2)
필터링 조인 : df1에서 행을 필터링하고 열을 수정하지 마십시오.
semi_join(df1, df2) #keep only observations in df1 that match in df2.
anti_join(df1, df2) #drops all observations in df1 that match in df2.
답변
R Wiki 에서이 작업을 수행하는 좋은 예가 있습니다. 나는 여기서 몇 가지를 훔칠 것이다 :
병합 방법
키 이름이 동일하기 때문에 내부 조인을 수행하는 짧은 방법은 merge ()입니다.
merge(df1,df2)
“all”키워드를 사용하여 전체 내부 조인 (두 테이블의 모든 레코드)을 작성할 수 있습니다.
merge(df1,df2, all=TRUE)
df1 및 df2의 왼쪽 외부 조인 :
merge(df1,df2, all.x=TRUE)
df1과 df2의 오른쪽 외부 조인 :
merge(df1,df2, all.y=TRUE)
당신은 그것을 뒤집고, 때리고 그들을 문지르면 다른 두 개의 외부 조인을 얻을 수 있습니다 🙂
첨자 방법
아래 첨자 방법을 사용하여 왼쪽에서 df1을 사용하는 왼쪽 외부 조인은 다음과 같습니다.
df1[,"State"]<-df2[df1[ ,"Product"], "State"]
외부 외부 조인의 다른 조합은 왼쪽 외부 조인 첨자 예제를 병합하여 만들 수 있습니다. (그렇습니다. “독자 운동으로 남겨 두겠습니다 …”라고 말하는 것과 같습니다.
답변
2014 년 새로운 기능 :
특히 정렬, 필터링, 하위 설정, 요약 등의 일반적인 데이터 조작에 관심 dplyr
이있는 경우 데이터 프레임을 사용하여 작업을 용이하게하도록 설계된 다양한 기능이 포함 된을 살펴보십시오. 그리고 다른 특정 데이터베이스 유형. 심지어 매우 정교한 SQL 인터페이스와 (대부분의) SQL 코드를 R로 직접 변환하는 기능도 제공합니다.
dplyr 패키지의 4 가지 조인 관련 함수는 다음과 같습니다.
inner_join(x, y, by = NULL, copy = FALSE, ...)
: y에 일치하는 값이있는 x의 모든 행과 x와 y의 모든 열을 반환합니다.left_join(x, y, by = NULL, copy = FALSE, ...)
: x의 모든 행과 x와 y의 모든 열을 반환합니다.semi_join(x, y, by = NULL, copy = FALSE, ...)
: x의 열만 유지하면서 y에 일치하는 값이있는 x의 모든 행을 반환합니다.anti_join(x, y, by = NULL, copy = FALSE, ...)
: x의 열만 유지하면서 y에 일치하는 값이없는 x의 모든 행을 반환합니다.
여기 에 모두 자세히 설명되어 있습니다.
로 열을 선택할 수 있습니다 select(df,"column")
. 그것이 SQL-ish가 충분하지 않으면 SQL sql()
코드를 그대로 입력 할 수 있는 기능이 있으며 R을 모두 쓰는 것처럼 지정한 작업을 수행합니다 (자세한 내용은 참조하십시오. 받는 사람 dplyr / 데이터베이스 비네팅 ). 예를 들어, 올바르게 적용되면 sql("SELECT * FROM hflights")
“hflights”dplyr 테이블 ( “tbl”)에서 모든 열을 선택합니다.
답변
데이터 세트 가입을위한 data.table 메서드 업데이트 각 조인 유형에 대한 아래 예를 참조하십시오. 두 [.data.table
번째 data.table을 하위 집합에 대한 첫 번째 인수로 전달할 때 부터 두 가지 방법이 있으며 , 다른 방법은 merge
빠른 data.table 메서드에 디스패치 하는 함수 를 사용 하는 것입니다.
df1 = data.frame(CustomerId = c(1:6), Product = c(rep("Toaster", 3), rep("Radio", 3)))
df2 = data.frame(CustomerId = c(2L, 4L, 7L), State = c(rep("Alabama", 2), rep("Ohio", 1))) # one value changed to show full outer join
library(data.table)
dt1 = as.data.table(df1)
dt2 = as.data.table(df2)
setkey(dt1, CustomerId)
setkey(dt2, CustomerId)
# right outer join keyed data.tables
dt1[dt2]
setkey(dt1, NULL)
setkey(dt2, NULL)
# right outer join unkeyed data.tables - use `on` argument
dt1[dt2, on = "CustomerId"]
# left outer join - swap dt1 with dt2
dt2[dt1, on = "CustomerId"]
# inner join - use `nomatch` argument
dt1[dt2, nomatch=NULL, on = "CustomerId"]
# anti join - use `!` operator
dt1[!dt2, on = "CustomerId"]
# inner join - using merge method
merge(dt1, dt2, by = "CustomerId")
# full outer join
merge(dt1, dt2, by = "CustomerId", all = TRUE)
# see ?merge.data.table arguments for other cases
아래의 벤치 마크는 기본 R, sqldf, dplyr 및 data.table을 테스트합니다.
벤치 마크는 키가없는 / 인덱싱되지 않은 데이터 세트를 테스트합니다. 벤치 마크는 50M-1 행 데이터 세트에서 수행되며, 조인 열에는 50M-2 공통 값이 있으므로 각 시나리오 (내부, 왼쪽, 오른쪽, 전체)를 테스트 할 수 있으며 조인은 여전히 쉽지 않습니다. 결합 알고리즘을 잘 강조하는 결합 유형입니다. 타이밍이의 같다 sqldf:0.4.11
, dplyr:0.7.8
, data.table:1.12.0
.
# inner
Unit: seconds
expr min lq mean median uq max neval
base 111.66266 111.66266 111.66266 111.66266 111.66266 111.66266 1
sqldf 624.88388 624.88388 624.88388 624.88388 624.88388 624.88388 1
dplyr 51.91233 51.91233 51.91233 51.91233 51.91233 51.91233 1
DT 10.40552 10.40552 10.40552 10.40552 10.40552 10.40552 1
# left
Unit: seconds
expr min lq mean median uq max
base 142.782030 142.782030 142.782030 142.782030 142.782030 142.782030
sqldf 613.917109 613.917109 613.917109 613.917109 613.917109 613.917109
dplyr 49.711912 49.711912 49.711912 49.711912 49.711912 49.711912
DT 9.674348 9.674348 9.674348 9.674348 9.674348 9.674348
# right
Unit: seconds
expr min lq mean median uq max
base 122.366301 122.366301 122.366301 122.366301 122.366301 122.366301
sqldf 611.119157 611.119157 611.119157 611.119157 611.119157 611.119157
dplyr 50.384841 50.384841 50.384841 50.384841 50.384841 50.384841
DT 9.899145 9.899145 9.899145 9.899145 9.899145 9.899145
# full
Unit: seconds
expr min lq mean median uq max neval
base 141.79464 141.79464 141.79464 141.79464 141.79464 141.79464 1
dplyr 94.66436 94.66436 94.66436 94.66436 94.66436 94.66436 1
DT 21.62573 21.62573 21.62573 21.62573 21.62573 21.62573 1
당신이 사용하여 수행 할 수있는 조인의 다른 종류가 있습니다주의 data.table
:
– 가입에 대한 업데이트를 당신이 당신의 기본 테이블에 다른 테이블의 값을 조회하려면 –
– 가입에 집계 당신은 당신이하지 않아도 합류 키를 집계 할 경우 – 모든 결과에 가입 실현하기
– 가입 중복 당신이 범위에 의해 병합 할 경우 –
– 압연 가입 – 당신이 병합 / 선행 전방 또는 후방을 굴려 행을 다음의 값에 일치 할 수 있도록하려면
– 비 동등 가입 – 경우 조인 조건이 동일하지 않습니다
재현 할 코드 :
library(microbenchmark)
library(sqldf)
library(dplyr)
library(data.table)
sapply(c("sqldf","dplyr","data.table"), packageVersion, simplify=FALSE)
n = 5e7
set.seed(108)
df1 = data.frame(x=sample(n,n-1L), y1=rnorm(n-1L))
df2 = data.frame(x=sample(n,n-1L), y2=rnorm(n-1L))
dt1 = as.data.table(df1)
dt2 = as.data.table(df2)
mb = list()
# inner join
microbenchmark(times = 1L,
base = merge(df1, df2, by = "x"),
sqldf = sqldf("SELECT * FROM df1 INNER JOIN df2 ON df1.x = df2.x"),
dplyr = inner_join(df1, df2, by = "x"),
DT = dt1[dt2, nomatch=NULL, on = "x"]) -> mb$inner
# left outer join
microbenchmark(times = 1L,
base = merge(df1, df2, by = "x", all.x = TRUE),
sqldf = sqldf("SELECT * FROM df1 LEFT OUTER JOIN df2 ON df1.x = df2.x"),
dplyr = left_join(df1, df2, by = c("x"="x")),
DT = dt2[dt1, on = "x"]) -> mb$left
# right outer join
microbenchmark(times = 1L,
base = merge(df1, df2, by = "x", all.y = TRUE),
sqldf = sqldf("SELECT * FROM df2 LEFT OUTER JOIN df1 ON df2.x = df1.x"),
dplyr = right_join(df1, df2, by = "x"),
DT = dt1[dt2, on = "x"]) -> mb$right
# full outer join
microbenchmark(times = 1L,
base = merge(df1, df2, by = "x", all = TRUE),
dplyr = full_join(df1, df2, by = "x"),
DT = merge(dt1, dt2, by = "x", all = TRUE)) -> mb$full
lapply(mb, print) -> nul
