Python 查找数据帧中的连续段
我有一个pandas.DataFrame,其中包含在连续时间点进行的测量。随着每次测量,被观察的系统在每个时间点都有不同的状态。因此,数据帧还包含一列,其中包含每次测量时的系统状态。状态更改比测量间隔慢得多。因此,指示状态的列可能如下所示(索引:state): 是否有一种简单的方法来检索连续相等状态的每一段的索引。这意味着我想得到这样的东西:Python 查找数据帧中的连续段,python,pandas,Python,Pandas,我有一个pandas.DataFrame,其中包含在连续时间点进行的测量。随着每次测量,被观察的系统在每个时间点都有不同的状态。因此,数据帧还包含一列,其中包含每次测量时的系统状态。状态更改比测量间隔慢得多。因此,指示状态的列可能如下所示(索引:state): 是否有一种简单的方法来检索连续相等状态的每一段的索引。这意味着我想得到这样的东西: [[1,2,3,4], [5,6,7,8], [9,10,11,12,13]] 结果也可能与普通列表不同 到目前为止,我能想到的唯一解决方案是手动迭代行
[[1,2,3,4], [5,6,7,8], [9,10,11,12,13]]
结果也可能与普通列表不同
到目前为止,我能想到的唯一解决方案是手动迭代行,查找段更改点并从这些更改点重建索引,但我希望有一个更简单的解决方案。您可以使用np.diff()测试段开始/结束的位置,并迭代这些结果。这是一个非常简单的解决方案,因此可能不是最有效的解决方案
a = np.array([3,3,3,3,3,4,4,4,4,4,1,1,1,1,4,4,12,12,12])
prev = 0
splits = np.append(np.where(np.diff(a) != 0)[0],len(a)+1)+1
for split in splits:
print np.arange(1,a.size+1,1)[prev:split]
prev = split
结果:
[1 2 3 4 5]
[ 6 7 8 9 10]
[11 12 13 14]
[15 16]
[17 18 19]
一艘班轮:
df.reset_index().groupby('A')['index'].apply(np.array)
代码,例如:
In [1]: import numpy as np
In [2]: from pandas import *
In [3]: df = DataFrame([3]*4+[4]*4+[1]*4, columns=['A'])
In [4]: df
Out[4]:
A
0 3
1 3
2 3
3 3
4 4
5 4
6 4
7 4
8 1
9 1
10 1
11 1
In [5]: df.reset_index().groupby('A')['index'].apply(np.array)
Out[5]:
A
1 [8, 9, 10, 11]
3 [0, 1, 2, 3]
4 [4, 5, 6, 7]
您还可以直接从groupby对象访问信息:
In [1]: grp = df.groupby('A')
In [2]: grp.indices
Out[2]:
{1L: array([ 8, 9, 10, 11], dtype=int64),
3L: array([0, 1, 2, 3], dtype=int64),
4L: array([4, 5, 6, 7], dtype=int64)}
In [3]: grp.indices[3]
Out[3]: array([0, 1, 2, 3], dtype=int64)
为了解决DSM提到的情况,您可以采取以下措施:
In [1]: df['block'] = (df.A.shift(1) != df.A).astype(int).cumsum()
In [2]: df
Out[2]:
A block
0 3 1
1 3 1
2 3 1
3 3 1
4 4 2
5 4 2
6 4 2
7 4 2
8 1 3
9 1 3
10 1 3
11 1 3
12 3 4
13 3 4
14 3 4
15 3 4
现在按两列分组并应用lambda函数:
In [77]: df.reset_index().groupby(['A','block'])['index'].apply(np.array)
Out[77]:
A block
1 3 [8, 9, 10, 11]
3 1 [0, 1, 2, 3]
4 [12, 13, 14, 15]
4 2 [4, 5, 6, 7]
这假设值不会在不连续的段中重复——例如,
DataFrame([3]*4+[4]*4+[1]*4+[3]*4,columns=['A'])
将把两组3放入同一组。您可以扫描这些中断,但这只是原始问题的另一个版本。也许有一种方法可以让pandasgroupby
的行为更像itertools.groupby
。谢谢,您的第二个解决方案很好。实际上,我有DSM所描述的情况。如果您希望按某种偏差进行分组(例如,组中包含的值,所有值都在原始集合中相邻值的+-1范围内)@ryanjdillon您可以尝试df['block']=(df.A.diff(1.abs()>1.cumsum()
)。但这只是检查相邻值之间的差异,因此如果您使用数据帧([3]*4+[4]*4+[5]*1+[6]*3,columns=['A']])
,它仍然只会生成一个块。值得注意的是,您实际上不需要那里的“astype(int)”——熊猫正好可以对布尔值求和。谢谢,实际上,Zelazny7的解决方案更方便,因为我喜欢将数据段存储在数据帧中,它会自动实现这一点。谢谢Rutgernp.diff()
在这里是一个很好的建议。
In [77]: df.reset_index().groupby(['A','block'])['index'].apply(np.array)
Out[77]:
A block
1 3 [8, 9, 10, 11]
3 1 [0, 1, 2, 3]
4 [12, 13, 14, 15]
4 2 [4, 5, 6, 7]