想象一下,Chutes and Ladders游戏减少到两个没有滑槽和一个梯子的瓷砖:
Start: [one] [two] :Finish
梯子可以带你从[一]到完成,跳过瓦片[两]。
当一个游戏块(由数字索引)开始游戏时,我们会在它进入该区块时为其创建时间戳。
这是一款包含4款游戏的游戏:
In [1]: df
Out[1]:
one two Finish
1 2014-01-01 2014-01-02 2014-01-03
2 2014-01-02 2014-01-06 2014-01-08
3 2014-01-02 NaT 2014-01-05
4 2014-01-02 2014-01-07 2014-01-09
如何将其转换为时间索引的DataFrame,用于计算每个时间段内每个磁贴上的碎片数量?我希望结果数据框看起来像这样:
In [2]: new_df
Out[2]:
one two
2014-01-01 1 0
2014-01-02 3 1
2014-01-03 3 0
2014-01-04 3 0
2014-01-05 2 0
2014-01-06 1 1
2014-01-07 0 2
2014-01-08 0 1
2014-01-09 0 0
当我正在处理一个(非常大的,1MM +行,十二列)DataFrame时,使这个计算节俭的人会非常精彩。
谢谢!
答案 0 :(得分:0)
首先,我认为如果我们通过回填扔掉NaTs会使这个问题变得容易一些(我们可以认为这是一个部分是两个然后立即在Finish中):
In [11]: df = df.bfill(axis=1)
In [12]: df
Out[12]:
one two Finish
1 2014-01-01 2014-01-02 2014-01-03
2 2014-01-02 2014-01-06 2014-01-08
3 2014-01-02 2014-01-05 2014-01-05
4 2014-01-02 2014-01-07 2014-01-09
现在我们可以使用value_counts
然后concat
来获取当前的片段:
In [12]: ones = df['one'].value_counts()
twos = df['two'].value_counts()
finished = df['Finish'].value_counts()
我们必须手动更改名称,因为不要传播(但......)。
In [13]: ones.name, twos.name, finished.name = 'one', 'two', 'Finish'
In [14]: counts = pd.concat([ones, twos, finished], axis=1)
In [15]: counts
Out[15]:
one two Finish
2014-01-01 1 NaN NaN
2014-01-02 3 1 NaN
2014-01-03 NaN NaN 1
2014-01-05 NaN NaN 1
2014-01-06 NaN 1 NaN
2014-01-07 NaN 1 NaN
2014-01-08 NaN NaN 1
2014-01-09 NaN NaN 1
In [16]: total = counts.fillna(0).cumsum()
In [17]: total
Out[17]:
one two Finish
2014-01-01 1 0 0
2014-01-02 4 1 0
2014-01-03 4 1 1
2014-01-05 4 2 2
2014-01-06 4 3 2
2014-01-07 4 4 2
2014-01-08 4 4 3
2014-01-09 4 4 4
现在,您可以通过查看列差异来获取所需的DataFrame:
In [18]: pd.DataFrame({'one': total['one'] - total['two'],
'two': total['two'] - total['Finish']})
Out[18]:
one two
2014-01-01 1 0
2014-01-02 3 1
2014-01-03 3 0
2014-01-05 2 0
2014-01-06 1 1
2014-01-07 0 2
2014-01-08 0 1
2014-01-09 0 0
可能是一种更简单/更便宜的方法(如果没有,我认为这会对pandas做出很好的功能请求)......