将带有时间戳的状态列列表转换为该时间段内每个状态的时间索引列表,如Chutes和ladder所示



想象一个滑道和梯子的游戏缩减到两个没有滑道和一个梯子的贴图:

Start: [one] [two] :Finish

梯子可以带你从[1]到Finish,跳过[2]。

当一个棋子(以数字为索引)开始游戏时,我们为它创建一个时间戳。

这是一个有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,计算每个时间段内每个tile上有多少块?我希望生成的数据框看起来像这样:

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,因此使计算节省将是非常好的。

谢谢!

首先,我认为如果我们通过回填来丢弃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_countsconcat来获得当前的片段:

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

可能是一个更简单/更便宜的方法来做到这一点(如果没有,我认为这将使一个很好的功能请求熊猫)…

最新更新