python - 按 Multiindex 级别 2 上的位置对 pandas 数据帧进行切片

标签 python pandas

我有一个带有 MultiIndex 的 pandas DataFrame,如下所示:

>>> import pandas as pd
>>> category = ['bar', 'bar', 'bar', 'bar', 'bar', 'baz', 'baz', 'baz', 'baz',
                'baz', 'baz', 'foo', 'foo', 'foo']
>>> timestamp = ['2017-01-01 09:00:00', '2017-01-01 09:01:00', '2017-01-01 09:02:00', 
                '2017-01-01 09:03:00', '2017-01-01 09:04:00', '2016-11-18 03:18:00', 
                '2016-11-18 03:19:00', '2016-11-18 03:20:00', '2016-11-18 03:21:00', 
                '2016-11-18 03:22:00', '2016-11-18 03:23:00', '2017-02-03 20:39:00', 
                '2017-02-03 20:40:00', '2017-02-03 20:41:00']
>>> values = [1,1,2,2,2,35,3,3,4,4,4,28,28,28]
>>> tuples = list(zip(*[category,timestamp]))
>>> index = pd.MultiIndex.from_tuples(tuples, names=['category', 'timestamp'])
>>> df = pd.DataFrame(values,index=index,columns=['values'])
>>> df
                                  values
category timestamp                  
bar      2017-01-01 09:00:00       1
         2017-01-01 09:01:00       1
         2017-01-01 09:02:00       2
         2017-01-01 09:03:00       2
         2017-01-01 09:04:00       2
baz      2016-11-18 03:18:00      35
         2016-11-18 03:19:00       3
         2016-11-18 03:20:00       3
         2016-11-18 03:21:00       4
         2016-11-18 03:22:00       4
         2016-11-18 03:23:00       4
foo      2017-02-03 20:39:00      28
         2017-02-03 20:40:00      28
         2017-02-03 20:41:00      28

对于每个类别,我想找到值列变化次数的累积和,如下所示:

                              values changed  cum_changes
category timestamp                                       
bar      2017-01-01 09:00:00       1   False            0
         2017-01-01 09:01:00       1   False            0
         2017-01-01 09:02:00       2    True            1
         2017-01-01 09:03:00       2   False            1
         2017-01-01 09:04:00       2   False            1
baz      2016-11-18 03:18:00      35   False            0
         2016-11-18 03:19:00       3    True            1
         2016-11-18 03:20:00       3   False            1
         2016-11-18 03:21:00       4    True            2
         2016-11-18 03:22:00       4   False            2
         2016-11-18 03:23:00       4   False            2
foo      2017-02-03 20:39:00      28   False            0
         2017-02-03 20:40:00      28   False            0
         2017-02-03 20:41:00      28   False            0

我尝试这样做:

df["changes"] = False
df.iloc[idx[:,1:],1] = df.iloc[idx[:,1:],0] == df.iloc[idx[:,:-1],0]   #This doesn't work
df["cum_changes"] = df["changed"].groupby(level=[0]).cumsum().astype(int)

但不幸的是第二行不起作用。它类似于使用 loc 按值进行多重索引的方式,但显然 iloc 不会以相同的方式处理多重索引。我无法按标签索引,因为每个组中的时间戳都不同,并且我无法使用 head() 因为每个组的长度不同。是否可以在 MultiIndex 的第二层上进行位置索引?

我真正需要的是“cum_changes”列,“changed”列只是一个中间步骤。如果有不同的方法来计算“cum_changes”列,我有兴趣听到它。我知道这可以通过迭代类别列来完成,但似乎应该可以保持这个向量化,所以我正在寻找一个不涉及循环的解决方案。

我发现了这个相关的问题,但我不相信它适用,因为解决方案实际上并不是按位置索引,而是查找与给定位置相对应的标签并按标签索引: Slice MultiIndex pandas DataFrame by position

最佳答案

您可以使用diff()作为@Psidom has already said in the comment :

In [25]: df['x'] = df.groupby(level=0)['values'] \
                     .apply(lambda x: x.diff().fillna(0).ne(0).cumsum())

In [26]: df
Out[26]:
                              values  x
category timestamp
bar      2017-01-01 09:00:00       1  0
         2017-01-01 09:01:00       1  0
         2017-01-01 09:02:00       2  1
         2017-01-01 09:03:00       2  1
         2017-01-01 09:04:00       2  1
baz      2016-11-18 03:18:00      35  0
         2016-11-18 03:19:00       3  1
         2016-11-18 03:20:00       3  1
         2016-11-18 03:21:00       4  2
         2016-11-18 03:22:00       4  2
         2016-11-18 03:23:00       4  2
foo      2017-02-03 20:39:00      28  0
         2017-02-03 20:40:00      28  0
         2017-02-03 20:41:00      28  0

关于python - 按 Multiindex 级别 2 上的位置对 pandas 数据帧进行切片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42635076/

相关文章:

python - 从股票数据中获取每天第一笔交易的时间

python - 使用 Scipy 在 Python 中进行方差分析,无需手动输入每个组名称

python - 将 "unknown format"字符串转换为日期时间对象?

python - 修改现有的 pandas DataFrame 并添加/删除列

python-3.x - 是否可以使用 pandas 和/或 pyreadstat 分块读取大型 SPSS 文件,或者是否存在替代方案?

python - 运行主循环时读取 tmx 文件(用于 pygame)

python - 我可以使用 C 模块绕过 python GIL 吗?

python - 根据现有列分配 True/False 条件

python - 过滤数据帧值

python - 在数据框中搜索子字符串并替换它