X [Y] डेटा से क्यों जुड़ता है। टेबल्स एक पूर्ण बाहरी जॉइन, या लेफ्ट जॉइन की अनुमति नहीं देते हैं?


123

यह डेटा के बारे में एक दार्शनिक सवाल है। वाक्य रचना में शामिल होने के लिए। मैं data.tables के लिए अधिक से अधिक उपयोग पा रहा हूं, लेकिन अभी भी सीख रहा हूं ...

X[Y]Data.tables के लिए शामिल होने का प्रारूप बहुत संक्षिप्त, आसान और कुशल है, लेकिन जहां तक ​​मैं बता सकता हूं, यह केवल आंतरिक जोड़ और सही बाहरी जोड़ का समर्थन करता है। बाएं या पूर्ण बाहरी जुड़ने के लिए, मुझे उपयोग करने की आवश्यकता है merge:

  • X[Y, nomatch = NA] - Y में सभी पंक्तियाँ - सही बाहरी जुड़ना (डिफ़ॉल्ट)
  • X[Y, nomatch = 0] - एक्स और वाई दोनों में मैचों के साथ केवल पंक्तियाँ - भीतरी जुड़ती हैं
  • merge(X, Y, all = TRUE) - एक्स और वाई दोनों से सभी पंक्तियाँ - पूर्ण बाहरी जुड़ती हैं
  • merge(X, Y, all.x = TRUE) - एक्स में सभी पंक्तियाँ - बाहरी जुड़ाव छोड़ दें

यह मुझे लगता है कि यह आसान होगा यदि X[Y]जॉइन फॉर्मेट ने सभी 4 प्रकार के जॉइन का समर्थन किया। क्या एक कारण केवल दो प्रकार के जोड़ का समर्थन है?

मेरे लिए, nomatch = 0और nomatch = NAपैरामीटर मान प्रदर्शन किए जा रहे कार्यों के लिए बहुत सहज नहीं हैं। यह आसान मुझे समझने के लिए और याद है merge: वाक्य रचना all = TRUE, all.x = TRUEऔर all.y = TRUE। चूंकि X[Y]ऑपरेशन की mergeतुलना में बहुत अधिक है match, क्यों नहीं के mergeबजाय जोड़ के लिए वाक्यविन्यास का उपयोग करेंmatch फ़ंक्शन के nomatchपैरामीटर के ?

यहाँ 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
क्या आपने 1.12 पढ़े हैं ? आप हमेशा कॉल कर सकते हैं Y[X]अगर आप चाहते हैं छोड़ दिया बाहरी में शामिल होने के X[Y]और rbind(Y[X],X[Y])अगर आप एक पूर्ण बाहरी चाहते में शामिल होने के
mnel

पूर्ण बाहरी के लिए एक अधिक data.table दृष्टिकोण के लिए मेरा उत्तर देखें में शामिल होने के
mnel

@, मुझे लगता है unique()कि पूर्ण दृष्टिकोण के लिए नीचे आपका दृष्टिकोण बेहतर है rbind(Y[X],X[Y]), क्योंकि rbind में तालिका की प्रतिलिपि शामिल होगी। क्या वह सही है?
डगलस क्लार्क

