根据列值之间的间隔对数据框进行分组

时间:2020-08-24 09:05:22

标签: python pandas dataframe grouping

假设我们有以下数据集:

Name    Num

First    1
Second   50
Third    110
Fourth   2
Fifth    58
Sixth    105
Seventh  8

我想基于 num 列的每一行之间的最大间隔(例如10)对数据帧进行分组。因此,例如,我希望拥有:

Name                   Num
First,Fourth,Seventh   1,2,8
Second,Fifth           50,58
Sixth,Third            105,110

我尝试使用Raymond Hettinger's Answer,但是我需要对数据框进行分组,而不仅是对列进行分组,因为我想在之后进行绘制。 我尝试过这个(我首先根据列对数据框进行了排序):

    for idx,val in enumerate(df_sorted['num'], start=1):
    if idx == 1:
        groups =[df_sorted.iloc[idx]]
    elif abs(data['pos'][idx] - data['pos'][idx-1]) <= 10:
        groups[-1].append(data.iloc[idx,:])
    else:
        groups.append(data.iloc[idx,:])

但是我在理解列表如何在Python中工作时遇到了一些问题(我一直在R中使用它们)。 不知道是否有使用 groupby 或其他方法(例如 Grouper 用于时间序列)的简便方法。

编辑: 最后,我使用Raymond Hettinger的答案选择以下方法来解决问题:

def cluster(data, maxgap, column):
'''Arrange data into groups where successive elements
   differ by no more than *maxgap*
'''
#data.sort() #sort data if necessary
groups = list()
groups = [[data.iloc[0,:]]]

for idx,val in enumerate(data[column]):
    if idx > 0:
        if abs(val - data[column][idx-1]) <= maxgap:
            groups[-1].append(data.iloc[idx,:])
        else:
            groups.append([data.iloc[idx,:]])
return groups

1 个答案:

答案 0 :(得分:1)

我们对数字进行装箱以计算分布,然后根据该分布对其进行分组和列出; N = 24是为您的预期结果量身定制的。对于实际操作,可能很难设置阈值。例如,对于每10个类别,50和58将是一个不同的组。

import pandas as pd
import numpy as np
import io

data = '''
Name Num
First 1
Second 50
Third 110
Fourth 2
Fifth 58
Sixth 105
Seventh 8
'''

df = pd.read_csv(io.StringIO(data), sep='\s+')

df.sort_values('Num', ascending=True, inplace=True, ignore_index=True)
N = 24
category = pd.cut(df['Num'], bins=np.arange(df['Num'].min(), df['Num'].max()+ N, N), right=False)

category.value_counts()
[1, 25)      3
[97, 121)    2
[49, 73)     2
[73, 97)     0
[25, 49)     0
Name: Num, dtype: int64

df.groupby(category).agg(list)
    Name    Num
Num     
[1, 25) [First, Fourth, Seventh]    [1, 2, 8]
[25, 49)    []  []
[49, 73)    [Second, Fifth] [50, 58]
[73, 97)    []  []
[97, 121)   [Sixth, Third]  [105, 110]