如何检查DataSeries的连续性?

时间:2019-08-17 21:13:44

标签: python pandas

我有一个名为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?

1 个答案:

答案 0 :(得分:1)

您可以在此处按(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。但这是一种反模式,通常弊大于利。