Python 在多索引数据框中填充日期间隙
我想修改pandas多索引数据框,使每个索引组包含指定范围之间的日期。我希望每组用值0(或Python 在多索引数据框中填充日期间隙,python,pandas,numpy,dataframe,multi-index,Python,Pandas,Numpy,Dataframe,Multi Index,我想修改pandas多索引数据框,使每个索引组包含指定范围之间的日期。我希望每组用值0(或NaN)填写缺失的日期2013-06-11至2013-12-31 我看过一些关于reindexing的讨论,但这是针对一个简单(非分组)的时间序列数据 有没有一个简单的方法可以做到这一点 以下是我为实现这一目标所做的一些尝试。例如:一旦我按['A','B']取消了堆栈,我就可以重新编制索引了 df = pd.DataFrame({'A': ['loc_a'] * 12 + ['loc_b'],
NaN
)填写缺失的日期2013-06-11至2013-12-31
我看过一些关于reindex
ing的讨论,但这是针对一个简单(非分组)的时间序列数据
有没有一个简单的方法可以做到这一点
以下是我为实现这一目标所做的一些尝试。例如:一旦我按
['A','B']
取消了堆栈,我就可以重新编制索引了
df = pd.DataFrame({'A': ['loc_a'] * 12 + ['loc_b'],
'B': ['group_a'] * 7 + ['group_b'] * 3 + ['group_c'] * 2 + ['group_a'],
'Date': ["2013-06-11",
"2013-07-02",
"2013-07-09",
"2013-07-30",
"2013-08-06",
"2013-09-03",
"2013-10-01",
"2013-07-09",
"2013-08-06",
"2013-09-03",
"2013-07-09",
"2013-09-03",
"2013-10-01"],
'Value': [22, 35, 14, 9, 4, 40, 18, 4, 2, 5, 1, 2, 3]})
df.Date = df['Date'].apply(lambda x: pd.to_datetime(x).date())
df = df.set_index(['A', 'B', 'Date'])
dt_start = dt.datetime(2013,6,1)
all_dates = [(dt_start + dt.timedelta(days=x)).date() for x in range(0,60)]
df2 = df.unstack(['A', 'B'])
df3 = df2.reindex(index=all_dates).fillna(0)
df4 = df3.stack(['A', 'B'])
## df4 is about where I want to get, now I'm trying to get it back in the form of df...
df5 = df4.reset_index()
df6 = df5.rename(columns={'level_0' : 'Date'})
df7 = df6.groupby(['A', 'B', 'Date'])['Value'].sum()
最后几行让我有点难过。我希望在df6
上,我可以简单地将索引设置回['A','B','Date']
,但这并没有对值进行分组,因为它们在初始df
数据帧中进行分组
关于如何重新编制未堆叠数据帧的索引、重新打包并使数据帧与原始数据帧的格式相同,您有什么想法吗?您的问题不清楚您丢失了哪些日期;我只是假设您希望填写NaN
,填写您在其他地方观察到的任何日期。如果这个假设是错误的,我的解决方案将不得不修改
旁注:最好包含一行代码来创建DataFrame
In [55]: df = pd.DataFrame({'A': ['loc_a'] * 12 + ['loc_b'],
....: 'B': ['group_a'] * 7 + ['group_b'] * 3 + ['group_c'] * 2 + ['group_a'],
....: 'Date': ["2013-06-11",
....: "2013-07-02",
....: "2013-07-09",
....: "2013-07-30",
....: "2013-08-06",
....: "2013-09-03",
....: "2013-10-01",
....: "2013-07-09",
....: "2013-08-06",
....: "2013-09-03",
....: "2013-07-09",
....: "2013-09-03",
....: "2013-10-01"],
....: 'Value': [22, 35, 14, 9, 4, 40, 18, 4, 2, 5, 1, 2, 3]})
In [56]:
In [56]: df.Date = pd.to_datetime(df.Date)
In [57]: df = df.set_index(['A', 'B', 'Date'])
In [58]:
In [58]: print(df)
Value
A B Date
loc_a group_a 2013-06-11 22
2013-07-02 35
2013-07-09 14
2013-07-30 9
2013-08-06 4
2013-09-03 40
2013-10-01 18
group_b 2013-07-09 4
2013-08-06 2
2013-09-03 5
group_c 2013-07-09 1
2013-09-03 2
loc_b group_a 2013-10-01 3
要填充未观察到的值,我们将使用unstack
和stack
方法。取消堆叠将创建我们感兴趣的NaN
s,然后我们将它们堆叠起来使用
In [71]: df.unstack(['A', 'B'])
Out[71]:
Value
A loc_a loc_b
B group_a group_b group_c group_a
Date
2013-06-11 22 NaN NaN NaN
2013-07-02 35 NaN NaN NaN
2013-07-09 14 4 1 NaN
2013-07-30 9 NaN NaN NaN
2013-08-06 4 2 NaN NaN
2013-09-03 40 5 2 NaN
2013-10-01 18 NaN NaN 3
In [59]: df.unstack(['A', 'B']).fillna(0).stack(['A', 'B'])
Out[59]:
Value
Date A B
2013-06-11 loc_a group_a 22
group_b 0
group_c 0
loc_b group_a 0
2013-07-02 loc_a group_a 35
group_b 0
group_c 0
loc_b group_a 0
2013-07-09 loc_a group_a 14
group_b 4
group_c 1
loc_b group_a 0
2013-07-30 loc_a group_a 9
group_b 0
group_c 0
loc_b group_a 0
2013-08-06 loc_a group_a 4
group_b 2
group_c 0
loc_b group_a 0
2013-09-03 loc_a group_a 40
group_b 5
group_c 2
loc_b group_a 0
2013-10-01 loc_a group_a 18
group_b 0
group_c 0
loc_b group_a 3
根据需要重新排列索引级别
<>我不得不在<>代码> fILNA(0)中间,以便<代码>楠< /代码> s没有被删除。code>stack
确实有一个dropna
参数。我认为将其设置为false将保留allNaN
行。可能是个bug?您可以根据现有多索引级别的笛卡尔乘积创建一个新的多索引。然后,使用新索引重新索引数据帧
new_index=pd.MultiIndex.from_乘积(df.index.levels)
新建索引df=df.reindex(新建索引)
#可选:将缺少的值转换为零,然后将数据转换回零
#到整数。见下面的解释。
new_df=new_df.fillna(0).astype(int)
就这样!新数据帧具有所有可能的索引值。已正确索引现有数据
请继续阅读以获得更详细的解释
解释 设置示例数据
将熊猫作为pd导入
df=pd.DataFrame({'A':['loc_A']*12+['loc_b'],
‘B’:[‘a组’]*7+[‘B组’]*3+[‘c组’]*2+[‘a组’],
“日期”:[“2013-06-11”,
"2013-07-02",
"2013-07-09",
"2013-07-30",
"2013-08-06",
"2013-09-03",
"2013-10-01",
"2013-07-09",
"2013-08-06",
"2013-09-03",
"2013-07-09",
"2013-09-03",
"2013-10-01"],
“值”:[22,35,14,9,4,40,18,4,2,5,1,2,3]})
df.Date=pd.to_datetime(df.Date)
df=df.set_索引(['A','B','Date'])
下面是示例数据的样子
Value
A B Date
loc_a group_a 2013-06-11 22
2013-07-02 35
2013-07-09 14
2013-07-30 9
2013-08-06 4
2013-09-03 40
2013-10-01 18
group_b 2013-07-09 4
2013-08-06 2
2013-09-03 5
group_c 2013-07-09 1
2013-09-03 2
loc_b group_a 2013-10-01 3
制作新索引
使用该方法,我们可以创建一个新的多索引。这个新索引是旧索引所有级别的所有值的集合
new_index = pd.MultiIndex.from_product(df.index.levels)
重新索引
使用新索引重新索引现有数据帧
new_df = df.reindex(new_index)
所有可能的组合现在都存在。缺少的值为空(NaN)
扩展的、重新索引的数据帧如下所示:
Value
loc_a group_a 2013-06-11 22.0
2013-07-02 35.0
2013-07-09 14.0
2013-07-30 9.0
2013-08-06 4.0
2013-09-03 40.0
2013-10-01 18.0
group_b 2013-06-11 NaN
2013-07-02 NaN
2013-07-09 4.0
2013-07-30 NaN
2013-08-06 2.0
2013-09-03 5.0
2013-10-01 NaN
group_c 2013-06-11 NaN
2013-07-02 NaN
2013-07-09 1.0
2013-07-30 NaN
2013-08-06 NaN
2013-09-03 2.0
2013-10-01 NaN
loc_b group_a 2013-06-11 NaN
2013-07-02 NaN
2013-07-09 NaN
2013-07-30 NaN
2013-08-06 NaN
2013-09-03 NaN
2013-10-01 3.0
group_b 2013-06-11 NaN
2013-07-02 NaN
2013-07-09 NaN
2013-07-30 NaN
2013-08-06 NaN
2013-09-03 NaN
2013-10-01 NaN
group_c 2013-06-11 NaN
2013-07-02 NaN
2013-07-09 NaN
2013-07-30 NaN
2013-08-06 NaN
2013-09-03 NaN
2013-10-01 NaN
整数列中的空值
您可以看到,新数据帧中的数据已从整数转换为浮点。或者,我们可以将所有空值转换为0,并将数据转换回整数
new_df = new_df.fillna(0).astype(int)
结果
Value
loc_a group_a 2013-06-11 22
2013-07-02 35
2013-07-09 14
2013-07-30 9
2013-08-06 4
2013-09-03 40
2013-10-01 18
group_b 2013-06-11 0
2013-07-02 0
2013-07-09 4
2013-07-30 0
2013-08-06 2
2013-09-03 5
2013-10-01 0
group_c 2013-06-11 0
2013-07-02 0
2013-07-09 1
2013-07-30 0
2013-08-06 0
2013-09-03 2
2013-10-01 0
loc_b group_a 2013-06-11 0
2013-07-02 0
2013-07-09 0
2013-07-30 0
2013-08-06 0
2013-09-03 0
2013-10-01 3
group_b 2013-06-11 0
2013-07-02 0
2013-07-09 0
2013-07-30 0
2013-08-06 0
2013-09-03 0
2013-10-01 0
group_c 2013-06-11 0
2013-07-02 0
2013-07-09 0
2013-07-30 0
2013-08-06 0
2013-09-03 0
2013-10-01 0
FWIW,stack()的dropna参数适用于pandas 0.16.2。这非常有用。我确实丢失了索引的名称,但这意味着我们在看3行代码而不是2行…好的,4行代码:
index\u names=df.index.names
new\u index=pd.MultiIndex.from\u product(df.index.levels)
new\u index.names=index\u names
new\u df=df.reindex(tmp\u new\u index.fillna.astype)(int)采用names
positional参数,因此:new\u index=pd.MultiIndex.from\u product(df.index.levels,names=df.index.names)
Value
loc_a group_a 2013-06-11 22
2013-07-02 35
2013-07-09 14
2013-07-30 9
2013-08-06 4
2013-09-03 40
2013-10-01 18
group_b 2013-06-11 0
2013-07-02 0
2013-07-09 4
2013-07-30 0
2013-08-06 2
2013-09-03 5
2013-10-01 0
group_c 2013-06-11 0
2013-07-02 0
2013-07-09 1
2013-07-30 0
2013-08-06 0
2013-09-03 2
2013-10-01 0
loc_b group_a 2013-06-11 0
2013-07-02 0
2013-07-09 0
2013-07-30 0
2013-08-06 0
2013-09-03 0
2013-10-01 3
group_b 2013-06-11 0
2013-07-02 0
2013-07-09 0
2013-07-30 0
2013-08-06 0
2013-09-03 0
2013-10-01 0
group_c 2013-06-11 0
2013-07-02 0
2013-07-09 0
2013-07-30 0
2013-08-06 0
2013-09-03 0
2013-10-01 0