data.tables의 X [Y] 조인이 완전 외부 조인 또는 왼쪽 조인을 허용하지 않는 이유는 무엇입니까?


123

이것은 data.table 조인 구문에 대한 약간의 철학적 질문입니다. 나는 data.tables에 대한 더 많은 용도를 찾고 있지만 여전히 배우고 있습니다 ...

X[Y]data.tables 의 조인 형식 은 매우 간결하고 편리하며 효율적이지만 제가 알 수있는 한 내부 조인과 오른쪽 외부 조인 만 지원합니다. 왼쪽 또는 전체 외부 조인을 얻으려면 다음을 사용해야합니다 merge.

  • X[Y, nomatch = NA] -Y의 모든 행-오른쪽 외부 결합 (기본값)
  • X[Y, nomatch = 0] -X와 Y 모두 일치하는 행만-내부 조인
  • merge(X, Y, all = TRUE) -X와 Y 모두의 모든 행-완전 외부 결합
  • merge(X, Y, all.x = TRUE) -X의 모든 행-왼쪽 외부 결합

X[Y]조인 형식이 4 가지 유형의 조인을 모두 지원 하면 편리 할 것 같습니다 . 두 가지 유형의 조인 만 지원되는 이유가 있습니까?

나에게 nomatch = 0nomatch = NA매개 변수 값은 수행중인 작업에 대해 그다지 직관적이지 않습니다. merge구문 을 이해하고 기억하는 것이 더 쉽습니다 : all = TRUE, all.x = TRUEall.y = TRUE. X[Y]연산 merge이보다 훨씬 더 비슷 하므로 함수의 매개 변수 대신 조인 구문을 match사용하지 않는 이유는 무엇입니까?mergematchnomatch

다음은 4 가지 조인 유형의 코드 예입니다.

# sample X and Y data.tables
library(data.table)
X <- data.table(t = 1:4, a = (1:4)^2)
setkey(X, t)
X
#    t  a
# 1: 1  1
# 2: 2  4
# 3: 3  9
# 4: 4 16

Y <- data.table(t = 3:6, b = (3:6)^2)
setkey(Y, t)
Y
#    t  b
# 1: 3  9
# 2: 4 16
# 3: 5 25
# 4: 6 36

# all rows from Y - right outer join
X[Y]  # default
#  t  a  b
# 1: 3  9  9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36

X[Y, nomatch = NA]  # same as above
#    t  a  b
# 1: 3  9  9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36

merge(X, Y, by = "t", all.y = TRUE)  # same as above
#    t  a  b
# 1: 3  9  9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36

identical(X[Y], merge(X, Y, by = "t", all.y = TRUE))
# [1] TRUE

# only rows in both X and Y - inner join
X[Y, nomatch = 0]  
#    t  a  b
# 1: 3  9  9
# 2: 4 16 16

merge(X, Y, by = "t")  # same as above
#    t  a  b
# 1: 3  9  9
# 2: 4 16 16

merge(X, Y, by = "t", all = FALSE)  # same as above
#    t  a  b
# 1: 3  9  9
# 2: 4 16 16

identical( X[Y, nomatch = 0], merge(X, Y, by = "t", all = FALSE) )
# [1] TRUE

# all rows from X - left outer join
merge(X, Y, by = "t", all.x = TRUE)
#    t  a  b
# 1: 1  1 NA
# 2: 2  4 NA
# 3: 3  9  9
# 4: 4 16 16

# all rows from both X and Y - full outer join
merge(X, Y, by = "t", all = TRUE)
#    t  a  b
# 1: 1  1 NA
# 2: 2  4 NA
# 3: 3  9  9
# 4: 4 16 16
# 5: 5 NA 25
# 6: 6 NA 36

업데이트 : data.table v1.9.6 on=은 기본 키가 아닌 필드에 대한 임시 조인을 허용 하는 구문을 도입했습니다 . 데이터 프레임 (내부, 외부, 왼쪽, 오른쪽)을 결합 (병합)하는 방법에 대한 jangorecki의 답변무엇입니까? data.table이 처리 할 수있는 추가 조인 유형의 몇 가지 예를 제공합니다.


