data.table बनाम dplyr: क्या कोई ऐसा काम कर सकता है जो दूसरे को खराब लगे या न करे?


758

अवलोकन

मैं अपेक्षाकृत परिचित हूं data.table, इतना नहीं dplyr। मैंने कुछ dplyrविगनेट्स और उदाहरणों के माध्यम से पढ़ा है जो SO पर पॉप अप हुए हैं, और अब तक मेरे निष्कर्ष यह हैं:

  1. data.tableऔर dplyrगति में तुलनीय हैं, सिवाय इसके कि जब कई (अर्थात> 10-100K) समूह होते हैं, और कुछ अन्य परिस्थितियों में (पासवर्ड को देखें)
  2. dplyr अधिक सुलभ वाक्यविन्यास है
  3. dplyr सार (या होगा) संभावित DB बातचीत
  4. कुछ मामूली कार्यक्षमता अंतर हैं (नीचे "उदाहरण / उपयोग देखें")

मेरे दिमाग में 2. ज्यादा वजन नहीं है क्योंकि मैं इससे काफी परिचित data.tableहूं, हालांकि मैं समझता हूं कि दोनों के लिए नए उपयोगकर्ताओं के लिए यह एक बड़ा कारक होगा। मैं एक ऐसे तर्क से बचना चाहूंगा, जिसके बारे में अधिक सहज ज्ञान युक्त हो, क्योंकि इससे परिचित किसी के दृष्टिकोण से पूछे गए मेरे विशिष्ट प्रश्न के लिए अप्रासंगिक है data.table। मैं इस बारे में चर्चा करने से बचना चाहता हूं कि "अधिक सहज" कैसे तेजी से विश्लेषण की ओर जाता है (निश्चित रूप से सच है, लेकिन फिर से, न कि मैं यहां सबसे अधिक दिलचस्पी रखता हूं)।

सवाल

जो मैं जानना चाहता हूं वह है:

  1. क्या ऐसे विश्लेषणात्मक कार्य हैं जो पैकेज से परिचित लोगों के लिए एक या दूसरे पैकेज के साथ कोड करना बहुत आसान है (यानी कीस्ट्रोक्स के कुछ संयोजन आवश्यक बनाम गूढ़ता के आवश्यक स्तर, जहां प्रत्येक में से एक अच्छी बात है)।
  2. क्या ऐसे विश्लेषणात्मक कार्य हैं जो एक पैकेज बनाम दूसरे में अधिक कुशलतापूर्वक (अर्थात 2x से अधिक) किए जाते हैं।

हाल ही में एक एसओ प्रश्न मुझे इस बारे में थोड़ा और सोचने को मिला, क्योंकि उस समय तक मुझे नहीं लगता था कि dplyrजो मैं पहले से ही कर सकता हूं उससे बहुत अधिक की पेशकश करेगा data.table। यहाँ dplyrसमाधान (क्यू के अंत में डेटा) है:

dat %.%
  group_by(name, job) %.%
  filter(job != "Boss" | year == min(year)) %.%
  mutate(cumu_job2 = cumsum(job2))

जो एक data.tableसमाधान में मेरे हैक प्रयास से बहुत बेहतर था । उस ने कहा, अच्छे data.tableसमाधान भी बहुत अच्छे हैं (धन्यवाद जीन-रॉबर्ट, अरुण, और यहां ध्यान दें कि मैंने कड़ाई से सबसे अधिक समाधान समाधान पर एकल कथन का समर्थन किया है:

setDT(dat)[,
  .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], 
  by=list(id, job)
]

उत्तरार्द्ध के लिए वाक्यविन्यास बहुत गूढ़ लग सकता है, लेकिन यह वास्तव में बहुत सरल है यदि आप उपयोग किए जाते हैं data.table(यानी कुछ अधिक गूढ़ चाल का उपयोग नहीं करते हैं)।

आदर्श रूप में मैं जो देखना चाहता हूं वह कुछ अच्छे उदाहरण हैं dplyrया data.tableजिस तरह से अधिक संक्षिप्त है या काफी बेहतर प्रदर्शन करता है।

उदाहरण

प्रयोग
  • dplyrसमूहित संचालन की अनुमति नहीं देता है जो मनमाने ढंग से पंक्तियों की वापसी करता है ( एड्डी के प्रश्न से , ध्यान दें: ऐसा लगता है कि इसे duspr 0.5 में लागू किया जाएगा , साथ ही, @beginneR do@ eddi के प्रश्न के उत्तर में उपयोग करते हुए एक संभावित कार्य-को दर्शाता है )।
  • data.tableरोलिंग जॉइन (थैंक्स @dholstius) के साथ-साथ ओवरलैप जॉइन का समर्थन करता है
  • data.tableआंतरिक रूप से DT[col == value]या स्वचालित अनुक्रमण के माध्यम से गति केDT[col %in% values] लिए अनुकूलन करता है जो एक ही आधार आर सिंटैक्स का उपयोग करते हुए द्विआधारी खोज का उपयोग करता है। कुछ और विवरण और एक छोटे बेंचमार्क के लिए यहां देखें
  • dplyrकार्यों के मानक मूल्यांकन संस्करण प्रदान करता है (उदाहरण के लिए regroup, summarize_each_) जो प्रोग्रामेटिक उपयोग को आसान बना सकता है dplyr(नोट प्रोग्रामेटिक उपयोग data.tableसंभव है, बस कुछ सावधानी से विचार, प्रतिस्थापन / उद्धरण, आदि की आवश्यकता है, कम से कम मेरे ज्ञान के लिए)
मानक

डेटा

यह पहला उदाहरण है जिसे मैंने प्रश्न अनुभाग में दिखाया है।

dat <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L), name = c("Jane", "Jane", "Jane", "Jane", 
"Jane", "Jane", "Jane", "Jane", "Bob", "Bob", "Bob", "Bob", "Bob", 
"Bob", "Bob", "Bob"), year = c(1980L, 1981L, 1982L, 1983L, 1984L, 
1985L, 1986L, 1987L, 1985L, 1986L, 1987L, 1988L, 1989L, 1990L, 
1991L, 1992L), job = c("Manager", "Manager", "Manager", "Manager", 
"Manager", "Manager", "Boss", "Boss", "Manager", "Manager", "Manager", 
"Boss", "Boss", "Boss", "Boss", "Boss"), job2 = c(1L, 1L, 1L, 
1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L)), .Names = c("id", 
"name", "year", "job", "job2"), class = "data.frame", row.names = c(NA, 
-16L))

9
समाधान जो dplyrएक को पढ़ने में समान है:as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]
eddi

7
# 1 के लिए दोनों dplyrऔर data.tableटीमें बेंचमार्क पर काम कर रही हैं, इसलिए कुछ बिंदु पर एक उत्तर होगा। # 2 (सिंटैक्स) imO कड़ाई से गलत है, लेकिन यह स्पष्ट रूप से राय क्षेत्र में उद्यम करता है, इसलिए मैं भी बंद करने के लिए मतदान कर रहा हूं।
ईडी

