Pandas-将列表值(1、2、3)变成范围(1-3)?

问题描述 投票:0回答:1

是否有任何简单的方法来获取一定范围的数字,即(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]
python pandas
1个回答
0
投票

当然,像这样:

f = lambda x: '[' + str(x.min()) + '-' + str(x.max()) + ']'
df.groupby('IP')['Port'].apply(f)

输出:

IP
1.1.1.1     [1-14]
1.1.1.2    [15-27]
1.1.1.3    [40-47]
Name: Port, dtype: object

0
投票

这就是我要做的:

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
© www.soinside.com 2019 - 2024. All rights reserved.