2017-09-27 14 views
5

के साथ सप्ताहांत की गणना में कुशल सप्ताह बनाएं मेरे कामकाजी डेटासेट में, मैं थोक और राजस्व में बदलाव के लिए सप्ताह-दर-सप्ताह मूल्यों की गणना करने की कोशिश कर रहा हूं। कोड काम करता प्रतीत होता है, लेकिन मेरे अनुमानों से पता चलता है कि यह एक साधारण सरल गणना चलाने के लिए लगभग 75 घंटे लग जाएगा। नीचे सामान्य प्रतिलिपि प्रस्तुत करने योग्य संस्करण है जो इस छोटे डाटासेट पर चलने के लिए के बारे में 2 एम लेता है:सबसेटिंग

######################################################################################################################## 
# MAKE A GENERIC REPORDUCIBLE STACK OVERFLOW QUESTION 
######################################################################################################################## 

# Create empty data frame of 26,000 observations similar to my data, but populated with noise 
exampleData <- data.frame(product = rep(LETTERS,1000), 
          wholesale = rnorm(1000*26), 
          revenue = rnorm(1000*26)) 

# create a week_ending column which increases by one week with every set of 26 "products" 
for(i in 1:nrow(exampleData)){ 
    exampleData$week_ending[i] <- as.Date("2016-09-04")+7*floor((i-1)/26) 
} 
exampleData$week_ending <- as.Date(exampleData$week_ending, origin = "1970-01-01") 

# create empty columns to fill 
exampleData$wholesale_wow <- NA 
exampleData$revenue_wow <- NA 

# loop through the wholesale and revenue numbers and append the week-over-week changes 
for(i in 1:nrow(exampleData)){ 
    # set a condition where the loop only appends the week-over-week values if it's not the first week 
    if(exampleData$week_ending[i]!="2016-09-04"){ 
    # set temporary values for the current and past week's wholesale value 
    currentWholesale <- exampleData$wholesale[i] 
    lastWeekWholesale <- exampleData$wholesale[which(exampleData$product==exampleData$product[i] & 
                 exampleData$week_ending==exampleData$week_ending[i]-7)] 
    exampleData$wholesale_wow[i] <- currentWholesale/lastWeekWholesale -1 

    # set temporary values for the current and past week's revenue 
    currentRevenue <- exampleData$revenue[i] 
    lastWeekRevenue <- exampleData$revenue[which(exampleData$product==exampleData$product[i] & 
                exampleData$week_ending==exampleData$week_ending[i]-7)] 
    exampleData$revenue_wow[i] <- currentRevenue/lastWeekRevenue -1 
    } 
} 

समझने क्यों यह इतने लंबे समय या कैसे समय में कटौती करने लग जाते हैं किसी भी मदद की बहुत सराहना की जाएगी!

+0

शायद मुख्य मुद्दा नहीं है ... लेकिन लूप में तिथियों को तारों का विश्लेषण न करें; बस 'd0 = as.Date ("2016-09-04") को कहीं और सहेजें और इसका उपयोग करें। यह भी एक स्ट्रिंग बनाम '! =' नहीं है जिसे आज तक पार्स किया जाना चाहिए। मुझे संदेह है कि कोड का मुख्य भाग एक लूप के बजाय मर्ज/जॉइन के रूप में लिखा जा सकता है। – Frank

+1

यह अच्छा और पुनरुत्पादित दिखता है, लेकिन (कम से कम भविष्य में) मैं सुझाव देता हूं कि ** न्यूनतम ** उदाहरण भी बनाएं। 26 उत्पादों और 140 हफ्तों की तुलना में, 2 उत्पादों और 4 सप्ताह के साथ क्या हो रहा है, यह देखने के लिए प्रत्येक चरण में डेटा का निरीक्षण करना अधिक आसान होगा। – Gregor

+0

प्रतिक्रिया के लिए धन्यवाद! मैं oversimplify नहीं करना चाहता था, लेकिन आप सही हैं कि यह अधिक सरल हो सकता था। मैं अगली बार इसे ध्यान में रखूंगा। –

उत्तर

6

पहले for पाश के लिए निम्नलिखित के साथ सरल किया जा सकता:

exampleData$week_ending2 <- as.Date("2016-09-04") + 7 * floor((seq_len(nrow(exampleData)) - 1)/26) 

setequal(exampleData$week_ending, exampleData$week_ending2) 
[1] TRUE 

की जगह दूसरा for पाश

library(data.table) 
dt1 <- as.data.table(exampleData) 
dt1[, wholesale_wow := wholesale/shift(wholesale) - 1 , by = product] 
dt1[, revenue_wow := revenue/shift(revenue) - 1 , by = product] 