13
अच्छी तरह से, फिर से, समस्याओं का सेट है जो अधिक स्पष्ट रूप से व्यक्त किए गए (d)plyrहैं उपाय 0 में
eddi

28
@BrodieG एक बात यह है कि वास्तव में मुझे दोनों के बारे में कीड़े dplyrऔर plyrवाक्य रचना के संबंध में और मूल रूप से मुख्य कारण मैं उनके वाक्य विन्यास नापसंद है, मैं भी कई तरह से नाम के साथ अतिरिक्त कार्य ((1 से अधिक पढ़ने के लिए) जानने के लिए कि यह है कि अभी भी मेरे लिए कोई मतलब नहीं है), याद रखें कि वे क्या करते हैं, क्या तर्क देते हैं, आदि। यह हमेशा मेरे लिए प्लाई-दर्शन से एक बहुत बड़ा मोड़ रहा है।
Eddi

43
@ जेडी [जीभ-में-गाल] एक चीज जो वास्तव में मुझे डेटाटेबल सिंटैक्स के बारे में बताती है, वह यह है कि मुझे सीखना होगा कि किस तरह से कई फ़ंक्शन तर्क इंटरैक्ट करते हैं, और क्रिप्टिक शॉर्टकट्स का क्या मतलब है (जैसे .SD)। [गंभीरता से] मुझे लगता है कि ये वैध डिजाइन अंतर हैं जो विभिन्न लोगों के लिए अपील करेंगे
हैडली

जवाबों:


532

हम कवर कम से कम एक व्यापक जवाब / तुलना (महत्व के किसी विशेष क्रम में) प्रदान करने के लिए इन पहलुओं की जरूरत है: Speed, Memory usage, Syntaxऔर Features

मेरा इरादा इनमें से प्रत्येक को डेटाटेबल परिप्रेक्ष्य से यथासंभव स्पष्ट रूप से कवर करना है।

ध्यान दें: जब तक कि स्पष्ट रूप से उल्लेख नहीं किया गया है, तब तक, dplyr का उल्लेख करके, हम dplyr के data.frame इंटरफ़ेस का उल्लेख करते हैं, जिसका इंटर्नल Rcpp का उपयोग करके C ++ में हैं।


डेटाटेबल सिंटैक्स अपने रूप में सुसंगत है - DT[i, j, by]। रखने के लिए i, jऔर byएक साथ डिजाइन द्वारा है। संबंधित कार्यों को एक साथ रखकर, यह गति और अधिक महत्वपूर्ण रूप से स्मृति उपयोग के लिए आसानी से संचालन का अनुकूलन करने की अनुमति देता है , और कुछ शक्तिशाली विशेषताएं भी प्रदान करता है , जबकि सभी वाक्यविन्यास में स्थिरता बनाए रखते हैं।

1. गति

कुछ बेंचमार्क (हालांकि ज्यादातर समूहीकरण के संचालन पर) पहले से ही डेटा को दिखाने वाले प्रश्न में जोड़ दिए गए हैं। तालिका में तेजी से बढ़ने वाले समूहों की संख्या और / या पंक्तियों की संख्या तेजी से बढ़ जाती है, जिनमें मैट द्वारा 10 मिलियन से समूहन पर बेंचमार्क सहित बेंचमार्क शामिल हैं। 100 - 10 मिलियन समूहों और अलग-अलग ग्रुपिंग कॉलम पर 2 बिलियन रो (100GB RAM) , जिसकी तुलना भी की जाती है pandasअद्यतन किए गए मानदंड भी देखें , जिनमें शामिल हैं Sparkऔर pydatatableसाथ ही साथ।

बेंचमार्क पर, इन शेष पहलुओं को भी कवर करना बहुत अच्छा होगा:

  • पंक्तियों के सबसेट को समाहित करने वाला संचालन समूह - यानी, DT[x > val, sum(y), by = z]प्रकार के संचालन।

  • बेंचमार्क अन्य संचालन जैसे कि अपडेट और जॉइन

  • रनटाइम के अलावा प्रत्येक ऑपरेशन के लिए बेंचमार्क मेमोरी फुटप्रिंट

