2017-09-25 90 views
1

比方說,我有一個數據幀是這樣的:熊貓:添加行到每一組視病情

  date id val 
0 2017-01-01 1 10 
1 2019-01-01 1 20 
2 2017-01-01 2 50 

我想這組數據集由id
對於每個組,我想添加一個新的行,日期從現在開始爲1年。如果它晚於組中的最後一個日期,則只應添加此行。行的val應該與組中的最後一行相同。

決賽桌應該是這樣的:

  date id val 
0 2017-01-01 1 10 
1 2019-01-01 1 20 
2 2017-01-01 2 50 
3 2018-09-25 2 50 <-- new row 

當前的代碼如下。我可以得到一個掩碼,顯示哪些組需要添加一行,但不知道下一步該怎麼做。

>>> df = pd.DataFrame(data={'d': [datetime.date(2017, 1, 1), datetime.date(2019,1,1), datetime.date(2017,1,1)], 'id': [1,1,2], 'val': [10,20,50]}) 
>>> df = df.sort_values(by='d') 
>>> future_date = (pd.datetime.now().date() + pd.DateOffset(years=1)).date() 
>>> maxd = df.groupby('id')['d'].max() 
>>> maxd < future_date 
id 
1 False 
2  True 
Name: d, dtype: bool 

回答

2

這裏有一種方法

In [3481]: def add_row(x): 
     ...:  next_year = pd.to_datetime('today') + pd.DateOffset(years=1) 
     ...:  if x['date'].max() < next_year: 
     ...:   last_row = x.iloc[-1] 
     ...:   last_row['date'] = next_year 
     ...:   return x.append(last_row) 
     ...:  return x 
     ...: 

In [3482]: df.groupby('id').apply(add_row).reset_index(drop=True) 
Out[3482]: 
     date id val 
0 2017-01-01 1 10 
1 2019-01-01 1 20 
2 2017-01-01 2 50 
3 2018-09-25 2 50 
2

您可以使用idxmaxloc的行與maxdate

future_date = pd.to_datetime('today') + pd.DateOffset(years=1) 
maxd = df.loc[df.groupby('id')['d'].idxmax()] 

maxd = maxd[maxd['d'] < future_date] 
maxd['d'] = future_date 
print (maxd) 
      d id val 
2 2018-09-25 2 50 

df = pd.concat([df, maxd]).sort_values(['id','d']).reset_index(drop=True) 
print (df) 
      d id val 
0 2017-01-01 1 10 
1 2019-01-01 1 20 
2 2017-01-01 2 50 
3 2018-09-25 2 50 
2

一種不同的方式來看待它,使用duplicated找到最後一行每'id'

t = df[~df.duplicated('id', 'last')] 
df.append(
    t.assign(
     date=pd.to_datetime('today') + pd.DateOffset(years=1) 
    ).pipe(lambda d: d[d.date > t.date]), 
    ignore_index=True).sort_values(['id', 'date']) 

     date id val 
0 2017-01-01 1 10 
1 2019-01-01 1 20 
2 2017-01-01 2 50 
3 2018-09-24 2 50