setequal(exampleData, dt1) 
[1] TRUE 

यह अपने लैपटॉप पर चलाने के लिए लगभग 4 मिलीसेकेंड लेता

+0

धन्यवाद, लेकिन वास्तविक समस्या दूसरी लूप के साथ है। मेरे असली डेटा को सप्ताह के अंत में फ़ील्ड जोड़ने की आवश्यकता नहीं थी क्योंकि यह पहले से मौजूद है इसलिए मैंने इसे उदाहरण के लिए बनाया है। –

+0

@WillWright ने दूसरे लूप के लिए कोड जोड़ा जो मिलीसेकंड – manotheshark

+0

अविश्वसनीय में निष्पादित करता है। मुझे नहीं लगता कि मैंने अतीत में डेटाटेबल पैकेज का उपयोग किया है, लेकिन मैं निश्चित रूप से इसे सीखने में कुछ समय लगाऊंगा। यह समाधान एक आकर्षण की तरह काम करता है! –

1

यहाँ है tidyr पैकेज का उपयोग कर एक वेक्टरकृत समाधान।

set.seed(123) 
# Create empty data frame of 26,000 observations similar to my data, but populated with noise 
exampleData <- data.frame(product = rep(LETTERS,1000), 
          wholesale = rnorm(1000*26), 
          revenue = rnorm(1000*26)) 

# create a week_ending column which increases by one week with every set of 26 "products" 
#vectorize the creating of the data 
i<-1:nrow(exampleData) 
exampleData$week_ending <- as.Date("2016-09-04")+7*floor((i-1)/26) 

exampleData$week_ending <- as.Date(exampleData$week_ending, origin = "1970-01-01") 

# create empty columns to fill 
exampleData$wholesale_wow <- NA 
exampleData$revenue_wow <- NA 

#find the index of rows of interest (ie removing the first week) 
i<-i[exampleData$week_ending!="2016-09-04"] 

library(tidyr) 

#create temp variables and convert into wide format 
# the rows are product and the columns are the ending weeks 
Wholesale<-exampleData[ ,c(1,2,4)] 
Wholesale<-spread(Wholesale, week_ending, wholesale) 

Revenue<-exampleData[ ,c(1,3,4)] 
Revenue<-spread(Revenue, week_ending, revenue) 

#number of columns 
numCol<-ncol(Wholesale) 

#remove the first two columns for current wholesale 
#remove the first and last column for last week's wholesale 
#perform calculation on ever element in dataframe (divide this week/lastweek) 
Wholesale_wow<- Wholesale[ ,-c(1, 2)]/Wholesale[ ,-c(1, numCol)] - 1 
#convert back to long format 
Wholesale_wow<-gather(Wholesale_wow) 

#repeat for revenue 
Revenue_wow<- Revenue[ ,-c(1, 2)]/Revenue[ ,-c(1, numCol)] - 1 
#convert back to long format 
Revenue_wow<-gather(Revenue_wow) 

#assemble calculated values back into the original dataframe 
exampleData$wholesale_wow[i]<-Wholesale_wow$value 
exampleData$revenue_wow[i]<-Revenue_wow$value 

रणनीति मूल डेटा को एक विस्तृत प्रारूप में परिवर्तित करना था जहां पंक्तियां उत्पाद आईडी थीं और कॉलम सप्ताह थे। फिर एक दूसरे द्वारा डेटा फ्रेम विभाजित करें। वापस एक लंबे प्रारूप में कनवर्ट करें और उदाहरण के लिए डेटा गणना फ्रेम में नए गणना मूल्य जोड़ें। यह काम करता है, बहुत साफ नहीं है लेकिन लूप की तुलना में बहुत तेज़ है। इस प्रकार के काम के लिए dplyr पैकेज एक और उपकरण है। के साथ मामले उपयोग का परीक्षण

इस कोड के इस परिणाम की तुलना करने के लिए:

print(identical(goldendata, exampleData)) 

कहाँ goldendata अपने नाम से जाना जाता अच्छे परिणाम, set.seed() फ़ंक्शन के साथ एक ही यादृच्छिक संख्या का उपयोग सुनिश्चित करें है।

+0

उत्कृष्ट! मुझे पता था कि समाधान डेटा पुनर्गठन के साथ होगा, लेकिन मैं इन शर्तों में समाधान के बारे में सोचने के लिए अभी भी नया हूं। अनेक अनेक धन्यवाद! यह सेकंड में चलता है। मैं निश्चित रूप से इसे अपने टूलबल्ट में जोड़ दूंगा। –

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

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