2. मेमोरी का उपयोग

  1. शामिल filter()या slice()dplyr में संचालन स्मृति अक्षम हो सकता है (दोनों data.frames और data.tables पर)। इस पोस्ट को देखें

    ध्यान दें कि हेडली की टिप्पणी गति के बारे में बात करती है (जो कि उसके लिए बहुत तेज़ है), जबकि यहाँ प्रमुख चिंता स्मृति है

  2. data.table इंटरफ़ेस इस समय किसी को संदर्भ द्वारा कॉलम को संशोधित / अपडेट करने की अनुमति देता है (ध्यान दें कि हमें परिणाम को एक चर पर फिर से असाइन करने की आवश्यकता नहीं है)।

    # sub-assign by reference, updates 'y' in-place
    DT[x >= 1L, y := NA]
    

    लेकिन dplyr संदर्भ द्वारा कभी अद्यतन नहीं होगा । Dplyr समतुल्य होगा (ध्यान दें कि परिणाम को फिर से असाइन करने की आवश्यकता है):

    # copies the entire 'y' column
    ans <- DF %>% mutate(y = replace(y, which(x >= 1L), NA))
    

    इसके लिए एक चिंताजनक संदर्भ पारदर्शिता है । संदर्भ द्वारा विशेष रूप से किसी डेटाटेबल ऑब्जेक्ट को अपडेट करना, विशेष रूप से किसी फ़ंक्शन के भीतर हमेशा वांछनीय नहीं हो सकता है। लेकिन यह एक अविश्वसनीय रूप से उपयोगी विशेषता है: दिलचस्प मामलों के लिए यह और यह पोस्ट देखें । और हम इसे रखना चाहते हैं।

    इसलिए हम shallow()data.table में फ़ंक्शन को निर्यात करने की दिशा में काम कर रहे हैं जो उपयोगकर्ता को दोनों संभावनाओं के साथ प्रदान करेगा । उदाहरण के लिए, यदि इनपुट डेटा को संशोधित नहीं करना वांछनीय है। किसी फ़ंक्शन के भीतर, तो कोई भी ऐसा कर सकता है:

    foo <- function(DT) {
        DT = shallow(DT)          ## shallow copy DT
        DT[, newcol := 1L]        ## does not affect the original DT 
        DT[x > 2L, newcol := 2L]  ## no need to copy (internally), as this column exists only in shallow copied DT
        DT[x > 2L, x := 3L]       ## have to copy (like base R / dplyr does always); otherwise original DT will 
                                  ## also get modified.
    }
    

    उपयोग न करने से shallow(), पुरानी कार्यक्षमता बरकरार रहती है:

    bar <- function(DT) {
        DT[, newcol := 1L]        ## old behaviour, original DT gets updated by reference
        DT[x > 2L, x := 3L]       ## old behaviour, update column x in original DT.
    }
    

    एक उथले कॉपी का उपयोग करके shallow(), हम समझते हैं कि आप मूल वस्तु को संशोधित नहीं करना चाहते हैं। हम यह सुनिश्चित करने के लिए आंतरिक रूप से सब कुछ का ख्याल रखते हैं कि कॉलम को कॉपी करना सुनिश्चित करते समय आप केवल तभी संशोधित करें जब यह बिल्कुल आवश्यक हो । जब लागू किया जाता है, तो यह उपयोगकर्ता को दोनों कमजोरियों के साथ प्रदान करते हुए पूरी तरह से संदर्भित पारदर्शिता मुद्दे को निपटाना चाहिए ।

    इसके अलावा, एक बार shallow()dplyr के data.table इंटरफ़ेस को निर्यात करने के बाद लगभग सभी प्रतियों से बचना चाहिए। तो जो लोग dplyr के सिंटैक्स को पसंद करते हैं, वे data.tables के साथ इसका उपयोग कर सकते हैं।

    लेकिन इसमें अभी भी कई विशेषताओं का अभाव होगा जो डेटाटेबल प्रदान करता है, जिसमें (उप)-संदर्भ द्वारा -ignignment भी शामिल है।

  3. ज्वाइन करते समय एग्रीगेट करें:

    मान लीजिए कि आपके पास दो data.tables निम्नानुसार हैं:

    DT1 = data.table(x=c(1,1,1,1,2,2,2,2), y=c("a", "a", "b", "b"), z=1:8, key=c("x", "y"))
    #    x y z
    # 1: 1 a 1
    # 2: 1 a 2
    # 3: 1 b 3
    # 4: 1 b 4
    # 5: 2 a 5
    # 6: 2 a 6
    # 7: 2 b 7
    # 8: 2 b 8
    DT2 = data.table(x=1:2, y=c("a", "b"), mul=4:3, key=c("x", "y"))
    #    x y mul
    # 1: 1 a   4
    # 2: 2 b   3
    

    और आप कॉलम में शामिल होने के दौरान sum(z) * mulप्रत्येक पंक्ति के लिए प्राप्त करना चाहेंगे । हम या तो कर सकते हैं:DT2x,y

    • 1) कुल DT1प्राप्त करने के लिए sum(z), 2) एक में शामिल होने के लिए प्रदर्शन और 3) गुणा (या)

      # data.table way
      DT1[, .(z = sum(z)), keyby = .(x,y)][DT2][, z := z*mul][]
      
      # dplyr equivalent
      DF1 %>% group_by(x, y) %>% summarise(z = sum(z)) %>% 
          right_join(DF2) %>% mutate(z = z * mul)
      
    • 2) यह सब एक बार में करें ( by = .EACHIसुविधा का उपयोग करके ):

      DT1[DT2, list(z=sum(z) * mul), by = .EACHI]

    फायदा क्या है?

    • हमें मध्यवर्ती परिणाम के लिए मेमोरी आवंटित करने की आवश्यकता नहीं है।

    • हमें दो बार समूह / हैश नहीं करना है (एकत्रीकरण के लिए एक और शामिल होने के लिए अन्य)।

    • और इससे भी महत्वपूर्ण बात, ऑपरेशन जो हम करना चाहते थे वह j(2) में देखकर स्पष्ट है ।

    चेक इस पोस्ट की एक विस्तृत विवरण के लिए by = .EACHI। कोई मध्यवर्ती परिणाम भौतिक नहीं हैं, और सभी में एक साथ मिलकर + जोड़ दिया जाता है।

    इस पर एक नज़र डालें , यह और यह वास्तविक उपयोग परिदृश्यों के लिए पोस्ट करता है।

    में dplyrआप करने के लिए होता में शामिल होने और कुल या सकल पहले और उसके बाद में शामिल होने , न तो जो की स्मृति के मामले में, कुशल के रूप में कर रहे हैं (जो बारी में गति करने के लिए अनुवाद)।

  4. अद्यतन और शामिल:

    नीचे दिखाए गए डेटाटेबल कोड पर विचार करें:

    DT1[DT2, col := i.mul]

    / अपडेट कहते हैं DT1के स्तंभ colके साथ mulसे DT2उन पंक्तियों पर जहां DT2रों कुंजी स्तंभ से मेल खाता है ' DT1। मुझे नहीं लगता कि इस ऑपरेशन का एक सटीक समकक्ष है dplyr, यानी, एक *_joinऑपरेशन से बचने के बिना , जिसमें इसे पूरा DT1करने के लिए एक नया कॉलम जोड़ना होगा, जो अनावश्यक है।

    वास्तविक उपयोग परिदृश्य के लिए इस पोस्ट को देखें ।

संक्षेप में, यह महसूस करना महत्वपूर्ण है कि अनुकूलन के हर बिट मायने रखती है। जैसा कि ग्रेस हॉपर कहेंगे, माइंड योर नैनोसकंड्स !

3. सिंटेक्स

आइए अब सिंटैक्स देखें । हेडली ने यहां टिप्पणी की :

डेटा टेबल बेहद तेज़ हैं, लेकिन मुझे लगता है कि उनका कॉन्सेप्ट सीखने में मुश्किल हो जाता है और कोड का उपयोग करना मुश्किल हो जाता है

मुझे यह टिप्पणी निरर्थक लगती है क्योंकि यह बहुत व्यक्तिपरक है। हम जो कोशिश कर सकते हैं वह वाक्य रचना में निरंतरता के विपरीत है । हम data.table और dplyr सिंटैक्स को एक-दूसरे से तुलना करेंगे।

हम नीचे दिखाए गए डमी डेटा के साथ काम करेंगे:

