【问题标题】:How to split pandas dataframe using periodic values column如何使用周期性值列拆分熊猫数据框
【发布时间】:2018-09-12 08:14:13
【问题描述】:

我有一个看起来像这样的 pandas 数据框:

v1  v2  v3  result
0  12  31  31       0
1  34  52   4       1
2  32   4   5       1
3   7  89   2       0
4   5  17   8       1
5  11  25  23       1
6   2  32  34       1
7   0   1   3       0

您可能会注意到,在最后一列中,它有一个由 0 和 1 组成的模式。 是否可以将这个数据框拆分为两个子数据框?

我想要的输出是:

df1:

v1  v2  v3  result
0  34  52   4       1
1  32   4   5       1

df2:

0   5  17   8       1
1  11  25  23       1
2   2  32  34       1

df.groupby() 肯定不行,因为它只会创建两个大数据框;一个带一,第二个带零。我对将数据标记为零不感兴趣。

提前致谢!

PS。 实际上这个数据框要大得多,所以我正在尝试创建 df1, df2, ... dfn

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    你可以创建dictionary of DataFrames:

    mask = df['result'].eq(1)
    a = pd.factorize(df['result'].eq(0).cumsum()[mask])[0]
    dfs = dict(tuple(df[mask].groupby(a)))
    print (dfs[0])
       v1  v2  v3  result
    1  34  52   4       1
    2  32   4   5       1
    
    print (dfs[1])
       v1  v2  v3  result
    4   5  17   8       1
    5  11  25  23       1
    6   2  32  34       1
    

    详情

    eq (==) 过滤创建布尔掩码:

    mask = df['result'].eq(1)
    print (mask)
    0    False
    1     True
    2     True
    3    False
    4     True
    5     True
    6     True
    7    False
    Name: result, dtype: bool
    

    通过比较0Series.cumsum来创建计数器Series

    print (df['result'].eq(0).cumsum())
    0    1
    1    1
    2    1
    3    2
    4    2
    5    2
    6    2
    7    3
    Name: result, dtype: int32
    

    仅按boolean indexing 过滤1 行:

    print (df['result'].eq(0).cumsum()[mask])
    1    1
    2    1
    4    2
    5    2
    6    2
    Name: result, dtype: int32
    

    添加factorize 用于按0 分级的组:

    a  = pd.factorize(df['result'].eq(0).cumsum()[mask])[0]
    print (a)
    [0 0 1 1 1]
    

    groupby 对象创建字典,还可以通过布尔掩码过滤行:

    dfs = dict(tuple(df[mask].groupby(a)))
    print (dfs)
    {0:    v1  v2  v3  result
    1  34  52   4       1
    2  32   4   5       1, 1:    v1  v2  v3  result
    4   5  17   8       1
    5  11  25  23       1
    6   2  32  34       1}
    

    【讨论】:

      【解决方案2】:
      # Flag the rows that will be the beginning of a new dataframe
      df['_start_new_gp'] = (df.result == 1) & (df.result.shift() == 0)
      
      # Get rigs of the results = 0 (here creating a copy - not necessary)
      df2 = df[df.result == 1].copy()
      
      # Use a cumulative sum on the '_start_new_gp' column to create a "group number"
      df2['_group_number'] = df2['_start_new_gp'].cumsum()
      
      # Group by "group number"
      grouped = df2.groupby('_group_number')
      
      # Get list of dataframes
      dataframes = [group for _, group in grouped]
      

      【讨论】:

        【解决方案3】:

        使用 numpy.split

        s = df.loc[df.result.eq(1)]
        idx = np.where(np.diff(s.index)!=1)[0] + 1
        
        for d in np.split(s, idx):
            print(d, end='\n\n')
        

           v1  v2  v3  result
        1  34  52   4       1
        2  32   4   5       1
        
           v1  v2  v3  result
        4   5  17   8       1
        5  11  25  23       1
        6   2  32  34       1
        

        【讨论】:

          猜你喜欢
          • 2019-01-19
          • 2019-05-29
          • 1970-01-01
          • 2022-11-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-07-15
          • 2018-07-01
          相关资源
          最近更新 更多