所以这里有一个不太简洁的版本,但它在 pandas 的习语中稍微多一点:
首先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 实际上只是一个布尔索引器,因此删除它的NaNs 并将其转换为 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]
这可能看起来很多,但这可能是因为我正在写出每个步骤。大约有五行代码。