4
FAQ 1.12 를 읽었 습니까? 당신은 항상 호출 할 수 있습니다 Y[X]당신이 원하는 경우 왼쪽 외부 조인X[Y]rbind(Y[X],X[Y])는 완전 외부를 원하는 경우에 가입
mnel

전체 외부 조인에 대한 더 많은 data.table 접근 방식에 대한 내 대답을 참조하십시오
mnel

@mnel, rbind는 테이블 복사를 포함하므로 unique()전체 조인에 대한 아래 의 접근 방식이 rbind(Y[X],X[Y]). 맞습니까?
Douglas Clark

내가 아는 한, 네. 나는 세 개의 작은 고유 호출이 하나의 큰 호출보다 빠른지 여부를 테스트하지 않았습니다 (예 : unique(c(unique(X[,t]), unique(Y[,t]))X와 Y의 행 수보다 작거나 같은 두 개의 목록 만 결합하므로 메모리 효율성이 더 높아야합니다). .
mnel

2
귀하의 질문은 좋은 설명입니다. 귀하의 질문에서 내 질문에 대한 답변을 찾았습니다. 감사합니다
irriss

답변:


71

FAQ 에서 인용하려면 data.table 1.11 X[Y]과 의 차이점은 무엇입니까 merge(X, Y)?

X[Y] Y (또는 Y가있는 경우 Y의 키)를 인덱스로 사용하여 X의 행을 조회하는 조인입니다.

Y[X] X (또는 X의 키가있는 경우)를 사용하여 Y의 행을 조회하는 조인입니다.

merge(X,Y)동시에 두 가지 방법을 수행합니다. 행의 수 X[Y]Y[X]통상 행수 의해 반환 반면 다를 merge(X,Y)merge(Y,X)동일하다.

그러나 요점을 놓친다. 대부분의 작업은 조인 또는 병합 후 데이터에서 수행해야하는 작업이 필요합니다. 데이터의 모든 열을 병합하고 나중에 열의 일부만 사용하는 이유는 무엇입니까? 을 제안 할 수 merge(X[,ColsNeeded1],Y[,ColsNeeded2])있지만 프로그래머가 필요한 열을 파악해야합니다. X[Y,j] in data.table은 모든 작업을 한 번에 수행합니다. 를 작성할 때 X[Y,sum(foo*bar)]data.table은 j표현식을 자동으로 검사하여 사용하는 열을 확인합니다. 해당 열만 하위 집합으로 만듭니다. 나머지는 무시됩니다. 메모리는 j사용 하는 열에 대해서만 생성 되며 Y열은 각 그룹의 컨텍스트 내에서 표준 R 재활용 규칙을 사용합니다. foo가에 X있고 바가 에 있다고 가정 해 보겠습니다 (의 Y다른 열 20 개와 함께 Y). 그렇지 않다X[Y,sum(foo*bar)] 모든 것을 낭비하고 하위 집합으로 병합하는 것보다 프로그래밍이 더 빠르며 실행이 더 빠릅니다.


왼쪽 외부 조인을 원하는 경우 X[Y]

le <- Y[X]
mallx <- merge(X, Y, all.x = T)
# the column order is different so change to be the same as `merge`
setcolorder(le, names(mallx))
identical(le, mallx)
# [1] TRUE

완전 외부 조인을 원하는 경우

# the unique values for the keys over both data sets
unique_keys <- unique(c(X[,t], Y[,t]))
Y[X[J(unique_keys)]]
##   t  b  a
## 1: 1 NA  1
## 2: 2 NA  4
## 3: 3  9  9
## 4: 4 16 16
## 5: 5 25 NA
## 6: 6 36 NA

# The following will give the same with the column order X,Y
X[Y[J(unique_keys)]]

5
감사합니다 @mnel. FAQ 1.12는 전체 또는 왼쪽 외부 조인을 언급하지 않습니다. unique ()를 사용한 전체 외부 조인 제안은 큰 도움이됩니다. FAQ에 있어야합니다. 저는 Matthew Dowle이 "자신의 사용을 위해 설계했으며 그렇게 원했습니다." (FAQ 1.9),하지만 X[Y,all=T]data.table X [Y] 구문 내에서 전체 외부 조인을 지정하는 우아한 방법이 될 수 있다고 생각했습니다 . 또는 X[Y,all.x=T]왼쪽 조인의 경우. 왜 그렇게 설계되지 않았는지 궁금했습니다. 그냥 생각.
Douglas Clark

1
@DouglasClark 답변을 추가하고 2302 : Add mnel 's merge join syntax to FAQ (with timings) . 훌륭한 제안!
Matt Dowle

1
@mnel 솔루션 주셔서 감사합니다 ... 내 하루를 만들었습니다 ... :)
Ankit

