我有一个名为df
的Pandas DataFrame,其列名为“ step”,它只是一个增量计数器(1、2、3、4等):
step col1 col2
1 2 3
2 3 5
3 1 0
4 8 9
5 2 3
我正在从
df
选择一些感兴趣的行: work_df = df[df[col1] < df[col2]]
step col1 col2
1 2 3
2 3 5
4 8 9
5 2 3
现在,我应该通过“ step”的连续性将
work_df
拆分为一些sub_df(即,如果work_df['step'] == [1,2,3,7,8,9]
则[1,2,3]
属于sub_df_1
而[7,8,9]
属于sub_df_2
等),目前我正在这样做这条路: for idx, row in work_df.iterrows():
if row['step'] > prev_step + 1:
if step_count > 1: #don't want to have df with only 1 row
interval_list.append({'step_count': step_count ... })
step_count = 0
else:
step_count += 1
prev_step = row['step']
我正在根据来自
interval_list
的信息构建新的sub_df。但是我不确定这是否是实现我真正需要的最佳方法:sub_df1=
step col1 col2
1 2 3
2 3 5
sub_df2=
step col1 col2
4 8 9
5 2 3
是否有更好的方法通过列的连续性拆分DataFrame?
最佳答案
您可以在此处按(df[col] != df[col].shift(1)+1).cumsum()
分组,也可以按@MarkWang says df['data'].diff().ne(1).cumsum()
分组。确实,如果我们使用您的样本数据:
>>> df
data
0 1
1 2
2 3
3 7
4 8
5 9
那么此表达式将产生:
>>> df['data'].diff().ne(1).cumsum()
0 1
1 1
2 1
3 2
4 2
5 2
Name: data, dtype: int64
因此,我们可以在这些值上执行
groupby
:>>> list(df.groupby(df['data'].diff().ne(1).cumsum()))
[(1, data
0 1
1 2
2 3), (2, data
3 7
4 8
5 9)]
因此,我们这里有两组:
[1,2,3]
和[7,8,9]
。因此,您可以在这里获得两个组:>>> (__, sub_df_1), (__, sub_df_2) = df.groupby(df['data'].diff().ne(1).cumsum())
>>> sub_df_1
data
0 1
1 2
2 3
>>> sub_df_2
data
3 7
4 8
5 9
或您提供的第二个样本数据片段:
>>> (__, sub_df1), (__, sub_df2) = df2.groupby(df2['data'].diff().ne(1).cumsum())
>>> sub_df1
step col1 col2
0 1 2 3
1 2 3 5
>>> sub_df2
step col1 col2
2 4 8 9
3 5 2 3
例如,您可以在此处使用列表推导或
itemgetter
来获取相应的组。例如:>>> [g[1] for g in df2.groupby(df2['step'].diff().ne(1).cumsum())]
[ step col1 col2
0 1 2 3
1 2 3 5, step col1 col2
2 4 8 9
3 5 2 3]
您也可以使用
1
删除长度的组:>>> [g[1] for g in df2.groupby(df2['step'].diff().ne(1).cumsum()) if len(g[1]) > 1]
[ step col1 col2
0 1 2 3
1 2 3 5, step col1 col2
2 4 8 9
3 5 2 3]
因此,此列表包含两个子组。我强烈建议不要按名称分配。是的,它是strictly speaking possible。但这是一种反模式,通常弊大于利。
关于python - 如何检查DataSeries的连续性?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57539975/