DT = data.table(x=1:10, y=11:20, z=rep(1:2, each=5))
DF = as.data.frame(DT)
  1. बुनियादी एकत्रीकरण / अद्यतन संचालन।

    # case (a)
    DT[, sum(y), by = z]                       ## data.table syntax
    DF %>% group_by(z) %>% summarise(sum(y)) ## dplyr syntax
    DT[, y := cumsum(y), by = z]
    ans <- DF %>% group_by(z) %>% mutate(y = cumsum(y))
    
    # case (b)
    DT[x > 2, sum(y), by = z]
    DF %>% filter(x>2) %>% group_by(z) %>% summarise(sum(y))
    DT[x > 2, y := cumsum(y), by = z]
    ans <- DF %>% group_by(z) %>% mutate(y = replace(y, which(x > 2), cumsum(y)))
    
    # case (c)
    DT[, if(any(x > 5L)) y[1L]-y[2L] else y[2L], by = z]
    DF %>% group_by(z) %>% summarise(if (any(x > 5L)) y[1L] - y[2L] else y[2L])
    DT[, if(any(x > 5L)) y[1L] - y[2L], by = z]
    DF %>% group_by(z) %>% filter(any(x > 5L)) %>% summarise(y[1L] - y[2L])
    
    • data.table सिंटैक्स कॉम्पैक्ट और dplyr की काफी क्रिया है। मामले में चीजें कमोबेश बराबर हैं (ए)।

    • मामले में (बी), हम संक्षेपfilter() में उपयोग करते समय था । लेकिन अपडेट करते समय , हमें तर्क को अंदर ले जाना पड़ा । हालांकि डेटाटेबल में, हम दोनों ऑपरेशंस को एक ही लॉजिक के साथ व्यक्त करते हैं - जहाँ , लेकिन पहली स्थिति में, पंक्तियों पर काम करते हैं , जबकि दूसरी स्थिति में उन पंक्तियों को उसके संचयी योग से अपडेट करते हैं ।mutate()x > 2sum(y)y

      जब हम कहते हैं कि इसका मतलब यह है कि DT[i, j, by]प्रपत्र सुसंगत है

    • इसी तरह मामले में (ग), जब हमारी if-elseस्थिति होती है, तो हम दोनों डेटाटैबल और डुप्लीयर में "as-is" तर्क व्यक्त करने में सक्षम होते हैं । हालाँकि, यदि हम उन पंक्तियों को वापस करना चाहते हैं जहाँ ifस्थिति संतुष्ट हो जाती है और अन्यथा छोड़ देते हैं, तो हम summarise()सीधे (AFAICT) का उपयोग नहीं कर सकते हैं । हमें filter()पहले और फिर सारांश करना होगा क्योंकि summarise()हमेशा एक ही मूल्य की उम्मीद है ।

      जबकि यह एक ही परिणाम देता है, filter()यहाँ का उपयोग वास्तविक संचालन को कम स्पष्ट करता है।

      filter()पहले मामले में भी इसका उपयोग करना बहुत अच्छी तरह से संभव हो सकता है (मुझे स्पष्ट नहीं लगता है), लेकिन मेरी बात यह है कि हमें ऐसा नहीं करना चाहिए।

  2. कई स्तंभों पर एकत्रीकरण / अद्यतन

    # case (a)
    DT[, lapply(.SD, sum), by = z]                     ## data.table syntax
    DF %>% group_by(z) %>% summarise_each(funs(sum)) ## dplyr syntax
    DT[, (cols) := lapply(.SD, sum), by = z]
    ans <- DF %>% group_by(z) %>% mutate_each(funs(sum))
    
    # case (b)
    DT[, c(lapply(.SD, sum), lapply(.SD, mean)), by = z]
    DF %>% group_by(z) %>% summarise_each(funs(sum, mean))
    
    # case (c)
    DT[, c(.N, lapply(.SD, sum)), by = z]     
    DF %>% group_by(z) %>% summarise_each(funs(n(), mean))
    
    • मामले में (ए), कोड अधिक या कम समकक्ष हैं। data.table परिचित आधार फ़ंक्शन का उपयोग करता है lapply(), जबकि कार्यों के एक समूह के साथ dplyrपरिचय *_each()करता है funs()

    • data.table :=को कॉलम नाम प्रदान करने की आवश्यकता होती है, जबकि dplyr यह स्वचालित रूप से उत्पन्न करता है।

    • मामले में (बी), dplyr का सिंटैक्स अपेक्षाकृत सीधा है। डेटा कार्यों की सूची में कई कार्यों पर एकत्रीकरण / अपडेट में सुधार करना है।

    • हालाँकि, (सी) हालाँकि, n()केवल एक बार के बजाए, कई बार कॉलम जितनी बार वापस आएगा । Data.table में, हमें केवल एक सूची वापस करनी है j। सूची का प्रत्येक तत्व परिणाम में एक कॉलम बन जाएगा। तो, हम, उपयोग कर सकते हैं एक बार फिर से, परिचित आधार समारोह c()को श्रेणीबद्ध करने के लिए .Nएक के लिए listहै जो एक रिटर्न list

    नोट: एक बार फिर, data.table में, हम सभी को एक सूची वापस करने की आवश्यकता है j। सूची का प्रत्येक तत्व परिणाम में एक कॉलम बन जाएगा। आप उपयोग कर सकते हैं c(), as.list(), lapply(), list()किसी भी नए कार्यों में जानने के लिए बिना आदि ... आधार कार्य पूरा करने के लिए,।

    आपको बस विशेष चर सीखने की आवश्यकता होगी - .Nऔर .SDकम से कम। Dplyr में बराबर हैं n()और.

  3. में शामिल

    dplyr प्रत्येक प्रकार के जुड़ने के लिए अलग-अलग फ़ंक्शन प्रदान करता है, जहाँ data.table समान सिंटैक्स DT[i, j, by](और कारण के साथ) का उपयोग करके जुड़ने की अनुमति देता है । यह merge.data.table()विकल्प के रूप में एक समान कार्य भी प्रदान करता है ।

    setkey(DT1, x, y)
    
    # 1. normal join
    DT1[DT2]            ## data.table syntax
    left_join(DT2, DT1) ## dplyr syntax
    
    # 2. select columns while join    
    DT1[DT2, .(z, i.mul)]
    left_join(select(DT2, x, y, mul), select(DT1, x, y, z))
    
    # 3. aggregate while join
    DT1[DT2, .(sum(z) * i.mul), by = .EACHI]
    DF1 %>% group_by(x, y) %>% summarise(z = sum(z)) %>% 
        inner_join(DF2) %>% mutate(z = z*mul) %>% select(-mul)
    
    # 4. update while join
    DT1[DT2, z := cumsum(z) * i.mul, by = .EACHI]
    ??
    
    # 5. rolling join
    DT1[DT2, roll = -Inf]
    ??
    
    # 6. other arguments to control output
    DT1[DT2, mult = "first"]
    ??
    
    • कुछ को प्रत्येक अच्छे (बाएं, दाएं, आंतरिक, विरोधी, अर्ध आदि) में शामिल होने के लिए एक अलग फ़ंक्शन मिल सकता है, जबकि अन्य डेटा पसंद कर सकते हैं DT[i, j, by]। या merge()जो आधार आर के समान है।

    • हालांकि dplyr जॉइन बस यही करते हैं। और कुछ नहीं। कुछ भी कम नहीं।

    • data.tables ज्वाइन करते समय (2) कॉलम का चयन कर सकते हैं, और dplyr में आपको select()ऊपर दिखाए गए से जुड़ने से पहले दोनों डेटा.फ्रेम पर पहले आना होगा। अन्यथा आप अनावश्यक स्तंभों के साथ जुड़ने के लिए उन्हें बाद में हटाने के लिए भौतिकवाद करेंगे और वह अक्षम है।

    • data.tables जुड़ते समय (3) को जोड़ सकते हैं और सुविधा का उपयोग करते हुए (4) जुड़ते समय भी अपडेट कर by = .EACHIसकते हैं। केवल कुछ कॉलम जोड़ने / अपडेट करने के लिए पूरे जॉइन के परिणाम को क्यों मटियामेट किया?

    • data.table करने में सक्षम है रोलिंग मिलती है (5) - रोल आगे, LOCF , रोल पिछड़े, NOCB , निकटतम

    • data.table में भी mult =तर्क है जो पहले , अंतिम या सभी मैचों (6) का चयन करता है ।

    • data.table के पास allow.cartesian = TRUEआकस्मिक अमान्य जुड़ावों से बचाने के लिए तर्क है।

