我的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列
非常感谢你的帮助答案 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