2017-02-11 63 views
1

我有僱用的人,多年數據幀:熊貓:擴展數據幀逐行,類似的r SurvSplit()

person_id years     
1   1.00 
2   2.34 
3   6.85 

我想逐行根據預先定義的「塊擴展數據框「在員工的任期內。例如,如果我要大塊人們在1年標誌使用權,上述數據幀將變成:

person_id tstart tend     
1   0.00 1.00 
2   0.00 1.00 
2   1.00 2.34 
3   0.00 1.00 
3   1.00 6.85 

如果我想塊在1年和2年的標誌,原來的數據幀變爲:

person_id tstart tend     
1   0.00 1.00 
2   0.00 1.00 
2   1.00 2.00 
2   2.00 2.34 
3   0.00 1.00 
3   1.00 2.00 
3   2.00 6.85 

所以,理想情況下,我想提供一個list或塊的tuple直接在行擴張(如[1,2]到塊在1,2年)

該數據幀的操作將類似的r survSplit() - 參見頁碼127 here

我該怎麼做?我在Stackoverflow上發現了一些文章,但他們討論了不同的數據框擴展目標。

回答

1

考慮以下定義的方法。雖然有點步行通過它使用不同survsplit實際的源代碼沒有循環這是寫在C.

以下基本運行的迭代任職多年的交叉聯接到最大 ARG和合並,以點人'。然後,原始數據幀值與計算的tstart傾向列在merge結果上連接。一個關鍵必須分配給原始數據幀,這裏是

from io import StringIO 
import pandas as pd 
import numpy as np 

persons = pd.read_table(StringIO("""person_id years     
1   1.00 
2   2.34 
3   6.85"""), sep="\s+").assign(key = 1) 

def expand_tenure(chunk): 
    newpersons = persons.assign(tstart = chunk, tend = persons['years']) 
    newpersons.loc[newpersons['tend'] < chunk, 'tstart'] = np.floor(persons['years']) 

    df = pd.DataFrame({'tstart': list(range(0, chunk)), 
         'tend': list(range(1, chunk+1)), 
         'key': 1}) 

    mdf = pd.merge(persons, df, on='key')  
    mdf = mdf[mdf['tend'] <= mdf['years']][['person_id', 'tstart', 'tend']] 

    cdf = pd.concat([newpersons[['person_id', 'tstart', 'tend']], mdf])\ 
        .sort_values(['person_id', 'tstart'])\ 
        .drop_duplicates(['person_id', 'tend']).reset_index(drop=True) 

    return cdf 

輸出(三奔跑)

print(expand_tenure(1)) 
# person_id tstart tend 
# 0   1  0.0 1.00 
# 1   2  0.0 1.00 
# 2   2  1.0 2.34 
# 3   3  0.0 1.00 
# 4   3  1.0 6.85 

print(expand_tenure(4)) 
# person_id tstart tend 
# 0   1  0.0 1.00 
# 1   2  0.0 1.00 
# 2   2  1.0 2.00 
# 3   2  2.0 2.34 
# 4   3  0.0 1.00 
# 5   3  1.0 2.00 
# 6   3  2.0 3.00 
# 7   3  3.0 4.00 
# 8   3  4.0 6.85 

print(expand_tenure(12)) 
#  person_id tstart tend 
# 0   1  0.0 1.00 
# 1   2  0.0 1.00 
# 2   2  1.0 2.00 
# 3   2  2.0 2.34 
# 4   3  0.0 1.00 
# 5   3  1.0 2.00 
# 6   3  2.0 3.00 
# 7   3  3.0 4.00 
# 8   3  4.0 5.00 
# 9   3  5.0 6.00 
# 10   3  6.0 6.85 
+0

真棒,謝謝! – NickBraunagel