熊猫-将清单值(1、2、3)变成范围(1-3)?

时间:2020-02-19 20:34:59

标签: python pandas

有没有简单的方法来获取一定范围的数字,即(1、2、3、4、5)并将其转换为易于理解的范围(1-5)?

我正在使用IP /端口组合,并尝试列出单个IP上看到的端口范围,在单个IP上可能有50,000+端口,但是我希望能够看到类似[ 1-50,000],而不是列出每一个。

    IP  Port
0   1.1.1.1     1
1   1.1.1.1     2
2   1.1.1.1     3
3   1.1.1.1     4
4   1.1.1.1     5
5   1.1.1.1     6
6   1.1.1.1     7
7   1.1.1.1     8
8   1.1.1.1     9
9   1.1.1.1    10
10  1.1.1.1    11
11  1.1.1.1    12
12  1.1.1.1    13
13  1.1.1.1    14
14  1.1.1.2    15
15  1.1.1.2    16
16  1.1.1.2    18
17  1.1.1.2    20
18  1.1.1.2    22
19  1.1.1.2    27
20  1.1.1.3    40
21  1.1.1.3    41
22  1.1.1.3    42
23  1.1.1.3    43
24  1.1.1.3    44
25  1.1.1.3    45
26  1.1.1.3    46
27  1.1.1.3    47

//代码//

df.groupby('IP')['Port'].apply(list)

//结果//

1.1.1.1    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]  
1.1.1.2                           [15, 16, 18, 20, 22, 27]  
1.1.1.3                   [40, 41, 42, 43, 44, 45, 46, 47]  

//期望的结果//

1.1.1.1                     [1-14]  
1.1.1.2    [15-16, 18, 20, 22, 27]  
1.1.1.3                    [40-47]

1 个答案:

答案 0 :(得分:2)

这就是我要做的:

s = df.groupby('IP').Port.diff()
new_df = (df.groupby(['IP', s.ne(1).groupby(df['IP']).cumsum()])
            .Port.agg(['min','max','count'])
            .reset_index('Port', drop=True)
         )
new_df['out'] = np.where(new_df['count']==1, 
                         new_df['min'], 
                         new_df[['min','max']].astype(str).agg('-'.join, axis=1))
new_df.groupby('IP')['out'].apply(list)

输出:

IP
1.1.1.1                     [1-14]
1.1.1.2    [15-16, 18, 20, 22, 27]
1.1.1.3                    [40-47]
Name: out, dtype: object