2012-11-01 16 views
6

को स्थानांतरित करने का सबसे प्रभावी तरीका मेरे पास डेटाफ्रेम है जिसमें कई स्टैक्ड टाइम श्रृंखला शामिल हैं। इंडेक्स (पूलआईडी, महीने) है जहां दोनों पूर्णांक हैं, "महीने" 2000 से महीनों की संख्या है। एकाधिक चर के एक महीने के अंतराल संस्करणों की गणना करने का सबसे अच्छा तरीका क्या है?मल्टीइंडेक्स समय श्रृंखला

cols_to_shift = ["bal", ...5 more columns...] 
df_shift = df[cols_to_shift].groupby(level=0).transform(lambda x: x.shift(-1)) 

अपने डेटा के लिए यह मेरे चलाने के लिए ले लिया एक पूर्ण 60 रों,:

अभी, मैं की तरह कुछ है। (मैं 48k अलग पूल और 718k पंक्तियों के कुल की है।)

मैं आर कोड और बराबर data.table कॉल से परिवर्तित कर रहा हूँ:

dt.shift <- dt[, list(bal=myshift(bal), ...), by=list(poolId)] 

केवल चलाने के लिए 9 रों लेता है। (यहां "माईशफ्ट" कुछ "फ़ंक्शन (एक्स) सी (एक्स [-1], एनए) जैसा है"।)

क्या कोई तरीका है कि मैं पैंडस कैरिसन को गति से वापस लाइन में वापस लाने के लिए एक तरीका प्राप्त कर सकता हूं? मैंने इसे 0.8.1 पर परीक्षण किया।

संपादित करें: यहाँ एक करीबी के लिए पर्याप्त डेटा सेट पैदा करने का एक उदाहरण है, तो आप मैं क्या मतलब है के कुछ विचार प्राप्त कर सकते हैं:

ids = np.arange(48000) 
lens = np.maximum(np.round(15+9.5*np.random.randn(48000)), 1.0).astype(int) 
id_vec = np.repeat(ids, lens) 
lens_shift = np.concatenate(([0], lens[:-1])) 
mon_vec = np.arange(lens.sum()) - np.repeat(np.cumsum(lens_shift), lens) 
n = len(mon_vec) 
df = pd.DataFrame.from_items([('pool', id_vec), ('month', mon_vec)] + [(c, np.random.rand(n)) for c in 'abcde']) 
df = df.set_index(['pool', 'month']) 
%time df_shift = df.groupby(level=0).transform(lambda x: x.shift(-1)) 

कि ले लिया 64 रों जब मैं इसे करने की कोशिश। इस डेटा में प्रत्येक श्रृंखला 0 महीने से शुरू होती है; वास्तव में, वे सभी महीने np.max (लेंस) पर समाप्त होना चाहिए, ragged प्रारंभ तिथियों के साथ, लेकिन काफी अच्छा है।

संपादित करें 2: यहां कुछ तुलना आर कोड है। यह 0.8 एस लेता है। 80 का कारक, अच्छा नहीं।

library(data.table) 
ids <- 1:48000 
lens <- as.integer(pmax(1, round(rnorm(ids, mean=15, sd=9.5)))) 
id.vec <- rep(ids, times=lens) 
lens.shift <- c(0, lens[-length(lens)]) 
mon.vec <- (1:sum(lens)) - rep(cumsum(lens.shift), times=lens) 
n <- length(id.vec) 
dt <- data.table(pool=id.vec, month=mon.vec, a=rnorm(n), b=rnorm(n), c=rnorm(n), d=rnorm(n), e=rnorm(n)) 
setkey(dt, pool, month) 
myshift <- function(x) c(x[-1], NA) 
system.time(dt.shift <- dt[, list(month=month, a=myshift(a), b=myshift(b), c=myshift(c), d=myshift(d), e=myshift(e)), by=pool]) 
+0

मैं यहाँ एक GitHub मुद्दे खोला: https://github.com/pydata/pandas/मुद्दों/2162। मैं एक नज़र डालेंगे –

उत्तर

6

मैं तुम्हें डेटा नयी आकृति प्रदान का सुझाव और बनाम GroupBy दृष्टिकोण एक भी पारी करना होगा:

result = df.unstack(0).shift(1).stack() 

