填写日期并使用以前的值

2024-04-25 09:49:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我的熊猫数据框如下所示

 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)填写从每个国家开始的所有日期(每天),例如,对于美国,从2013年1月1日到今天,对于英国,从2000年1月1日到今天。你知道吗

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

非常感谢你的帮助


Tags: 数据date国家countryusukgd
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]
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

您可以将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)

更正:我的第一个答案作为最后一步填充了整个数据帧:df = df.ffill()。只有当每个国家的第一个gd值不是NaN时,这才是正确的。如果某个国家的起始行具有NaNgd值,则向前填充可能会用另一个国家的值污染这些gd值。伊克斯。更健壮和正确的方法是将每个组作为shown by piRSquared向前填充一次。在较小的数据帧上,通过前向填充一次而不是多次来获得的任何性能增益都是很小的,因为ffill调用的数量受国家(相当低的数字)的数量限制,并且安全防范潜在的bug远比可能获得的有限性能增益重要。你知道吗


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

相关问题 更多 >

    热门问题