मेरे ज्ञान का सबसे अच्छा करने के लिए, हाँ। मैंने परीक्षण नहीं किया है कि क्या तीन छोटी अनोखी कॉलें एक से अधिक त्वरित हैं (जैसे unique(c(unique(X[,t]), unique(Y[,t]))- यह अधिक मेमोरी कुशल होनी चाहिए क्योंकि यह केवल दो सूचियों का संयोजन है जो एक्स और वाई में पंक्तियों की संख्या से कम या बराबर होने वाली हैं ।
एमल

2
आपका प्रश्न इतना अच्छा विवरण; मुझे आपके सवालों के जवाब मिले। धन्यवाद
irriss

जवाबों:


71

FAQ 1.11 से उद्धृत करने के लिए और data.table क्या अंतर है ?X[Y]merge(X, Y)

X[Y] एक जुड़ाव है, एक सूचकांक के रूप में Y (या Y की कुंजी का उपयोग करने पर X) की पंक्तियों को देखना।

Y[X] एक जुड़ाव है, X का उपयोग करके Y की पंक्तियों को देख रहा है (या X की कुंजी यदि यह एक है)

merge(X,Y)एक ही समय में दोनों तरीके से करता है। की पंक्तियों की संख्या X[Y]और Y[X]आमतौर पर भिन्न होती है, जबकि पंक्तियों की संख्या द्वारा merge(X,Y)और वापस लौटाया जाता हैmerge(Y,X) उसी के समान होती है।

लेकिन मुख्य बिंदु याद आती है। अधिकांश कार्यों में शामिल होने या विलय के बाद डेटा पर कुछ करने की आवश्यकता होती है। डेटा के सभी स्तंभों को मर्ज क्यों किया जाता है, केवल बाद में उनमें से एक छोटे उपसमूह का उपयोग करने के लिए? आप सुझाव दे सकते हैं merge(X[,ColsNeeded1],Y[,ColsNeeded2]), लेकिन इसके लिए प्रोग्रामर को यह काम करना पड़ता है कि किन कॉलमों की जरूरत है। X[Y,j] data.table में वह सब आपके लिए एक स्टेप में होता है। जब आप लिखते हैं X[Y,sum(foo*bar)], तो data.table अपने आप jयह देखने के लिए अभिव्यक्ति का निरीक्षण करता है कि यह किस कॉलम का उपयोग करता है। यह केवल उन कॉलमों को ही सब्मिट करेगा; दूसरों की अनदेखी की जाती है। मेमोरी केवल कॉलम के लिए बनाई गई हैj उपयोग , और Yकॉलम प्रत्येक समूह के संदर्भ में मानक आर रीसाइक्लिंग नियमों का आनंद लेते हैं। मान लें कि अंदर 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 1.12 पूर्ण या बाएँ बाहरी जुड़ाव का उल्लेख नहीं करता है। अद्वितीय () के साथ आपका पूर्ण बाहरी जुड़ाव सुझाव एक बड़ी मदद है। यह अक्सर पूछे जाने वाले प्रश्न में होना चाहिए। मुझे पता है कि मैथ्यू डोले ने "इसे अपने स्वयं के उपयोग के लिए डिज़ाइन किया था, और वह इसे इस तरह से चाहते थे।" (FAQ 1.9), लेकिन मुझे लगा X[Y,all=T]कि डेटाटेबल X [Y] सिंटैक्स के भीतर एक पूर्ण बाहरी जुड़ाव निर्दिष्ट करने का एक सुंदर तरीका हो सकता है। या X[Y,all.x=T]लेफ्ट जॉइन के लिए। मैंने सोचा कि क्यों इसे इस तरह से डिज़ाइन नहीं किया गया था। सिर्फ एक विचार।
डगलस क्लार्क

1
@DouglasClark ने उत्तर जोड़ा है, और 2302 दायर किया है : मेल के मर्ज को वाक्यविन्यास में FAQ (समय के साथ) में जोड़ें । शानदार सुझाव!
मैट डॉवले

1
@ समाधान के लिए धन्यवाद ... मेरा दिन बना दिया ... :)
अंकित

@ किसी भी तरह से हम प्रदर्शन करते समय NA के साथ 0 को थोप सकते हैं X[Y[J(unique_keys)]]?
अंकित

11
डेटाटेबल डॉक्यूमेंटेशन के बारे में मुझे जो प्रभावित करता है, वह यह है कि यह इतना वर्बोज़ हो सकता है, फिर भी इतना गूढ़ रह सकता है ...
NiuBiBang

24

@ मेल का जवाब हाजिर है, इसलिए उस जवाब को स्वीकार करें। यह केवल अनुवर्ती है, टिप्पणियों के लिए बहुत लंबा है।

जैसा कि मेल कहता है, बाएं / दाएं बाहरी जोड़ को स्वैप करके प्राप्त किया जाता है : Yऔर -vs-XY[X]X[Y] । तो 4 जोड़ प्रकारों में से 3 उस वाक्य रचना में समर्थित हैं, 2 नहीं, iiuc।

4 क जोड़ना एक अच्छा विचार है। चलो हम जोड़ने का कहना है कि full=TRUEया both=TRUEया merge=TRUE(नहीं यकीन है कि सबसे अच्छा तर्क नाम?) तो यह मेरे लिए नहीं हुआ था पहले कि X[Y,j,merge=TRUE]के बाद, लेकिन अकसर किये गए सवाल 1.12 में कारणों के लिए उपयोगी होगा। नई सुविधा अनुरोध अब जोड़ा गया है और यहाँ वापस लिंक किया गया है, धन्यवाद:

FR # 2301: X [Y] और Y [X] दोनों के लिए मर्ज = TRUE तर्क जोड़ें, मर्ज () करता है।

हाल के संस्करणों ने उगल दिया है merge.data.table(उदाहरण के लिए, अधिक कुशलता से चाबियाँ सेट करने के लिए आंतरिक रूप से एक उथले प्रति लेकर)। इसलिए हम पूर्ण लचीलेपन के लिए उपयोगकर्ता को सभी विकल्प लाने merge()और X[Y]पास करने की कोशिश कर रहे हैं । दोनों के पक्ष और विपक्ष हैं। एक अन्य उत्कृष्ट सुविधा अनुरोध है:

FR # 2033: by.x और by.y को merge.data.table में जोड़ें

यदि कोई अन्य हैं, तो कृपया उन्हें आते रहें।

प्रश्न में इस भाग द्वारा:

क्यों मैच समारोह के नाममात्र पैरामीटर के बजाय जॉइन के लिए मर्ज सिंटैक्स का उपयोग नहीं करते हैं?

यदि आप merge()वाक्यविन्यास और उसके 3 तर्क पसंद करते हैं all, all.xऔर all.yउसके बाद केवल इसका उपयोग करते हैं X[Y]। सोचें कि यह सभी मामलों को कवर करना चाहिए। या फिर आप मतलब था क्यों तर्क एक भी है nomatchमें [.data.table? यदि ऐसा है, तो यह ऐसा तरीका है जो स्वाभाविक रूप से दिया गया था 2.14 प्रश्न: "क्या आप आगे बता सकते हैं कि डेटाटेबल ए [बी] सिंटैक्स द्वारा आधार में क्यों प्रेरित है?"। लेकिन यह भी, nomatchवर्तमान में केवल दो मान लेता है 0और NA। इसे बढ़ाया जा सकता है ताकि एक नकारात्मक मूल्य का मतलब कुछ हो, या 12 का मतलब 12 वीं पंक्ति के मूल्यों को NAs में भरने के लिए उपयोग करना होगा, उदाहरण के लिए, या nomatchभविष्य में एक वेक्टर या यहां तक ​​कि स्वयं भी हो सकता है data.table

हम्म। मर्ज = TRUE के साथ कैसे - कैसे -के बिना बातचीत हो सकती है? शायद हमें इसे अधिक मदद के लिए मदद के लिए ले जाना चाहिए ।


धन्यवाद @ मट्टू। @ मेल का जवाब बहुत अच्छा है, लेकिन मेरा सवाल यह नहीं था कि कैसे एक पूर्ण या बाईं ओर जुड़ना है, लेकिन "क्या एक कारण केवल दो प्रकार के जुड़ने का समर्थन है?" तो अब यह थोड़ा और दार्शनिक है ;-) असल में मैं मर्ज सिंटैक्स पसंद नहीं करता, लेकिन मौजूदा सामान पर निर्माण के लिए एक आर परंपरा प्रतीत होती है जिससे लोग परिचित हैं। मैंने join="all", join="all.x", join="all.y" and join="x.and.y"अपने नोट्स के मार्जिन में स्क्रूटनी की थी । यकीन नहीं होता है कि अगर कोई बेहतर है।
डगलस क्लार्क

@DouglasClark शायद ऐसा joinही हो, अच्छा विचार है। मैंने डाटिटेबल-हेल्प पर पोस्ट किया है तो चलिए देखते हैं। शायद data.tableकुछ समय के लिए, में भी बसने के लिए दे । क्या आप उदाहरण के लिए अभी तक बिना-पास के हैं , और विरासत में मिला है ?
मैट डॉवेल

जैसा कि ऊपर मेरी टिप्पणी में संकेत दिया गया है, मैं सुझाव देता हूं कि मैं एक joinकीवर्ड जोड़ दूं , जब मैं एक डेटा योग्य हो X[Y,j,join=string]:। जुड़ने के संभावित स्ट्रिंग मान इस प्रकार हैं: 1) "all.y" और "right" -
डगलस क्लार्क

