熊猫:如果连续编号,按索引查找组

时间:2017-06-21 23:37:04

标签: python pandas

我正在尝试从查看索引的df2数据帧(第一列或零列df2 [0])中找到具有开始值和结束值(即行)的元组列表。 df2例子:

COL0  COL1 COL2
  4    x    y    # start 'tuple x' of COL1
  5    i    j
  6    n    m    # end 'tuple n'
 14    f    a    # start 'tuple f'
 15    e    b    # end 'tuple e'
 ...

因此COL0连续值将形成一个组。如果下一行不连续(例如6-14),则开始新组。选择可能如下:

Crit_a = df2[0][0] + 1 == df2[0][1]

作为输出,我正在寻找每行新的df3:

COL0  COL1 COL2 COL3 COL4 ...
  4    x    y    n    m   # start values and end values of COL1 and COL2
 14    f    a    e    b

我正在查看SO here和其他位置。 谢谢你的建议。

2 个答案:

答案 0 :(得分:1)

首先为属于同一组的行创建一个组密钥。

df['COL0'] = \
    (df.COL0.rolling(2,min_periods=1)
        .apply(lambda x: x[-1] if int(x[-1]-x[0])!=1 else np.nan)
        .ffill()
    )

然后按键分组并找到开始和结束行并将它们展开为列。最后重命名列。

df2 = \
    (df[['COL1','COL2']].groupby(df.COL0)
        .apply(lambda x: np.array([x.iloc[0],x.iloc[-1]]).flatten())
        .apply(pd.Series)
        .rename_axis(lambda x: 'COL'+str(x+1),axis=1)
    )


df2
Out[178]: 
     COL1 COL2 COL3 COL4
COL0                    
4.0     x    y    n    m
14.0    f    a    e    b

答案 1 :(得分:1)

不完全是您想要的输出,但可能更直观?

我创建了一个名为group_no的列来标记来自COL0的连续值。我区分了列,找到了这个差异不是1的值,然后在结果上做了一个cumsum。第一个元素是不明确的(当差异时它是NaN,所以我检查它的值是否等于第二个值。如果是这样,第一个值是连续的并且赋值为1.如果不是,则它不是连续的并且分配了一个值为0.

df = df.assign(group_no = (df.COL0.diff() != 1).cumsum())
df.group_no.iat[0] = 1 if df.COL0.iat[0] + 1 == df.COL0.iat[1] else 0
df_new = df.groupby('group_no').agg(
    {'COL0': ['first'], 
     'COL1': ['first', 'last'], 
     'COL2': ['first', 'last']})
>>> df_new
          COL2       COL0  COL1     
         first last first first last
group_no                            
1            y    m     4     x    n
2            a    b    14     f    e

agg函数采用字典,因此列的结果顺序可以是任意的。要对结果列进行排序,您可以明确地执行此操作,例如:

df_new[[('COL0', 'first'),
        ('COL1', 'first'),
        ('COL1', 'last'),
        ('COL2', 'first'),
        ('COL2', 'last')]]

这也可能有效:

n = 3  # First three columns of original dataframe.
df_new.loc[:, pd.IndexSlice[df.columns[:n], :]]