【问题标题】:Group by consecutive index numbers按连续索引号分组
【发布时间】:2020-01-02 22:32:19
【问题描述】:

我想知道是否有办法对连续的索引号进行分组并将组移动到不同的列中。这是我正在使用的 DataFrame 的示例:

                 0
0     19218.965703
1     19247.621650
2     19232.651322
9     19279.216956
10    19330.087371
11    19304.316973

我的想法是按顺序索引号分组并得到如下结果:

                 0             1
0     19218.965703  19279.216956    
1     19247.621650  19330.087371
2     19232.651322  19304.316973

我一直在尝试将我的数据按 3 块然后按 groupby 拆分,但我正在寻找更多可用于分组和重新排列顺序索引号的东西。 谢谢!

【问题讨论】:

  • #maybe df['v_col'].values.reshape(-1,3).T
  • 这是转置的好方法,但是我想避免设置边界 (-1, 3),以防我有更大的连续 idx 数字要分组。 @anky_91 回复是我问题的答案。谢谢!

标签: python pandas numpy group-by


【解决方案1】:

我认为您已经假设每个连续组中的观察次数相同。我的做法是:

准备数据:

import pandas as pd
import numpy as np

df = pd.DataFrame(data ={'data':[19218.965703 ,19247.621650 ,19232.651322 ,19279.216956 ,19330.087371 ,19304.316973]}, index = [0,1,2,9,10,11] )

以及解决方案:

df['Group'] = (df.index.to_series()-np.arange(df.shape[0])).rank(method='dense')
df.reset_index(inplace=True)
df['Observations'] = df.groupby(['Group'])['index'].rank()
df.pivot(index='Observations',columns='Group', values='data')

返回:

Group                  1.0           2.0
Observations                            
1.0           19218.965703  19279.216956
2.0           19247.621650  19330.087371
3.0           19232.651322  19304.316973

【讨论】:

    【解决方案2】:

    我的方式:

    df['groups']=list(df.reset_index()['index']-range(0,len(df)))
    pd.concat([df[df['groups']==i][['0']].reset_index(drop=True) for i in df['groups'].unique()],axis=1)
    
                  0             0
    0  19218.965703  19279.216956
    1  19247.621650  19330.087371
    2  19232.651322  19304.316973
    

    【讨论】:

      【解决方案3】:

      用新的pandas.MultiIndex 创建一个新的pandas.Series

      a = pd.factorize(df.index - np.arange(len(df)))[0]
      b = df.groupby(a).cumcount()
      
      pd.Series(df['0'].to_numpy(), [b, a]).unstack()
      
                    0             1
      0  19218.965703  19279.216956
      1  19247.621650  19330.087371
      2  19232.651322  19304.316973
      

      类似但有更多 Numpy

      a = pd.factorize(df.index - np.arange(len(df)))[0]
      b = df.groupby(a).cumcount()
      
      c = np.empty((b.max() + 1, a.max() + 1), float)
      c.fill(np.nan)
      c[b, a] = np.ravel(df)
      pd.DataFrame(c)
      
                    0             1
      0  19218.965703  19279.216956
      1  19247.621650  19330.087371
      2  19232.651322  19304.316973
      

      【讨论】:

        【解决方案4】:

        这是groupby + pivot_table


        m = df.index.to_series().diff().ne(1).cumsum()
        
        (df.assign(key=df.groupby(m).cumcount())
            .pivot_table(index='key', columns=m, values=0))
        

                        1             2
        key
        0    19218.965703  19279.216956
        1    19247.621650  19330.087371
        2    19232.651322  19304.316973
        

        【讨论】:

          【解决方案5】:

          一种来自pandasgroupby的方式

          s=df.index.to_series().diff().ne(1).cumsum()
          pd.concat({x: y.reset_index(drop=True) for x, y in df['0'].groupby(s)}, axis=1)
          
          Out[786]: 
                        1             2
          0  19218.965703  19279.216956
          1  19247.621650  19330.087371
          2  19232.651322  19304.316973
          

          【讨论】:

            【解决方案6】:

            这是一种方法:

            from more_itertools import consecutive_groups
            final=pd.concat([df.loc[i].reset_index(drop=True) 
                                for i in consecutive_groups(df.index)],axis=1)
            final.columns=range(len(final.columns))
            print(final)
            

                          0             1
            0  19218.965703  19279.216956
            1  19247.621650  19330.087371
            2  19232.651322  19304.316973
            

            【讨论】:

            • 我喜欢 more_itertools 解决方案!谢谢你。用 3 个答案,你们涵盖了所有可能和优雅的解决方案!
            猜你喜欢
            • 2017-11-25
            • 2018-04-09
            • 2018-11-27
            • 2019-01-04
            • 2021-04-27
            • 2016-08-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多