एक बार फिर, वाक्यविन्यास DT[i, j, by]अतिरिक्त तर्कों के साथ संगत है जो आउटपुट को आगे नियंत्रित करने की अनुमति देता है।

  1. do()...

    dplyr का सारांश विशेष रूप से उन कार्यों के लिए डिज़ाइन किया गया है जो एकल मान लौटाते हैं। यदि आपका फ़ंक्शन कई / असमान मान देता है, तो आपको इसका सहारा लेना होगा do()। आपको अपने सभी फ़ंक्शंस रिटर्न वैल्यू के बारे में पहले से जानना होगा।

    DT[, list(x[1], y[1]), by = z]                 ## data.table syntax
    DF %>% group_by(z) %>% summarise(x[1], y[1]) ## dplyr syntax
    DT[, list(x[1:2], y[1]), by = z]
    DF %>% group_by(z) %>% do(data.frame(.$x[1:2], .$y[1]))
    
    DT[, quantile(x, 0.25), by = z]
    DF %>% group_by(z) %>% summarise(quantile(x, 0.25))
    DT[, quantile(x, c(0.25, 0.75)), by = z]
    DF %>% group_by(z) %>% do(data.frame(quantile(.$x, c(0.25, 0.75))))
    
    DT[, as.list(summary(x)), by = z]
    DF %>% group_by(z) %>% do(data.frame(as.list(summary(.$x))))
    
    • .SDके समकक्ष है .

    • Data.table में, आप बहुत कुछ भी फेंक सकते हैं j- याद रखने की एकमात्र चीज इसके लिए एक सूची वापस करना है ताकि सूची का प्रत्येक तत्व एक कॉलम में परिवर्तित हो जाए।

    • सपने में, ऐसा नहीं कर सकते। do()आपको यह सुनिश्चित करने के लिए सहारा लेना होगा कि आप इस बात पर निर्भर हैं कि क्या आपका फ़ंक्शन हमेशा एकल मान लौटाएगा। और यह काफी धीमा है।

एक बार फिर, डेटाटेबल का सिंटैक्स संगत है DT[i, j, by]। हम केवल jइन चीजों के बारे में चिंता किए बिना भावों को फेंकते रह सकते हैं।

इस एसओ प्रश्न और इस एक पर एक नजर है । मुझे आश्चर्य है कि अगर यह स्पष्ट है कि dplyr के वाक्यविन्यास का उपयोग करते हुए सीधा उत्तर देना संभव होगा ...

संक्षेप में, मैंने विशेष रूप से कई उदाहरणों पर प्रकाश डाला है, जहां डप्पर का सिंटैक्स या तो अक्षम है, सीमित है या संचालन को सीधा करने में विफल रहता है। यह विशेष रूप से इसलिए है क्योंकि डेटाटेबल को "कठिन से पढ़ने / सीखने" के सिंटैक्स के बारे में काफी उलट मिलता है (जैसे कि एक चिपकाया / ऊपर लिंक किया गया)। ज्यादातर पोस्ट जो dplyr को कवर करते हैं, वे सबसे सीधे संचालन के बारे में बात करते हैं। और वह महान है। लेकिन इसके सिंटैक्स और फीचर की सीमाओं को भी महसूस करना महत्वपूर्ण है, और मुझे इस पर एक पोस्ट देखना बाकी है।

data.table के पास इसके क्वैर भी हैं (जिनमें से कुछ मैंने बताया है कि हम ठीक करने का प्रयास कर रहे हैं)। हम भी डेटाटेबल में सुधार करने का प्रयास कर रहे हैं । मैंने यहां प्रकाश डाला है

लेकिन किसी को डेटा की संख्या पर भी विचार करना चाहिए, जिसमें डेटा की तुलना में कमी है।

4. सुविधाएँ