1
हाय मैट, data.table पुस्तकालय शानदार है; उसके लिये आपका धन्यवाद; हालाँकि मुझे लगता है कि मुख्य दस्तावेज में मुख्य रूप से सम्मिलित व्यवहार (डिफ़ॉल्ट रूप से सही बाहरी जुड़ाव) होना चाहिए; यह पता लगाने में मुझे 3 दिन लगे।
टिमोथी हेनरी

1
@tucson बस यहाँ लिंक करने के लिए, अब # 709 इश्यू के रूप में दायर किया गया है ।
मैट डोले

17

यह "उत्तर" चर्चा के लिए एक प्रस्ताव है: जैसा कि मेरी टिप्पणी में संकेत दिया गया है, मैं सुझाव देता हूं कि joinअतिरिक्त प्रकार के जंक्शनों को सक्षम करने के लिए [.data.table () में एक पैरामीटर जोड़ा जाए, अर्थात X[Y,j,join=string]:। 4 प्रकार के साधारण जॉइन के अलावा, मैं 3 प्रकार के एक्सक्लूसिव जॉइन का समर्थन करने का भी सुझाव देता हूं , और क्रॉस जॉइन करता हूं ।

joinविभिन्न प्रकार में शामिल होने के लिए स्ट्रिंग मूल्यों (और अन्य नाम) होने के लिए प्रस्तावित कर रहे हैं:

  1. "all.y"और "right"- राइट जॉइन, वर्तमान डेटा। टायलेट डिफ़ॉल्ट (नोमैच = एनए) - एनए के साथ सभी वाई पंक्तियां जहां कोई एक्स मैच नहीं है;
  2. "both"और "inner" - इनर जॉइन (नामांक = 0) - केवल पंक्तियाँ जहाँ X और Y मेल खाते हैं;

  3. "all.x"और "left" - लेफ्ट जॉइन - एक्स, एनए से सभी पंक्तियाँ जहाँ कोई वाई मैच नहीं है:

  4. "outer"और "full" - पूर्ण बाहरी जुड़ाव - X और Y से सभी पंक्तियाँ, NA जहां कोई मेल नहीं है

  5. "only.x"और "not.y"- गैर-जॉइन या एंटी-जॉइनिंग रिटर्निंग एक्स पंक्तियां जहां कोई वाई मैच नहीं है

  6. "only.y" और "not.x"- गैर-जॉइन या एंटी-जॉइनिंग वाई पंक्तियां जहां कोई एक्स मैच नहीं है
  7. "not.both" - एक्स और वाई पंक्तियों को वापस लाने में विशेष रूप से शामिल हों जहां दूसरी तालिका से कोई मेल नहीं है, अर्थात एक विशेष या (एक्सओआर)
  8. "cross"- एक्स की प्रत्येक पंक्ति के साथ क्रॉस जॉइन या कार्टेशियन उत्पाद वाई की प्रत्येक पंक्ति से मेल खाते हैं

डिफ़ॉल्ट मान वह है join="all.y"जो वर्तमान डिफ़ॉल्ट से मेल खाता है।

"सभी", "all.x" और "all.y" स्ट्रिंग मान merge()पैरामीटर के अनुरूप हैं । "राइट", "लेफ्ट", "इनर" और "बाहरी" स्ट्रिंग्स SQL ​​उपयोगकर्ताओं के लिए अधिक उत्तरदायी हो सकते हैं।

"दोनों" और "not.both" तार इस समय मेरा सबसे अच्छा सुझाव हैं - लेकिन किसी के पास आंतरिक जुड़ने और अनन्य जुड़ने के लिए बेहतर स्ट्रिंग सुझाव हो सकते हैं। (मुझे यकीन नहीं है कि अगर "एक्सक्लूसिव" सही शब्दावली है, तो मुझे सही करें अगर "एक्सओआर" में शामिल होने के लिए उचित शब्द है।)

उपयोग की join="not.y"के लिए एक विकल्प है X[-Y,j]या X[!Y,j], (मेरे लिए) वाक्य रचना और हो सकता है और अधिक स्पष्ट गैर में शामिल होने हालांकि मुझे यकीन है कि नहीं अगर वे एक ही (data.table संस्करण 1.8.3 में नई सुविधा) कर रहे हैं रहा हूँ।

क्रॉस जॉइन कभी-कभी आसान हो सकता है, लेकिन यह डेटाटेबल प्रतिमान में फिट नहीं हो सकता है।


1
कृपया इसे चर्चा के लिए डेटा-हेल्प-हेल्प पर भेजें ।
मैट डॉवेल

3
+1 लेकिन, कृपया या तो डेटा -मदद करने के लिए भेजें , या एक सुविधा अनुरोध दर्ज करें । मुझे जोड़ने में कोई दिक्कत नहीं है joinलेकिन जब तक यह ट्रैकर पर नहीं मिलता, यह भूल जाएगा।
मैट डोले

1
मुझे लगता है कि आपने कुछ समय के लिए SO में लॉग इन नहीं किया है। इसलिए मैंने इसे FR # 2301
मैट डाउले

इस सुविधा के लिए @MattDowle, +1। (यह FR # 2301 के माध्यम से करने की कोशिश की, लेकिन मुझे एक अनुमति प्राप्त संदेश से इनकार कर दिया गया है)।
adilapapaya

@adilapapaya हम RForge से GitHub चले गए। यहाँ +1 करें: github.com/Rdatatable/data.table/issues/614 । अरुण ने मुद्दों को चित्रित किया ताकि वे खो न जाएं।
मैट डोले
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.