2015-12-24 10 views
8

के लिए 21 दिन रोलिंग योग करने का सबसे तेज़ तरीका मेरे पास एक बड़ा डेटाफ्रेम (3 एम + पंक्तियां) है। मैं 21 दिनों की खिड़की में एक निश्चित गतिविधि टाइप दिखाई देने की संख्या को गिनने की कोशिश कर रहा हूं। मैंने Rolling Sum by Another Variable in R से अपना समाधान तैयार किया है। लेकिन सिर्फ एक गतिविधि टाइप के लिए काफी समय लगता है। मुझे नहीं लगता था कि 3 एम + पंक्तियां ऐसी चीज हैं जो अनजान समय लेती हैं। नीचे है कि मैं क्या करने की कोशिश की:एक गतिविधि प्रकार

dt <- read.table(text=' 

         Name  ActivityType  ActivityDate     
         John  Email   1/1/2014   
         John  Email   1/3/2014     
         John  Webinar   1/5/2014   
         John  Webinar   1/20/2014   
         John  Webinar   3/25/2014   
         John  Email   4/1/2014   
         John  Email   4/20/2014   
         Tom  Email   1/1/2014   
         Tom  Webinar   1/5/2014   
         Tom  Webinar   1/20/2014   
         Tom  Webinar   3/25/2014   
         Tom  Email    4/1/2014   
         Tom  Email    4/20/2014   

         ', header=T, row.names = NULL) 

     library(data.table) 
     library(reshape2) 
     dt$ActivityType <- factor(dt$ActivityType) 
     dt$ActivityDate <- as.Date(dt$ActivityDate, "%m/%d/%Y") 
     dt <- dt[order(dt$Name, dt$ActivityDate),] 

    dt <- dcast(dt, Name + ActivityDate ~ ActivityType, fun.aggregate=length) 
    setDT(dt) 
    #Build reference table 
     Ref <- dt[,list(Compare_Value=list(I(Email)),Compare_Date=list(I(ActivityDate))), by=c("Name")] 
    #Use mapply to get last 21 days of value by Name  
    dt[,Email_RollingSum := mapply(ActivityDate=ActivityDate,Name=Name, function(ActivityDate, Name) { 
      d <- as.numeric(Ref$Compare_Date[[Name]] - ActivityDate) 
      sum((d <= 0 & d >= -21)*Ref$Compare_Value[[Name]])})] 

और यह सिर्फ ActivityType = ईमेल है, तो मैं अन्य ActivityType के स्तर के लिए भी ऐसा ही करने की है। जिस लिंक को मैंने समाधान दिया है, उससे "मैकप्ली" के बजाय "मैकप्ली" का उपयोग करने के बारे में बात की गई। कृपया मुझे बताएं कि मैं मैकप्ली या किसी अन्य समाधान का उपयोग कैसे कर सकता हूं जो इसे तेज कर देगा।

नीचे अपेक्षित आउटपुट है। प्रत्येक पंक्ति के लिए, मैं गतिविधि दिनांक लेता हूं और उससे 21 दिन पहले और 21 दिन की अवधि मेरी टाइम विंडो है। मैं उस समय विंडो में गतिविधि समय टाइप = "ईमेल" प्रकट करता हूं।

   Name  ActivityType  ActivityDate Email_RollingSum    
       John  Email   1/1/2014   1 
       John  Email   1/3/2014   2  
       John  Webinar   1/5/2014   2 
       John  Webinar   1/20/2014  2 
       John  Webinar   3/25/2014  0 
       John  Email   4/1/2014   1 
       John  Email   4/20/2014  2 
       Tom  Email   1/1/2014   1 
       Tom  Webinar   1/5/2014   1 
       Tom  Webinar   1/20/2014  1 
       Tom  Webinar   3/25/2014  0 
       Tom  Email    4/1/2014   1 
       Tom  Email    4/20/2014  2 
+0

मैं अक्सर संख्यात्मक करने के लिए अपने दिनांकों परिवर्तित जब पंक्तियों के लाखों लोगों के साथ काम कर। as.numeric ($ ActivityDate डीटी)। समाधान नहीं बल्कि शायद एक सुधार। – Jordan

+1

चूंकि ओपी स्पष्ट रूप से गति के बारे में है, इसलिए इसे विभिन्न तरीकों से प्राप्त समय के साथ अपडेट करना अच्छा होगा। – eddi

+0

वॉल्ट्स के दृष्टिकोण ने 1.89 घंटे लिया। कुछ कारणों से, मैं एडडी के दृष्टिकोण की कोशिश करते समय दो बार स्मृति से बाहर भाग गया। जब एक्सेल ने मेरे कंप्यूटर को दुर्घटनाग्रस्त कर दिया तो खसना का दृष्टिकोण चल रहा था (2 घंटे से थोड़ा अधिक)। डेटाटेबल कॉलम के खिलाफ – gibbz00

उत्तर

4

एक दृष्टिकोण है, जिसमें डेटा तालिका दोनों के नाम और तिथियों की सूची के लिए और ईमेल की संख्या के स्रोत के लिए प्रयोग किया जाता है की कोशिश करो। यह DTDT के by = .EACHI के साथ का उपयोग कर किया गया है। कोड दिखाई दे सकता है जैसे:

library(data.table) 
# convert character dates to Date types 
dt$ActivityDate <- as.Date(dt$ActivityDate, "%m/%d/%Y") 
# convert to a 'data.table' and define key 
setDT(dt, key = "Name") 
# count emails and webinars 
dt <- dt[dt[,.(Name, type = ActivityType, date = ActivityDate)], 
     .(type, date, 
      Email = sum(ActivityType == "Email" & between(ActivityDate, date-21, date)), 
      Webinar = sum(ActivityType == "Webinar" & between(ActivityDate, date-21, date))), 
     by=.EACHI] 

निम्नलिखित ऊपर के रूप में ही दृष्टिकोण का उपयोग करता है, लेकिन कुछ परिवर्तन जो आपके डेटा के आधार पर 30-40% द्वारा गति में सुधार कर सकते हैं शामिल हैं।

setDT(dt, key = "Name") 
    dt[, ":="(ActivityDate = as.Date(dt$ActivityDate, "%m/%d/%Y"), 
      ActivityType = as.character(ActivityType))] 
    dt4 <- dt[.(Name=Name, type=ActivityType, date=ActivityDate), {z=between(ActivityDate, date-21, date); 
                    .(type, date, 
                    Email=sum((ActivityType %chin% "Email") & z), 
                    Webinar=sum((ActivityType %chin% "Webinar") & z)) } 
      , by=.EACHI] 
+1

'<-' एक खराब अभ्यास – jangorecki

+0

@jangorecki <-? के बजाय क्या किया जाना चाहिए – gibbz00

+1

@ gibbz00 ': =' ऑपरेटर, पढ़ें [संदर्भ अर्थशास्त्र विग्नेट] (https://rawgit.com/wiki/Rdatatable/data.table/vignettes/datatable-reference-semantics.html)। – jangorecki

6
setDT(dt) 
dt[, ActivityDate := as.Date(ActivityDate, '%m/%d/%Y')] 

# add index to keep track of rows 
dt[, idx := .I] 

# match the dates we're looking for using a rolling join and extract the row numbers 
rr = dt[.(Name = Name, ActivityDate = ActivityDate - 21, refIdx = idx), 
     .(idx, refIdx), on = c('Name', 'ActivityDate'), roll = -Inf] 
# idx refIdx 
# 1: 1  1 
# 2: 1  2 
# 3: 1  3 
# 4: 1  4 
# 5: 5  5 
# 6: 5  6 
# 7: 6  7 
# 8: 8  8 
# 9: 8  9 
#10: 8  10 
#11: 11  11 
#12: 11  12 
#13: 12  13 

# extract the above rows and count occurrences using dcast 
dcast(rr[, {seq = idx:refIdx; dt[seq]}, by = 1:nrow(rr)], nrow ~ ActivityType) 
# nrow Email Webinar 
#1  1  1  0 
#2  2  2  0 
#3  3  2  1 
#4  4  2  2 
#5  5  0  1 
#6  6  1  1 
#7  7  2  0 
#8  8  1  0 
#9  9  1  1 
#10 10  1  2 
#11 11  0  1 
#12 12  1  1 
#13 13  2  0 
+0

आपके उत्तर के लिए बहुत बहुत धन्यवाद! – gibbz00

संबंधित मुद्दे