在 pandas 数据帧之间切片行
Slicing rows of pandas dataframe between
我有一个 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)
这行得通,但我想知道是否有更惯用的方法使用 fancy indexing/grouping/pivoting 或我缺少的东西?
我看过使用 groupby,但这不起作用,因为仅在标记列上分组 returns 标记所在的行,并且多索引和数据透视表需要唯一标签。我不会费心去问,除非 pandas 有一个几乎所有的工具,所以我的期望可能高得离谱。
我并不局限于以数组列表结尾,那只是我找到的解决方案。我非常愿意接受关于从一开始就改变我构建数据的方式的建议,如果这能让事情变得更容易的话。
您可以使用 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
我有一个 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)
这行得通,但我想知道是否有更惯用的方法使用 fancy indexing/grouping/pivoting 或我缺少的东西? 我看过使用 groupby,但这不起作用,因为仅在标记列上分组 returns 标记所在的行,并且多索引和数据透视表需要唯一标签。我不会费心去问,除非 pandas 有一个几乎所有的工具,所以我的期望可能高得离谱。
我并不局限于以数组列表结尾,那只是我找到的解决方案。我非常愿意接受关于从一开始就改变我构建数据的方式的建议,如果这能让事情变得更容易的话。
您可以使用 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