@mnel 수행 할 때 NA를 0으로 대치 할 수있는 방법이 X[Y[J(unique_keys)]]있습니까?
Ankit 2014

11
data.table 문서에 대해 저에게 깊은 인상을주는 것은 매우 장황 할 수 있지만 여전히 비밀 스럽습니다 ...
NiuBiBang

24

@mnel의 대답이 자리 잡고 있으므로 그 대답을 수락하십시오. 이것은 단지 후속 조치이며, 댓글이 너무 깁니다.

mnel가 말했듯이, 왼쪽 / 오른쪽 외부는 교환에 의해 얻어진다 조인 YX: Y[X]일등석 X[Y]. 따라서 4 개의 조인 유형 중 3 개가 해당 구문에서 지원되며 2, iiuc가 아닙니다.

4를 추가하는 것이 좋은 생각 인 것 같습니다. full=TRUE또는 both=TRUE또는 merge=TRUE(가장 좋은 인수 이름이 확실하지 않습니까?)를 추가한다고 가정 해 봅시다. 그러면 X[Y,j,merge=TRUE]FAQ 1.12의 이후 이유 때문에 유용 할 것입니다. 이제 새로운 기능 요청이 추가되고 여기에 다시 연결되었습니다. 감사합니다.

FR # 2301 : merge ()처럼 X [Y]와 Y [X] 조인 모두에 merge = TRUE 인수를 추가합니다.

최근 버전의 속도가 빨라졌습니다 merge.data.table(예 : 키를보다 효율적으로 설정하기 위해 내부적으로 얕은 복사본을 가져옴). 그래서 우리가 가지고하려고 merge()하고 X[Y]가까이, 전체 유연성을 사용자에게 모든 옵션을 제공합니다. 둘 다 장단점이 있습니다. 또 다른 뛰어난 기능 요청은 다음과 같습니다.

FR # 2033 : merge.data.table에 by.x 및 by.y 추가

다른 사람이 있으면 계속 오십시오.

질문의이 부분에서 :

match 함수의 nomatch 매개 변수 대신 조인에 병합 구문을 사용하지 않는 이유는 무엇입니까?

원하는 경우 merge()구문과의 3 개 인자 all, all.xall.y다음 그냥 대신에 그것을 사용 X[Y]. 모든 경우를 포함해야한다고 생각하십시오. 아니면 왜 논쟁이 싱글 nomatch[.data.table건가요? 그렇다면 FAQ 2.14 : "data.table이 base의 A [B] 구문에서 영감을 얻은 이유를 더 설명해 주시겠습니까?". 그러나 nomatch현재 0NA. 음수 값이 무언가를 의미하도록 확장 될 수 있습니다. 또는 12는 12 번째 행의 값을 사용하여 NA를 채우는 것을 의미하거나 nomatch미래에는 벡터 또는 그 자체가 data.table.

흠. by-without-by 는 merge = TRUE와 어떻게 상호 작용합니까? 아마도 우리는 이것을 datatable-help 로 가져 가야합니다 .


감사합니다 @Matthew. @mnel의 대답은 훌륭하지만 제 질문은 전체 또는 왼쪽 조인을 수행하는 방법이 아니라 "두 가지 유형의 조인 만 지원되는 이유가 있습니까?"였습니다. 그래서 지금은 좀 더 철학적입니다 ;-) 사실 저는 병합 구문을 선호하지 않습니다.하지만 기존의 사람들이 익숙한 것을 구축하는 R 전통이있는 것 같습니다. 나는 join="all", join="all.x", join="all.y" and join="x.and.y"내 노트의 여백에 낙서 를했다. 그것이 더 나은지 확실하지 않습니다.
Douglas Clark

@DouglasClark 아마도 join그렇게 좋은 생각입니다. 나는 datatable-help에 게시 했으므로 보자. 어쩌면 줄 data.table도에 정착하는 데 시간이. 예를 들어 아직 by-without-by에 도달하고 상속 된 범위에 가입 했습니까?
Matt Dowle 2012 년

