2017-09-25 94 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