我有一个指标数据框(1包含数据,0表示不包括),名为indicator_df
,其中索引是时间序列,列是MultiIndex,如下所示:
Item0 Item1
A D A C
2014-04-02 0 1 0 1
2014-04-03 0 1 0 1
2014-04-04 1 1 0 1
此外,我有一个名为data_df
的时间序列数据框,具有相同的索引和匹配的子列
A B C D
2014-04-02 3 4 2 -3
2014-04-03 1 3 -2 1
2014-04-04 -1 -5 0 -2
我正在寻找的是一种使用列['Item0', 'Item1']
获取时间序列数据帧的简洁方法,其中每列是指标所包含数据的总和
new_df[col] = indicator_df[col].mul(data_df).sum(axis=1)
Item0 Item1
2014-04-02 -3 2
2014-04-03 1 -2
2014-04-04 -3 0
我可以循环遍历MultiIndex的第一级并连接每一列,但我觉得我应该能够在没有循环的情况下执行此操作。也许有一个聪明的小组?
答案 0 :(得分:1)
所以这是一个不太简洁的版本,但它在熊猫的成语中稍微多一些:
首先pandas.melt
您的数据。使用两个DataFrame更容易,每个DataFrame只是一些具有一些共同点的列的集合,而不是尝试和执行MultiIndex杂技。
In [127]: dfm = pd.melt(df, var_name=['items', 'labels'], id_vars=['index'], value_name='indicator')
In [128]: dfm
Out[128]:
index items labels indicator
0 2014-04-02 Item0 A 0
1 2014-04-03 Item0 A 0
2 2014-04-04 Item0 A 1
3 2014-04-02 Item0 D 1
4 2014-04-03 Item0 D 1
5 2014-04-04 Item0 D 1
6 2014-04-02 Item1 A 0
7 2014-04-03 Item1 A 0
8 2014-04-04 Item1 A 0
9 2014-04-02 Item1 C 1
10 2014-04-03 Item1 C 1
11 2014-04-04 Item1 C 1
[12 rows x 4 columns]
In [129]: df2m = pd.melt(df2, var_name=['labels'], id_vars=['index'], value_name='value')
In [130]: df2m
Out[130]:
index labels value
0 2014-04-02 A 3
1 2014-04-03 A 1
2 2014-04-04 A -1
3 2014-04-02 B 4
4 2014-04-03 B 3
5 2014-04-04 B -5
6 2014-04-02 C 2
7 2014-04-03 C -2
8 2014-04-04 C 0
9 2014-04-02 D -3
10 2014-04-03 D 1
11 2014-04-04 D -2
[12 rows x 3 columns]
现在您有两个框架,其中包含一些公共列(“标签”和“索引”),您可以在pandas.merge
中使用这些列:
In [140]: merged = pd.merge(dfm, df2m, on=['labels', 'index'], how='outer')
In [141]: merged
Out[141]:
index items labels indicator value
0 2014-04-02 Item0 A 0 3
1 2014-04-02 Item1 A 0 3
2 2014-04-03 Item0 A 0 1
3 2014-04-03 Item1 A 0 1
4 2014-04-04 Item0 A 1 -1
5 2014-04-04 Item1 A 0 -1
6 2014-04-02 Item0 D 1 -3
7 2014-04-03 Item0 D 1 1
8 2014-04-04 Item0 D 1 -2
9 2014-04-02 Item1 C 1 2
10 2014-04-03 Item1 C 1 -2
11 2014-04-04 Item1 C 1 0
12 2014-04-02 NaN B NaN 4
13 2014-04-03 NaN B NaN 3
14 2014-04-04 NaN B NaN -5
[15 rows x 5 columns]
由于indicator
实际上只是一个布尔索引器,因此删除它NaN
并将其转换为bool dtype
In [147]: merged.dropna(subset=['indicator'], inplace=True)
In [148]: merged['indicator'] = merged.indicator.copy().astype(bool)
In [149]: merged
Out[149]:
index items labels indicator value
0 2014-04-02 Item0 A False 3
1 2014-04-02 Item1 A False 3
2 2014-04-03 Item0 A False 1
3 2014-04-03 Item1 A False 1
4 2014-04-04 Item0 A True -1
5 2014-04-04 Item1 A False -1
6 2014-04-02 Item0 D True -3
7 2014-04-03 Item0 D True 1
8 2014-04-04 Item0 D True -2
9 2014-04-02 Item1 C True 2
10 2014-04-03 Item1 C True -2
11 2014-04-04 Item1 C True 0
[12 rows x 5 columns]
现在切片indicator
并使用pivot_table
获得您想要的结果:
In [150]: merged.loc[merged.indicator].pivot_table(values='value', index='index', columns=['items'], aggfunc=sum)
Out[150]:
items Item0 Item1
index
2014-04-02 -3 2
2014-04-03 1 -2
2014-04-04 -3 0
[3 rows x 2 columns]
这可能看起来很多,但那可能是因为我正在写出每一步。它相当于大约五行代码。
答案 1 :(得分:0)
这对你来说是否足够好,因为指数是相同的?
pd.DataFrame(np.array([(DF1[item]*DF2[DF[item].columns]).sum(axis=1) for item in ['Item0', 'Item1']]).T,
columns=['Item0', 'Item1'], index=DF1.index)