在两者之间切片的pandas数据帧

时间:2015-06-11 15:54:22

标签: pandas subset slice

我有一个pandas数据框,其中一列标记了另一列中有趣的数据点(例如,峰和谷的位置)。我经常需要对每个标记之间的值进行一些计算。是否有一种利用标记作为端点切割数据帧的简洁方法,以便我可以在每个切片上运行一个函数?数据框看起来像这样,标有所需的切片:

   numbers     markers
0  0.632009    None
1  0.733576    None    # Slice 1 (0,1,2)
2  0.585944       x    _________
3  0.212374    None
4  0.491948    None    
5  0.324899    None    # Slice 2 (3,4,5,6)
6  0.389103       y    _________
7  0.638451    None
8  0.123557    None    # Slice 3 (7,8,9)
9  0.588472       x    _________

我当前的方法是创建标记出现的索引数组,使用值对数据帧进行切片迭代此数组,然后将这些切片附加到列表中。我最终得到了一个numpy数组列表,然后我可以将函数应用于:

import pandas as pd
df = pd.DataFrame({'numbers':np.random.rand(10),'markers':[None,None,'x',None,None,None,'y',None,None,'x']})

index_array = df[df.markers.isin(['x', 'y'])].index  # returns an array of xy indices    
slice_list = []

prev_i = 0  # first slice of the dataframe needs to start from index 0
for i in index_array:
    new_slice = df.numbers[prev_i:i+1].values  # i+1 to include the end marker in the slice
    slice_list.append(new_slice)
    prev_i = i+1  # excludes the start marker in the next slice

for j in slice_list:
    myfunction(j)

这是有效的,但我想知道是否有更惯用的方法使用花哨的索引/分组/旋转或我缺少的东西? 我已经看过使用groupby,但这不起作用,因为在markers列上的分组只返回标记所在的行,而多索引和数据透视表需要唯一标签。我不会打扰,除了大熊猫有几乎所有东西的工具,所以我的期望可能不合理。

我不喜欢以数组列表结束,这只是我找到的解决方案。如果能让事情变得更容易,我对于从一开始就改变我构建数据的方式的建议非常开放。

1 个答案:

答案 0 :(得分:2)

您可以使用compare-cumsum-groupby模式的变体来执行此操作。从

开始
>>> df["markers"].isin(["x","y"])
0    False
1    False
2     True
3    False
4    False
5    False
6     True
7    False
8    False
9     True
Name: markers, dtype: bool

我们可以转移并获取累计金额:

>>> df["markers"].isin(["x","y"]).shift().fillna(False).cumsum()
0    0
1    0
2    0
3    1
4    1
5    1
6    1
7    2
8    2
9    2
Name: markers, dtype: int64

之后groupby按您的意愿工作:

>>> group_id = df["markers"].isin(["x","y"]).shift().fillna(False).cumsum()
>>> for k,g in df.groupby(group_id):
...     print(k)
...     print(g)
...     
0
    numbers markers
0  0.632009    None
1  0.733576    None
2  0.585944       x
1
    numbers markers
3  0.212374    None
4  0.491948    None
5  0.324899    None
6  0.389103       y
2
    numbers markers
7  0.638451    None
8  0.123557    None
9  0.588472       x