我正在尝试从Pandas的每月桶中的表中计算库存。这是表格:
Goods | Incoming | Date
-------+------------+-----------
'a' | 10 | 2014-01-10
'a' | 20 | 2014-02-01
'b' | 30 | 2014-01-02
'b' | 40 | 2014-05-13
'a' | 20 | 2014-06-30
'c' | 10 | 2014-02-10
'c' | 50 | 2014-05-10
'b' | 70 | 2014-03-10
'a' | 10 | 2014-02-10
到目前为止,这是我的代码:
import pandas as pd
df = pd.DataFrame({
'goods': ['a', 'a', 'b', 'b', 'a', 'c', 'c', 'b', 'a'],
'incoming': [0, 20, 30, 40, 20, 10, 50, 70, 10],
'date': ['2014-01-10', '2014-02-01', '2014-01-02', '2014-05-13', '2014-06-30', '2014-02-10', '2014-05-10', '2014-03-10', '2014-02-10']})
df['date'] = pd.to_datetime(df['date'])
# we don't care about year in this example
df['month'] = df['date'].map(lambda x: x.month)
dfg = df.groupby(['goods', 'month'])['incoming'].sum()
# flatten multi-index
dfg = dfg.reset_index ()
dfg['level'] = dfg.groupby(['goods'])['incoming'].cumsum()
dfg
返回
goods month incoming level
0 a 1 0 0
1 a 2 30 30
2 a 6 20 50
3 b 1 30 30
4 b 3 70 100
5 b 5 40 140
6 c 2 10 10
7 c 5 50 60
虽然这很好,但我使用的可视化方法要求(1)每组数据点数相同(“商品”),(2)时间序列的相同程度(即最早/最近一个月是所有时间序列都相同)和(3)任何时间序列中没有“缺口”(数据点的最小(月)和最大(月)之间的月份)。
我怎么能用熊猫做到这一点?注意,即使认为这种结构可能有点低效,我也想坚持一般的事情。也许可以插入一些“后处理”来填补空白。
更新
总结下面的回答,我选择这样做:
piv = dfg.pivot_table(["level"], "month", "goods")
piv = piv.reindex(np.arange(piv.index[0], piv.index[-1] + 1))
piv = piv.ffill(axis=0)
piv = piv.fillna(0)
piv.index.name = 'month'
我还添加了
piv = piv.stack()
print r.reset_index()
获取类似于输入表的表:
month goods level
0 1 a 0
1 1 b 30
2 1 c 0
3 2 a 30
4 2 b 30
5 2 c 10
6 3 a 30
7 3 b 100
8 3 c 10
9 4 a 30
10 4 b 100
11 4 c 10
12 5 a 30
13 5 b 140
14 5 c 60
15 6 a 50
16 6 b 140
17 6 c 60
答案 0 :(得分:2)
我想你想使用pivot_table
:
In [11]: df.pivot_table(values="incoming", index="month", columns="goods", aggfunc="sum")
Out[11]:
goods a b c
month
1 0 30 NaN
2 30 NaN 10
3 NaN 70 NaN
5 NaN 40 50
6 20 NaN NaN
为了获得充实的月份,你可以重新索引(这感觉有点hacky,可能有一个更简洁的方式):
In [12]: res.reindex(np.arange(res.index[0], res.index[-1] + 1))
Out[12]:
goods a b c
1 0 30 NaN
2 30 NaN 10
3 NaN 70 NaN
4 NaN NaN NaN
5 NaN 40 50
6 20 NaN NaN
这里的一个问题是月份与年份无关,可能更适合具有期间指数:
In [21]: df.pivot_table(values="incoming", index=pd.DatetimeIndex(df.date).to_period("M"), columns="goods", aggfunc="sum")
Out[21]:
goods a b c
2014-01 0 30 NaN
2014-02 30 NaN 10
2014-03 NaN 70 NaN
2014-05 NaN 40 50
2014-06 20 NaN NaN
然后您可以按期间范围重新编制索引:
In [22]: res2.reindex(pd.period_range(res2.index[0], res2.index[-1], freq="M"))
Out[22]:
goods a b c
2014-01 0 30 NaN
2014-02 30 NaN 10
2014-03 NaN 70 NaN
2014-04 NaN NaN NaN
2014-05 NaN 40 50
2014-06 20 NaN NaN
也就是说,您可以对dfg
:
In [31]: dfg.pivot_table(["incoming", "level"], "month", "goods")
Out[31]:
incoming level
goods a b c a b c
month
1 0 30 NaN 0 30 NaN
2 30 NaN 10 30 NaN 10
3 NaN 70 NaN NaN 100 NaN
5 NaN 40 50 NaN 140 60
6 20 NaN NaN 50 NaN NaN
和reindex。