위의 의견에서 알 수 있듯이 join데이터 테이블 일 때에 키워드를 추가하는 것이 좋습니다 X[Y,j,join=string].. 조인에 사용할 수있는 문자열 값은 다음과 같습니다. 1) "all.y"및 "right"
Douglas Clark

1
안녕하세요 Matt, data.table 라이브러리는 환상적입니다. 감사합니다. 조인 동작 (기본적으로 올바른 외부 조인)은 주 문서에서 눈에 띄게 설명해야한다고 생각합니다. 이것을 알아내는 데 3 일이 걸렸습니다.
Timothée HENRY

1
@tucson 여기에 링크하기 위해 이제 문제 # 709 로 제출되었습니다 .
매트 Dowle

17

이 "답변"은 토론을위한 제안입니다. 내 의견에 표시된대로 join[.data.table ()에 매개 변수를 추가하여 추가 유형의 조인을 활성화 하는 것이 좋습니다 X[Y,j,join=string].. 4 가지 일반 조인 외에도 3 가지 배타적 조인과 크로스 조인 을 지원할 것을 제안합니다 .

join다양한 결합 유형에 대한 문자열 값 (및 별명)로 제안된다 :

  1. "all.y""right"- 바로 가입, 본 data.table 기본 (nomatch = NA) - 어떤 X 일치가없는 NAS가 모든 Y 행;
  2. "both""inner" -내부 결합 (nomatch = 0)-X와 Y가 일치하는 행만;

  3. "all.x"그리고 "left" -왼쪽 조인-Y가 일치하지 않는 X, NA의 모든 행 :

  4. "outer""full" -완전 외부 조인-X 및 Y의 모든 행, 일치하지 않는 NA

  5. "only.x""not.y"-Y 일치가없는 X 행을 반환하는 비 조인 또는 조인 방지

  6. "only.y""not.x"-X 일치가없는 Y 행을 반환하는 비 조인 또는 조인 방지
  7. "not.both" -다른 테이블과 일치하지 않는 X 및 Y 행을 반환하는 배타적 조인, 즉 배타적 또는 (XOR)
  8. "cross"-X의 각 행이 Y의 각 행과 일치하는 교차 조인 또는 데카르트 곱

기본값 join="all.y"은 현재 기본값에 해당합니다.

"all", "all.x"및 "all.y"문자열 값은 merge()매개 변수에 해당합니다 . "right", "left", "inner"및 "outer"문자열은 SQL 사용자에게 더 적합 할 수 있습니다.

"both"및 "not.both"문자열은 현재 가장 좋은 제안이지만 누군가 내부 조인 및 배타적 조인에 대해 더 나은 문자열 제안을 할 수 있습니다. ( "독점"이 올바른 용어인지 확실하지 않습니다. "XOR"조인에 대한 적절한 용어가 있으면 수정하십시오.)

의 사용은 또는 비 조인 구문 join="not.y"의 대안 이며 아마도 더 명확 할 수 있지만 동일한 지 확실하지 않습니다 (data.table 버전 1.8.3의 새로운 기능).X[-Y,j]X[!Y,j]

교차 조인은 때때로 편리 할 수 ​​있지만 data.table 패러다임에는 맞지 않을 수 있습니다.


1
토론을 위해 이것을 datatable-help 로 보내주십시오 .
Matt Dowle

3
+1하지만, 제발 에 하나 전송 데이터 테이블-도움 , 또는 파일 기능 요청을 . 추가해도 join괜찮지 만 추적기에 들어 가지 않으면 잊혀 질 것입니다.
Matt Dowle 2012

1
나는 당신이 한동안 SO에 로그인하지 않은 것을 봅니다. 그래서 저는 이것을 FR # 2301
Matt Dowle

@MattDowle,이 기능에 +1. ( FR # 2301을 통해 시도 했지만 권한 거부 메시지가 나타납니다).
adilapapaya 2015 년

@adilapapaya RForge에서 GitHub로 이동했습니다. 여기에서 +1하십시오 : github.com/Rdatatable/data.table/issues/614 . Arun은 문제를 잃어 버리지 않도록 포팅했습니다.
Matt Dowle 2015 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.