2014-09-26 32 views
1

我有一個快速從多索引熊貓數據框中刪除行的問題,其中丟棄標準基於1級索引。或者等價地,通過將​​單索引數據幀或numpy數組附加爲行來構建多索引數據幀。在我的具體的例子,我有所謂的「表」的數據幀,例如這樣的:快速從多索引數據框中快速刪除行,條件是1級索引

       userid watchers 
repositoryid   date  
    5910995 1348293168 1449180   1 
    5911012 1348292421 2627657   1 
    5911046 1367171000 1219404   1 
       1368722792 1892225   2 
       1383586883 2150178   3 
    5911088 1348302179 1521780   1 
     ... 

其中repositoryid和日期是級別0和一個多指標,分別是1,和用戶ID和觀察者是數據列。因此,對於每個repositoryid,我基本上都有一系列開始觀看存儲庫的用戶事件。對於每個repositoryid,我也從其他地方知道特定的creationdate。現在我想刪除所有行,其中datetime> creationdate + timewindow,其中timewindow是一些常量。

我嘗試使用drop()函數,但是這非常慢。我認爲布爾屏蔽將是最好的解決方案,但我無法使其與multiindex一起工作。我也試圖建立從頭開始新的數據幀在幾次嘗試,最新的一個是這樣的:

watch_new = DataFrame(columns=['date', 'userid', 'watchers']) 
for i,rid in enumerate(watch.index.get_level_values('repositoryid')): 
    creationdate = repository.loc[rid].date.squeeze() 
    thistimeseries = watch.loc[rid] 
    thistimeseries = thistimeseries[thistimeseries.index <= creationdate+timewindow] 
    thistimeseries.reset_index(inplace=True) 
    if len(thistimeseries) != 0: 
     watch_new.loc[rid] = thistimeseries.as_matrix() 

不幸的是,一旦thistimeseries.as_matrix()有超過一排,我收到一條錯誤消息,因爲這(在這種情況下,10行):

ValueError: could not broadcast input array from shape (10,3) into shape (3) 

所以,我的問題是,1a)中如何快速下降行從多索引的數據幀的條件上的電平1的索引,或等效1b)的如何將單索引數據幀插入多索引數據幀,以及2)這是甚至是解決我的問題最好的最快的方法,還是應該嘗試一種完全不同的方法? (我也嘗試過不使用索引,但那太慢了,我玩過join,merge,groupby等等,很遺憾我沒有設法讓他們解決我的問題,我花了5天時間學習優秀的書籍「Python for Data Analysis」,並試圖找到解決這個問題的解決方案,但又沒有成功。我希望一個先進的熊貓用戶可以爲這個看似簡單的問題提供一個優雅的解決方案?非常感謝!)

回答

0

與此設置開始:

import pandas as pd 
df = pd.read_table('data', sep='\s+').set_index(['repositoryid', 'date']) 
repository = pd.read_table('data2', sep='\s+').set_index(['repositoryid']) 
timewindow = 100 

假設我們有df

      userid watchers 
repositoryid date       
5910995  1348293168 1449180   1 
5911012  1348292421 2627657   1 
5911046  1367171000 1219404   1 
      1368722792 1892225   2 
      1383586883 2150178   3 
5911088  1348302179 1521780   1 

repository

    date 
repositoryid    
5910995  1348293200 
5911012  1348292400 
5911046  1368722800 
5911088  1348303000 

目前,大熊貓不支持合併在一個多指標的某些級別。因此,無論dfrepository必須具有相同的指數形狀,以被合併:

df.reset_index(level='date', inplace=True) 
df = df.join(repository, rsuffix='_threshold') 

產生

    date userid watchers date_threshold 
repositoryid            
5910995  1348293168 1449180   1  1348293200 
5911012  1348292421 2627657   1  1348292400 
5911046  1367171000 1219404   1  1368722800 
5911046  1368722792 1892225   2  1368722800 
5911046  1383586883 2150178   3  1368722800 
5911088  1348302179 1521780   1  1348303000 

現在,您可以添加timewindowdate_threshold

df['date_threshold'] += timewindow 

和當date小於date_threshold時比較:

mask = df['date'] < df['date_threshold'] 

其中產生一個布爾系列等

In [207]: mask 
Out[207]: 
repositoryid 
5910995   True 
5911012   True 
5911046   True 
5911046   True 
5911046   False 
5911088   True 
dtype: bool 

使用布爾系列很容易使用df.loc選擇所需的行:代替使用maskdf.loc

In [208]: df.loc[mask] 
Out[208]: 
        date userid watchers date_threshold 
repositoryid            
5910995  1348293168 1449180   1  1348293300 
5911012  1348292421 2627657   1  1348292500 
5911046  1367171000 1219404   1  1368722900 
5911046  1368722792 1892225   2  1368722900 
5911088  1348302179 1521780   1  1348303100 

替代地,你可以使用query

In [213]: df.query('date < date_threshold') 
Out[213]: 
        date userid watchers date_threshold 
repositoryid            
5910995  1348293168 1449180   1  1348293300 
5911012  1348292421 2627657   1  1348292500 
5911046  1367171000 1219404   1  1368722900 
5911046  1368722792 1892225   2  1368722900 
5911088  1348302179 1521780   1  1348303100 
+0

謝謝,這工作完美!我想我會盡量避免使用多指標,因爲它們似乎有點受限。 – MSData 2014-09-29 15:14:26