填写日期并使用以前的值

时间:2017-07-18 20:56:03

标签: python pandas

我的pandas数据框如下所示

 country     date           gd  
 US          01-01-2014      2
 US          01-01-2015      3
 US          01-01-2013      0.4
 UK          01-01-2000      0.7
 UK          02-01-2001      0.5
 UK          01-01-2016      1

我想做的是:

1)从每个国家/地区的最短日期开始填写所有日期(每日),所以对于美国来说,这是至今天的01-01-2013,对于英国,从今天起每天01-01-2000。

2)使用以前的可用数据填充gd列

非常感谢你的帮助

3 个答案:

答案 0 :(得分:3)

In [67]: today = pd.to_datetime(pd.datetime.now()).normalize()

In [68]: l = df.country.nunique()

In [72]: df.append(pd.DataFrame({'country':df.country.unique(), 'date':[today]*l, 'gd':[np.nan]*l})) \
    ...:   .sort_values('date') \
    ...:   .groupby('country') \
    ...:   .resample('1D', on='date') \
    ...:   .mean() \
    ...:   .reset_index() \
    ...:   .ffill()
    ...:
Out[72]:
     country       date   gd
0         UK 2000-01-01  0.7
1         UK 2000-01-02  0.7
2         UK 2000-01-03  0.7
3         UK 2000-01-04  0.7
4         UK 2000-01-05  0.7
5         UK 2000-01-06  0.7
6         UK 2000-01-07  0.7
7         UK 2000-01-08  0.7
8         UK 2000-01-09  0.7
9         UK 2000-01-10  0.7
...      ...        ...  ...
8059      US 2017-07-09  3.0
8060      US 2017-07-10  3.0
8061      US 2017-07-11  3.0
8062      US 2017-07-12  3.0
8063      US 2017-07-13  3.0
8064      US 2017-07-14  3.0
8065      US 2017-07-15  3.0
8066      US 2017-07-16  3.0
8067      US 2017-07-17  3.0
8068      US 2017-07-18  3.0

[8069 rows x 3 columns]

答案 1 :(得分:3)

您可以设置date索引,然后使用reindex扩展日期,ffill转发填充NaN:

def expand_dates(grp):
    start = grp.index.min()
    end = today
    index = pd.date_range(start, end, freq='D')
    return grp.reindex(index).ffill()

使用groupby/apply为每个组调用expand_dates一次并连接结果:

df = df.groupby('country')['gd'].apply(expand_dates)

更正:我的第一个答案是向前填充整个DataFrame作为最后一步:df = df.ffill()。仅当每个国家/地区的第一个gd值不是NaN时,这才是正确的。如果某个国家/地区的起始行有NaN gd个值,则前向填充可能会使用其他国家/地区的值污染这些gd值。让人惊讶。更健壮和正确的方法是将每个组前向填充一次为shown by piRSquared。通过前向填充而不是多次在较小的DataFrame上实现的任何性能提升都是微不足道的,因为ffill调用的数量受到国家数量的限制(数量非常少)并且防范潜在错误更为重要而不是有限的性能增益。

import numpy as np
import pandas as pd
df = pd.DataFrame({'country': ['US', 'US', 'US', 'UK', 'UK', 'UK'], 'date': ['01-01-2014', '01-01-2015', '01-01-2013', '01-01-2000', '02-01-2001', '01-01-2016'], 'gd': [2.0, 3.0, 0.4, 0.7, 0.5, 1.0]})
df['date'] = pd.to_datetime(df['date'])
today = pd.Timestamp('today')
def expand_dates(grp):
    start = grp.index.min()
    end = today
    index = pd.date_range(start, end, freq='D')
    return grp.reindex(index).ffill()
df = df.set_index('date')
df = df.groupby('country')['gd'].apply(expand_dates)
print(pd.concat([df.head(), df.tail()]))

产量

country            
UK       2000-01-01    0.7
         2000-01-02    0.7
         2000-01-03    0.7
         2000-01-04    0.7
         2000-01-05    0.7
US       2017-07-14    3.0
         2017-07-15    3.0
         2017-07-16    3.0
         2017-07-17    3.0
         2017-07-18    3.0
Name: gd, dtype: float64

答案 2 :(得分:3)

s = df.set_index(['country', 'date']).gd

today = pd.datetime.today()

def then2now(x):
    x = x.xs(x.name)
    mn = x.index.min()
    return x.reindex(pd.date_range(mn, today, name='date')).ffill()

s.groupby(level='country').apply(then2now).reset_index()

     country       date   gd
0         UK 2000-01-01  0.7
400       UK 2001-02-04  0.5
800       UK 2002-03-11  0.5
1200      UK 2003-04-15  0.5
1600      UK 2004-05-19  0.5
2000      UK 2005-06-23  0.5
2400      UK 2006-07-28  0.5
2800      UK 2007-09-01  0.5
3200      UK 2008-10-05  0.5
3600      UK 2009-11-09  0.5
4000      UK 2010-12-14  0.5
4400      UK 2012-01-18  0.5
4800      UK 2013-02-21  0.5
5200      UK 2014-03-28  0.5
5600      UK 2015-05-02  0.5
6000      UK 2016-06-05  1.0
6400      UK 2017-07-10  1.0
6800      US 2014-01-27  2.0
7200      US 2015-03-03  3.0
7600      US 2016-04-06  3.0
8000      US 2017-05-11  3.0