यह स्विच स्तरों के क्रम ताकि आप स्वैप करने के लिए चाहते हैं और पुन: व्यवस्थित करें:

result = result.swaplevel(0, 1).sortlevel(0) 

आप इसे एक अवधि के द्वारा लेग्ड किया गया है सत्यापित कर सकते हैं (यदि आप चाहते पारी (1) पारी (-1) के बजाय):

In [17]: result.ix[1] 
Out[17]: 
       a   b   c   d   e 
month             
1  0.752511 0.600825 0.328796 0.852869 0.306379 
2  0.251120 0.871167 0.977606 0.509303 0.809407 
3  0.198327 0.587066 0.778885 0.565666 0.172045 
4  0.298184 0.853896 0.164485 0.169562 0.923817 
5  0.703668 0.852304 0.030534 0.415467 0.663602 
6  0.851866 0.629567 0.918303 0.205008 0.970033 
7  0.758121 0.066677 0.433014 0.005454 0.338596 
8  0.561382 0.968078 0.586736 0.817569 0.842106 
9  0.246986 0.829720 0.522371 0.854840 0.887886 
10  0.709550 0.591733 0.919168 0.568988 0.849380 
11  0.997787 0.084709 0.664845 0.808106 0.872628 
12  0.008661 0.449826 0.841896 0.307360 0.092581 
13  0.727409 0.791167 0.518371 0.691875 0.095718 
14  0.928342 0.247725 0.754204 0.468484 0.663773 
15  0.934902 0.692837 0.367644 0.061359 0.381885 
16  0.828492 0.026166 0.050765 0.524551 0.296122 
17  0.589907 0.775721 0.061765 0.033213 0.793401 
18  0.532189 0.678184 0.747391 0.199283 0.349949 

In [18]: df.ix[1] 
Out[18]: 
       a   b   c   d   e 
month             
0  0.752511 0.600825 0.328796 0.852869 0.306379 
1  0.251120 0.871167 0.977606 0.509303 0.809407 
2  0.198327 0.587066 0.778885 0.565666 0.172045 
3  0.298184 0.853896 0.164485 0.169562 0.923817 
4  0.703668 0.852304 0.030534 0.415467 0.663602 
5  0.851866 0.629567 0.918303 0.205008 0.970033 
6  0.758121 0.066677 0.433014 0.005454 0.338596 
7  0.561382 0.968078 0.586736 0.817569 0.842106 
8  0.246986 0.829720 0.522371 0.854840 0.887886 
9  0.709550 0.591733 0.919168 0.568988 0.849380 
10  0.997787 0.084709 0.664845 0.808106 0.872628 
11  0.008661 0.449826 0.841896 0.307360 0.092581 
12  0.727409 0.791167 0.518371 0.691875 0.095718 
13  0.928342 0.247725 0.754204 0.468484 0.663773 
14  0.934902 0.692837 0.367644 0.061359 0.381885 
15  0.828492 0.026166 0.050765 0.524551 0.296122 
16  0.589907 0.775721 0.061765 0.033213 0.793401 
17  0.532189 0.678184 0.747391 0.199283 0.349949 

Perf (यह 0.9.0 में एक स्पर्श धीमी हो सकती है) इस विधि के साथ बहुत बुरा नहीं है:

In [19]: %time result = df.unstack(0).shift(1).stack() 
CPU times: user 1.46 s, sys: 0.24 s, total: 1.70 s 
Wall time: 1.71 s 
+0

यह एक बड़ा सुधार है! यह 0.8.1 के तहत मेरे लिए 6.6 एस लिया; उम्मीद है कि अगले हफ्ते हमारे पास 0.9.0 इंस्टॉल होगा इसलिए मैं कोशिश कर सकता हूं। –

+0

एक अंतर यह है कि चूंकि यह स्टैक() पर शिफ्ट() द्वारा उत्पन्न NaN प्रविष्टियों को छोड़ देता है, इसकी तुलना में कम पंक्तियां होती हैं, लेकिन इसमें शामिल होने() में ध्यान दिया जाता है। (और मेरा मतलब शिफ्ट (-1) था; यह एक खतरनाक दर की गणना है, इसलिए यह आगे दिख रहा है।) –

+0

मेरे द्वारा किए गए प्रदर्शन सुधार ट्रंक में थे। –

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