मैंने यहाँ और इस पोस्ट में भी अधिकांश विशेषताओं को इंगित किया है । के अतिरिक्त:

  • fread - फास्ट फाइल रीडर लंबे समय से उपलब्ध है।

  • fwrite - एक समानांतर तेज़ फ़ाइल लेखक अब उपलब्ध है। आगे के घटनाक्रम पर नज़र रखने के लिए कार्यान्वयन और # 1664 पर विस्तृत विवरण के लिए इस पोस्ट को देखें ।

  • स्वचालित अनुक्रमण - जैसा कि आंतरिक रूप से बेस आर सिंटैक्स का अनुकूलन करने के लिए एक और उपयोगी सुविधा है।

  • तदर्थ समूहन : dplyrस्वचालित रूप से चर चर के दौरान परिणामों को क्रमबद्ध करता है summarise(), जो हमेशा वांछनीय नहीं हो सकता है।

  • उपरोक्त उल्लिखित गति (स्मृति दक्षता और वाक्यविन्यास) के लिए डेटाटेबल जॉइन में कई फायदे।

  • गैर-इक्वि<=, <, >, >= जॉइन : अन्य ऑपरेटरों को डेटा के सभी अन्य लाभों के साथ जुड़ने की अनुमति देता है ।

  • ओवरलैपिंग रेंज जॉइन को हाल ही में data.table में लागू किया गया था। बेंचमार्क के साथ अवलोकन के लिए इस पोस्ट को देखें ।

  • setorder() data.table में कार्य करता है जो वास्तव में संदर्भ द्वारा data.tables के तेजी से पुन: व्यवस्थित करने की अनुमति देता है।

  • dplyr एक ही सिंटैक्स का उपयोग करके डेटाबेस को इंटरफ़ेस प्रदान करता है , जो कि डेटाटेबल फिलहाल नहीं है।

  • data.tableकी तेजी के समकक्ष प्रदान करता है सेट संचालन - (जनवरी Gorecki द्वारा लिखित) fsetdiff, fintersect, funionऔर fsetequalअतिरिक्त के साथ allतर्क (एसक्यूएल के रूप में)।

  • data.table बिना किसी मास्किंग चेतावनियों के साथ सफाई से लोड होता है और किसी भी आर पैकेज में पास होने पर अनुकूलता के लिए यहां एक तंत्र वर्णित है[.data.frame । dplyr आधार कार्यों को बदल देता है filter, lagऔर [जो समस्याओं का कारण बन सकता है; जैसे यहां और यहां


आखिरकार:

  • डेटाबेस पर - कोई कारण नहीं है कि data.table समान इंटरफ़ेस प्रदान नहीं कर सकता है, लेकिन यह अब प्राथमिकता नहीं है। यदि उपयोगकर्ता उस सुविधा को बहुत पसंद करेंगे तो यह टकरा सकता है।

  • समानता पर - सब कुछ मुश्किल है, जब तक कि कोई आगे बढ़कर ऐसा नहीं करता। निश्चित ही यह प्रयास करेगा (थ्रेड सेफ होना)।

    • वर्तमान में (v1.9.7 में) प्रगति की जा रही है वृद्धिशील प्रदर्शन लाभ का उपयोग करने के लिए ज्ञात समय लेने वाले भागों को समानांतर करने की दिशा में OpenMP

9
@bluefeet: मुझे नहीं लगता कि आपने उस चर्चा को चैट में स्थानांतरित करके हम में से किसी भी महान सेवा को किया था। मैं इस धारणा के तहत था कि अरुण डेवलपर्स में से एक है और इसके परिणामस्वरूप उपयोगी अंतर्दृष्टि हो सकती है।
IRTFM

2
जब मैं आपके लिंक का उपयोग करके चैट करने के लिए गया, तो यह दिखाई दिया कि टिप्पणी "आप एक फिल्टर का उपयोग करना चाहिए" शुरू करने के बाद सामग्री के सभी चला गया था। क्या मुझे SO-चैट तंत्र के बारे में कुछ याद आ रहा है?
IRTFM

6
मुझे लगता है कि हर जगह है जहाँ आप संदर्भ (से काम का उपयोग कर रहे :=), dplyrबराबर भी हो का उपयोग कर करना चाहिए <-के रूप में DF <- DF %>% mutate...बस के बजायDF %>% mutate...
डेविड Arenburg

4
वाक्य-विन्यास के बारे में। मेरा मानना ​​है कि dplyrउन उपयोगकर्ताओं के लिए आसान हो सकता है जो plyrसिंटैक्स का उपयोग करते थे , लेकिन data.tableउन उपयोगकर्ताओं के लिए आसान हो सकता है जो भाषा सिंटैक्स की तरह क्वेरी करते थे SQL, और इसके पीछे संबंधपरक बीजगणित, जो सारणीबद्ध डेटा परिवर्तन के बारे में है। @ यदि आपको ध्यान देना चाहिए कि सेट ऑपरेटर्सdata.table फ़ंक्शन को रैप करके बहुत आसान करते हैं और निश्चित रूप से महत्वपूर्ण स्पीडअप लाता है।
जंगोरकी

9
मैंने इस पोस्ट को कई बार पढ़ा है, और इससे मुझे डेटा समझने में बहुत मदद मिली। मैं, ज्यादातर मामलों के लिए, dplyr या पांडा या PL / pgSQL पर data.table को प्राथमिकता देता हूं। हालाँकि, मैं यह नहीं सोच सकता कि इसे कैसे व्यक्त किया जाए। वाक्य रचना है नहीं आसान, स्पष्ट या वर्बोज़। वास्तव में, जब मैंने data.table का बहुत उपयोग किया है, तब भी मैं अक्सर अपने कोड को समझने के लिए संघर्ष करता हूं, मैंने एक सप्ताह पहले शाब्दिक रूप से लिखा है। यह केवल लिखने वाली भाषा का एक जीवन उदाहरण है। en.wikipedia.org/wiki/Write-only_language तो, चलिए आशा करते हैं, एक दिन हम data.table पर dplyr का उपयोग कर पाएंगे।
उफोस

385

अरुण के उत्तर की व्यापक रूपरेखा (लेकिन कुछ अलग-अलग प्राथमिकताओं के आधार पर पुन: व्यवस्थित) के बाद, यहां मेरे सपने को व्यापक परिप्रेक्ष्य में देखा जा सकता है।

वाक्य - विन्यास

वाक्यविन्यास के लिए कुछ विषयवस्तु है, लेकिन मैं अपने कथन के साथ खड़ा हूं कि data.table का दृष्टिकोण सीखना मुश्किल है और पढ़ने के लिए कठिन है। यह आंशिक रूप से है क्योंकि dplyr एक बहुत आसान समस्या को हल कर रहा है!

वास्तव में एक महत्वपूर्ण बात जो आपके लिए काम करती है वह यह है कि यह आपके विकल्पों को बाधित करती है । मेरा दावा है कि "एकल समूह" क्रियाविशेषण के साथ अधिकांश सिंगल टेबल समस्याओं को सिर्फ पांच प्रमुख क्रियाओं फिल्टर, सेलेक्ट, म्यूटेट, अरेंज और संक्षेप में हल किया जा सकता है। जब आप डेटा हेरफेर सीख रहे हैं तो यह बाधा एक बड़ी मदद है, क्योंकि यह समस्या के बारे में आपकी सोच को आदेश देने में मदद करता है। Dplyr में, इन क्रियाओं में से प्रत्येक को एकल फ़ंक्शन पर मैप किया जाता है। प्रत्येक फ़ंक्शन एक काम करता है, और अलगाव में समझना आसान है।

आप इन सरल कार्यों को एक साथ जोड़कर जटिलता पैदा करते हैं %>%। यहां अरुण से जुड़े पदों में से एक से एक उदाहरण है :

diamonds %>%
  filter(cut != "Fair") %>%
  group_by(cut) %>%
  summarize(
    AvgPrice = mean(price),
    MedianPrice = as.numeric(median(price)),
    Count = n()
  ) %>%
  arrange(desc(Count))

यहां तक ​​कि अगर आपने पहले कभी नहीं देखा है (या यहां तक ​​कि आर!), तो आप अभी भी क्या हो रहा है इसका सार प्राप्त कर सकते हैं क्योंकि फ़ंक्शन सभी अंग्रेजी क्रियाएं हैं। अंग्रेजी क्रियाओं का नुकसान यह है कि उन्हें आवश्यकता से अधिक टाइपिंग की आवश्यकता होती है [, लेकिन मुझे लगता है कि बड़े पैमाने पर बेहतर स्वत: पूर्णता से इसे कम किया जा सकता है।

यहां बराबर डेटा.table कोड है:

diamondsDT <- data.table(diamonds)
diamondsDT[
  cut != "Fair", 
  .(AvgPrice = mean(price),
    MedianPrice = as.numeric(median(price)),
    Count = .N
  ), 
  by = cut
][ 
  order(-Count) 
]

जब तक आप पहले से ही डेटा से परिचित नहीं हो जाते तब तक इस कोड का पालन करना कठिन है। (मैं यह भी पता नहीं लगा सका कि बार-बार किस [ तरह से मेरी आंख को अच्छा लगता है)। व्यक्तिगत रूप से, जब मैं 6 महीने पहले लिखे गए कोड को देखता हूं, तो यह एक अजनबी द्वारा लिखे गए कोड को देखने जैसा होता है, इसलिए मैं सीधा, यदि क्रिया, कोड पसंद करना चाहता हूं।

दो अन्य मामूली कारक जिन्हें मैं समझता हूं कि पठनीयता में थोड़ी कमी आई है:

  • चूंकि लगभग हर डेटा टेबल ऑपरेशन [आपको अतिरिक्त संदर्भ की आवश्यकता है ताकि यह पता लगाया जा सके कि क्या हो रहा है। उदाहरण के लिए, x[y] दो डेटा टेबल से जुड़ रहा है या डेटा फ्रेम से कॉलम निकाल रहा है? यह केवल एक छोटा सा मुद्दा है, क्योंकि अच्छी तरह से लिखे गए कोड में चर नामों को सुझाव देना चाहिए कि क्या हो रहा है।

  • मुझे यह पसंद है कि group_by()एक अलग ऑपरेशन है। यह मूल रूप से गणना को बदल देता है इसलिए मुझे लगता है कि कोड को स्किम करते समय स्पष्ट होना चाहिए, और यह तर्क की group_by()तुलना में स्पॉट करना आसान byहै [.data.table

मुझे यह भी पसंद है कि पाइप सिर्फ एक पैकेज तक सीमित नहीं है। आप अपने डेटा को tidyr के साथ शुरू करके , और ggvis में एक प्लॉट के साथ समाप्त कर सकते हैं । और आप उन पैकेजों तक सीमित नहीं हैं जो मैं लिखता हूं - कोई भी एक फ़ंक्शन लिख सकता है जो डेटा हेरफेर पाइप का एक सहज हिस्सा बनाता है। वास्तव में, मैं नहीं बल्कि पिछले data.table कोड के साथ फिर से लिखा पसंद करते हैं %>%:

diamonds %>% 
  data.table() %>% 
  .[cut != "Fair", 
    .(AvgPrice = mean(price),
      MedianPrice = as.numeric(median(price)),
      Count = .N
    ), 
    by = cut
  ] %>% 
  .[order(-Count)]

और इसके साथ पाइप करने का विचार %>%केवल डेटा फ़्रेम तक सीमित नहीं है और आसानी से अन्य संदर्भों के लिए सामान्यीकृत है: इंटरैक्टिव वेब ग्राफिक्स , वेब स्क्रैपिंग , जिस्ट , रन-टाइम अनुबंध , ...)

स्मृति और प्रदर्शन

मैंने इन्हें एक साथ लम्प किया है, क्योंकि, मेरे लिए, वे महत्वपूर्ण नहीं हैं। अधिकांश आर उपयोगकर्ता डेटा की 1 मिलियन पंक्तियों के साथ अच्छी तरह से काम करते हैं, और डेटा के उस आकार के लिए पर्याप्त रूप से पर्याप्त रूप से तेज़ है जो आपको प्रसंस्करण समय के बारे में पता नहीं है। हम मध्यम डेटा पर स्पष्टता के लिए dplyr का अनुकूलन करते हैं; बड़ा डेटा पर कच्ची गति के लिए data.table का उपयोग करने के लिए स्वतंत्र महसूस करें।

Dplyr के लचीलेपन का मतलब यह भी है कि आप समान सिंटैक्स का उपयोग करके आसानी से प्रदर्शन विशेषताओं को बदल सकते हैं। यदि डेटा फ़्रेम बैकएंड के साथ dplyr का प्रदर्शन आपके लिए पर्याप्त नहीं है, तो आप डेटाटेबल बैकेंड का उपयोग कर सकते हैं (यद्यपि कुछ हद तक सीमित कार्यक्षमता के साथ)। यदि आप जिस डेटा के साथ काम कर रहे हैं, वह मेमोरी में फिट नहीं होता है, तो आप डेटाबेस बैकएंड का उपयोग कर सकते हैं।

सभी ने कहा, दीर्घावधि में प्रदर्शन बेहतर होगा। हम निश्चित रूप से डेटा के कुछ महान विचारों को लागू करेंगे। जैसे कि मूलांक क्रम और जोड़ और फ़िल्टर के लिए एक ही सूचकांक का उपयोग करना। हम समानांतरकरण पर भी काम कर रहे हैं ताकि हम कई कोर का लाभ उठा सकें।

विशेषताएं

कुछ चीजें जो हम 2015 में काम करने की योजना बना रहे हैं:

  • readrपैकेज, यह आसान डिस्क बंद और स्मृति करने के लिए फ़ाइलें, के अनुरूप प्राप्त करने के लिए बनाने के लिए fread()

  • नॉन-इक्वि-जॉन्स के लिए समर्थन सहित अधिक लचीले जोड़ शामिल हैं।

  • अधिक लचीले समूह जैसे बूटस्ट्रैप नमूने, रोलअप और अधिक

मैं आर के डेटाबेस कनेक्टर्स को सुधारने , वेब एपिस से बात करने की क्षमता और html पृष्ठों को परिमार्जन करना आसान बनाता हूं ।


27
बस एक पक्ष ध्यान दें, मैं आपकी कई दलीलों से सहमत हूँ (हालाँकि मैं data.tableस्वयं वाक्य रचना पसंद करता हूँ), लेकिन यदि आप शैली पसंद नहीं करते हैं तो आप %>%पाइप data.tableसंचालन के लिए आसानी से उपयोग कर सकते हैं [%>%के लिए विशिष्ट नहीं है dplyr, बल्कि एक अलग पैकेज से आता है (जो आप भी सह-लेखक होने के लिए होता है), इसलिए मुझे यकीन नहीं है कि मैं समझता हूं कि आप अपने अधिकांश सिंटैक्स पैराग्राफ में क्या कहना चाह रहे हैं ।
डेविड अरेनबर्ग

11
@DavidArenburg अच्छी बात है। मैंने फिर से लिखा वाक्य रचना करने के लिए उम्मीद है कि अधिक स्पष्ट क्या मेरी मुख्य बिंदु हैं, और विशेषता यह है कि आप उपयोग कर सकते हैं करने के लिए कर %>%data.table साथ
हैडली

5
धन्यवाद हैडली, यह एक उपयोगी परिप्रेक्ष्य है। री इंडेंटिंग मैं आम तौर पर करता हूं DT[\n\texpression\n][\texpression\n]( जिस्ट ) जो वास्तव में बहुत अच्छी तरह से काम करता है। मैं अरुण के उत्तर को उत्तर के रूप में रख रहा हूं क्योंकि वह सीधे मेरे विशिष्ट प्रश्नों का उत्तर देता है जो वाक्य रचना की पहुंच के बारे में बहुत अधिक नहीं हैं, लेकिन मुझे लगता है कि यह उन लोगों के लिए एक अच्छा जवाब है जो मतभेदों / सामान्यताओं के बीच एक सामान्य अनुभव प्राप्त करने की कोशिश कर रहे हैं dplyrऔर data.table
ब्रॉडी जी B

33
जब पहले से ही उपवास पर काम कर रहा है fread()? क्या फ़्रेड () को बेहतर बनाने या अन्य (अविकसित) चीज़ों पर काम करने में बेहतर समय नहीं बिताया जाएगा?
ईडी

10
के एपीआई data.tableको []संकेतन के बड़े पैमाने पर दुरुपयोग पर स्थापित किया गया है। यही इसकी सबसे बड़ी ताकत है और इसकी सबसे बड़ी कमजोरी।
पॉल

65

प्रश्न शीर्षक के सीधे जवाब में ...

dplyr निश्चित रूप से ऐसी चीजें करता है जो data.tableनहीं कर सकते हैं।

आपकी बात # ३

dplyr अमूर्त (या होगा) संभावित DB इंटरैक्शन

अपने खुद के सवाल का सीधा जवाब है, लेकिन एक उच्च पर्याप्त स्तर तक ऊंचा नहीं है। dplyrवास्तव में कई डेटा भंडारण तंत्र के data.tableलिए एक विस्तार योग्य फ्रंट-एंड है जहां एक एकल के लिए एक एक्सटेंशन है।

dplyrएक ही ग्रामर का उपयोग करने वाले सभी लक्ष्यों के साथ, एक बैक-एंड एग्नोस्टिक इंटरफ़ेस के रूप में देखें , जहां आप लक्ष्य और हैंडलर को अपनी इच्छा से बढ़ा सकते हैं। data.tableसे, है dplyrपरिप्रेक्ष्य, उन लक्ष्यों में से एक।

आप ऐसा कभी नहीं करेंगे (मुझे आशा है कि) एक दिन है जो data.tableआपके प्रश्नों का अनुवाद करने का प्रयास करता है ताकि SQL स्टेटमेंट बना सकें, जो ऑन-डिस्क या नेटवर्क डेटा स्टोर के साथ काम करते हैं।

dplyrसंभवतः चीजें कर सकते data.tableहैं या नहीं भी कर सकते हैं।

स्मृति में काम करने के डिजाइन के आधार पर, data.tableप्रश्नों के समानांतर प्रसंस्करण में खुद को विस्तारित करने में बहुत अधिक कठिन समय हो सकता है dplyr


शरीर के सवालों के जवाब में ...

प्रयोग

क्या ऐसे विश्लेषणात्मक कार्य हैं जो पैकेज से परिचित लोगों के लिए एक या दूसरे पैकेज के साथ कोड करना बहुत आसान है (यानी कीस्ट्रोक्स के कुछ संयोजन आवश्यक बनाम गूढ़ता के आवश्यक स्तर, जहां प्रत्येक में से एक अच्छी बात है)।

यह एक पंट की तरह लग सकता है लेकिन असली जवाब नहीं है। साधनों से परिचित लोग या तो उन सबसे परिचित या एक का उपयोग करने लगते हैं जो वास्तव में काम के लिए सही है। कहा जा रहा है कि, कभी-कभी आप किसी विशेष पठनीयता को प्रस्तुत करना चाहते हैं, कभी-कभी प्रदर्शन का स्तर, और जब आपको दोनों के उच्च पर्याप्त स्तर की आवश्यकता होती है, तो आपको केवल एक और उपकरण की आवश्यकता हो सकती है, जिसके साथ आपको पहले से ही स्पष्ट अमूर्त बनाना होगा। ।

प्रदर्शन

क्या ऐसे विश्लेषणात्मक कार्य हैं जो एक पैकेज बनाम दूसरे में अधिक कुशलतापूर्वक (अर्थात 2x से अधिक) किए जाते हैं।

फिर से, नहीं। data.tableहर चीज में कुशल होने के लिए एक्सेल, जहां यहdplyr अंतर्निहित डेटा स्टोर और पंजीकृत हैंडलर के लिए कुछ मामलों में सीमित होने का बोझ हो जाता है।

के साथ इस का मतलब है जब आप एक प्रदर्शन मुद्दे में चलाने data.tableआप यकीन है कि यह आपकी क्वेरी समारोह में है और अगर यह हो सकता है है वास्तव में के साथ एक टोंटी data.tableतो आप अपने आप को एक रिपोर्ट दायर की खुशी जीत लिया है। बैक-एंड के रूप में dplyrउपयोग करते समय यह भी सच है data.table; आप कुछ ओवरहेड देख सकते हैं , लेकिन यह आपकी क्वेरी है।dplyr

जब dplyrबैक-एंड्स के साथ प्रदर्शन समस्याएँ होती हैं, तो आप हाइब्रिड मूल्यांकन के लिए एक फ़ंक्शन दर्ज करके या (डेटाबेस के मामले में) निष्पादन से पहले उत्पन्न क्वेरी में हेरफेर करके उनके आसपास प्राप्त कर सकते हैं।

इसके अलावा स्वीकृत उत्तर देखें कि plyr data.table से बेहतर कब है?


3
Cant dplyr tbl_dt के साथ data.table को लपेट सकता है? क्यों नहीं दोनों दुनिया का सबसे अच्छा मिलता है?
आना 90210

22
आप उल्टे कथन का उल्लेख करना भूल जाते हैं "data.table निश्चित रूप से उन चीजों को करता है जो dplyr नहीं कर सकते हैं" जो भी सच है।
जांगोरेकी

25
अरुण जवाब इसे अच्छे से समझाते हैं। सबसे महत्वपूर्ण (प्रदर्शन के संदर्भ में) भय, संदर्भ द्वारा अद्यतन, रोलिंग रोलिंग, ओवरलैपिंग जॉइन। मेरा मानना ​​है कि कोई भी पैकेज नहीं है (न केवल dplyr) जो उन सुविधाओं के साथ प्रतिस्पर्धा कर सकते हैं। एक अच्छा उदाहरण इस प्रस्तुति से अंतिम स्लाइड हो सकता है ।
जंगोरकी

15
पूरी तरह से, data.table यही कारण है कि मैं अभी भी आर का उपयोग करता हूं। अन्यथा मैं पांडा का उपयोग करता हूं। यह पांडा से बेहतर / तेज है।
मारबेल

8
मुझे इसकी सादगी और SQL सिंटैक्स संरचना से समानता के कारण डेटाटेबल पसंद है। मेरी नौकरी में सांख्यिकीय मॉडलिंग के लिए हर रोज़ बहुत गहन तदर्थ डेटा विश्लेषण और ग्राफिक्स करना शामिल है, और मुझे जटिल चीजों को करने के लिए वास्तव में सरल उपकरण की आवश्यकता है। अब मैं अपने टूलकिट को केवल डेटा के लिए कम कर सकता हूं। अपनी रोजमर्रा की नौकरी में ग्राफ के लिए डेटा और जाली के लिए। एक उदाहरण दें, मैं इस तरह के ऑपरेशन भी कर सकता हूं: $ DT [group == 1, y_hat: = भविष्यवाणी (फिट, डेटा = .SD),] $, जो वास्तव में साफ-सुथरा है और मैं इसे SQL से एक महान लाभ के रूप में मानता हूं। क्लासिक आर पर्यावरण।
xappppp
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.