2017-01-31 87 views
2

考慮一個不平衡的面板,其中的空白是信息性的(例如,真正的零)。 I 想要添加零。實質上,我試圖在熊貓中重新創建stata函數tsfill的功能。使用Python填充面板數據中的空白大熊貓

實施例的數據(I構建均衡面板,以及除去一些觀察):

import numpy as np 
import pandas as pd 
import datetime 

np.random.seed(123456) 

all_dates = pd.DataFrame(pd.date_range(datetime.date(2015,1,1),datetime.date(2015,12,31)),columns=['date']) 
balanced_data=all_dates.copy() 
balanced_data['id']=0 
for x in range(99): 
    appendme=all_dates 
    appendme['id']=x+1 
    balanced_data=balanced_data.append(appendme) 

balanced_data.reset_index(inplace=True,drop=True) 
balanced_data['random']=np.random.random_sample(balanced_data.shape[0])>=0.5 

# remove some data 
unbalanced_data=balanced_data[balanced_data['random']==1].reset_index(drop=True) 

的一種方法,使再次平衡該面板是不平衡面板合併到具有平衡ID和日期的數據幀列:

# construct one full set of dates for everyone 
all_dates = pd.DataFrame(pd.date_range(unbalanced_data['date'].min(),unbalanced_data['date'].max()),columns=['date']) 

length = unbalanced_data['id'].unique().size 
all_dates_full=all_dates 
for x in range(length-1): 
    all_dates_full=all_dates_full.append(all_dates) 

all_dates_full.reset_index(inplace=True,drop=True) 

# duplicate ids to match the number of dates 
length = all_dates.size 
ids=unbalanced_data['id'].drop_duplicates() 
ids_full=ids 
for x in range(length-1): 
    ids_full=ids_full.append(ids) 

ids_full.sort_values(inplace=True) 
ids_full.reset_index(inplace=True,drop=True) 

balanced_panel = pd.concat([all_dates_full,ids_full],axis=1) 

rebalanced_data=pd.merge(balanced_panel,unbalanced_data,how='left',on=['id','date']) 
rebalanced_data.fillna(False,inplace=True) 

# check 
balanced_data==rebalanced_data 

除了笨重,我覺得這種方法是非常緩慢的,因爲N變大了。我想那裏必須是一個更有效的重新平衡面板的方法,但我找不到它。

(PS這是我在計算器的第一個問題,所以對於未來的問題的任何建設性的批評非常感謝!)

回答

0

至於性能也越高,相對於附加列表時,在大熊貓附加dataframes是一個緩慢的操作。索引是不可變的,所以每次追加時都會創建一個新的索引。這是一個解決方案,它在熊貓之外構建集合,然後將它們連接到一個數據框中。

uid = unbalanced_data['id'].unique() 
ids_full = np.array([[x]*len(all_dates) for x in range(len(uid))]).flatten() 
dates = all_dates['date'].tolist() * len(uid) 
balanced_panel = pd.DataFrame({'id': ids_full, 'date': dates}) 
rebalanced_data = pd.merge(balanced_panel, unbalanced_data, how=‌​'left', 
          on=['id', 'dat‌​e']).fillna(False) 
+0

謝謝。您的方法效率更高,但要求具有相同的索引位置以用於平衡和不平衡的數據。例如。如果我反而重置了非平衡數據索引--unbalanced_data = balanced_data [balanced_data ['random'] == 1] .reset_index() - 那麼「combine_first」方法不起作用。有沒有辦法解決這個問題? – dkou

+1

在這種情況下,rebalanced_data = pd.merge(balanced_pa​​nel,unbalanced_data,how ='left',on = ['id','date'])。fillna(False)我認爲我的代碼中主要的低效率似乎可以通過前4行來解決,所以再次感謝! – dkou

+0

你是對的,索引需要對齊,所以合併是一個更好的選擇。我更新這篇文章以反映這一點。 – rtk22