Сортировка IP-адресов как наборов числовых октетов (__not__ лексикографически) - PullRequest
0 голосов
/ 10 июня 2018

Я хочу отсортировать записи в каждой строке / ячейке определенного столбца 'D' по IP-адресу в порядке возрастания.Записи хранятся в новой строке и имеют связанный протокол и порт, перечисленные в конце IP-адреса, который меня не касается сортировки только 4 октетов IP-адреса.Я чувствую, что для этого нужна какая-то рег-функция с лямбда-функцией.Иногда вместо IP-адреса может быть указано имя хоста.

Примером кадра данных может быть:

ID    A     B     C     D
1     x     x     x     10.0.0.50/TCP/50
                        192.168.1.90/TCP/51
                        server1/TCP/80
                        10.0.0.9/TCP/78
2     y     y     y     192.168.3.90/UDP/53
                        10.0.4.10/TCP/65
                        10.0.3.4/TCP/34
                        host1/UDP/80
3     z     z     z     10.0.0.40/TCP/80
                        10.0.0.41/TCP/443
                        192.168.2.70/UDP/98
                        10.0.0.9/TCP/12

Желаемый вывод будет:

ID    A     B     C     D
 1    x     x     x     10.0.0.9/TCP/78
                        10.0.0.50/TCP/50
                        192.168.1.90/TCP/51
                        server1/TCP/80                   
 2    y     y     y     10.0.3.4/TCP/34
                        10.0.4.10/TCP/65
                        192.168.3.90/UDP/53
                        host1/UDP/80
 3    z     z     z     10.0.0.9/TCP/12
                        10.0.0.40/TCP/34
                        10.0.0.41/TCP/443
                        192.168.2.70/UDP/98

В порядкеДля достижения вышеупомянутого кадра данных я сначала объединяю строку D, используя групповую передачу, которая работает, однако IP-адрес не в порядке:

df = df.groupby(['ID','A','B','C'], sort=False, as_index=False)['D'].apply('\n'.join)

Возможно, было бы более эффективно объединять и сортировать одновременно, если это возможно, а не2 отдельные команды ??

Любые мысли, которые мне очень нравятся Я посмотрел несколько примеров, но ни одна из них не подходит.Надеюсь, мои объяснения достаточно ясны, заранее спасибо за любую помощь.

1 Ответ

0 голосов
/ 10 июня 2018

при условии, что у вас есть исходный DF, до группировка:

In [70]: df
Out[70]:
     ID  A  B  C                    D
0   1.0  x  x  x     10.0.0.50/TCP/50
1   1.0  x  x  x  192.168.1.90/TCP/51
2   1.0  x  x  x       server1/TCP/80
3   1.0  x  x  x      10.0.0.9/TCP/78
4   2.0  y  y  y  192.168.3.90/UDP/53
5   2.0  y  y  y     10.0.4.10/TCP/65
6   2.0  y  y  y      10.0.3.4/TCP/34
7   2.0  y  y  y         host1/UDP/80
8   3.0  z  z  z     10.0.0.40/TCP/80
9   3.0  z  z  z    10.0.0.41/TCP/443
10  3.0  z  z  z  192.168.2.70/UDP/98
11  3.0  z  z  z      10.0.0.9/TCP/12

Опция 1: многоиндексный DF:

In [69]: (df.assign(x=df.D.replace(['/.*',r'\b(\d{1})\b',r'\b(\d{2})\b'],
    ...:                           ['',r'00\1',r'0\1'],
    ...:                           regex=True))
    ...:    .sort_values('x')
    ...:    .groupby(['ID','A','B','C'], sort=False, as_index=False)['D']
    ...:    .apply('\n'.join)
    ...:    .to_frame('D'))
    ...:
    ...:
Out[69]:
                                                           D
ID  A B C
1.0 x x x  10.0.0.9/TCP/78\n10.0.0.50/TCP/50\n192.168.1.9...
3.0 z z z  10.0.0.9/TCP/12\n10.0.0.40/TCP/80\n10.0.0.41/T...
2.0 y y y  10.0.3.4/TCP/34\n10.0.4.10/TCP/65\n192.168.3.9...

Вариант 2: обычный DF:

In [75]: (df.assign(x=df.D.replace(['/.*',r'\b(\d{1})\b',r'\b(\d{2})\b'],
    ...:                           ['',r'00\1',r'0\1'],
    ...:                           regex=True))
    ...:    .sort_values('x')
    ...:    .groupby(['ID','A','B','C'], sort=False, as_index=False)['D']
    ...:    .apply('\n'.join)
    ...:    .reset_index(name='D'))
    ...:
    ...:
Out[75]:
    ID  A  B  C                                                  D
0  1.0  x  x  x  10.0.0.9/TCP/78\n10.0.0.50/TCP/50\n192.168.1.9...
1  3.0  z  z  z  10.0.0.9/TCP/12\n10.0.0.40/TCP/80\n10.0.0.41/T...
2  2.0  y  y  y  10.0.3.4/TCP/34\n10.0.4.10/TCP/65\n192.168.3.9...

следующее может помочь понять, как это работает:

добавить виртуальный столбец x сIP-октеты с добавлением нуля:

In [71]: df.assign(x=df.D.replace(['/.*',r'\b(\d{1})\b',r'\b(\d{2})\b'],
    ...:                           ['',r'00\1',r'0\1'],
    ...:                           regex=True))
    ...:
    ...:
Out[71]:
     ID  A  B  C                    D                x
0   1.0  x  x  x     10.0.0.50/TCP/50  010.000.000.050
1   1.0  x  x  x  192.168.1.90/TCP/51  192.168.001.090
2   1.0  x  x  x       server1/TCP/80          server1
3   1.0  x  x  x      10.0.0.9/TCP/78  010.000.000.009
4   2.0  y  y  y  192.168.3.90/UDP/53  192.168.003.090
5   2.0  y  y  y     10.0.4.10/TCP/65  010.000.004.010
6   2.0  y  y  y      10.0.3.4/TCP/34  010.000.003.004
7   2.0  y  y  y         host1/UDP/80            host1
8   3.0  z  z  z     10.0.0.40/TCP/80  010.000.000.040
9   3.0  z  z  z    10.0.0.41/TCP/443  010.000.000.041
10  3.0  z  z  z  192.168.2.70/UDP/98  192.168.002.070
11  3.0  z  z  z      10.0.0.9/TCP/12  010.000.000.009

сортировка DF по виртуальному столбцу x:

In [72]: (df.assign(x=df.D.replace(['/.*',r'\b(\d{1})\b',r'\b(\d{2})\b'],
    ...:                           ['',r'00\1',r'0\1'],
    ...:                           regex=True))
    ...:    .sort_values('x'))
    ...:
    ...:
Out[72]:
     ID  A  B  C                    D                x
3   1.0  x  x  x      10.0.0.9/TCP/78  010.000.000.009
11  3.0  z  z  z      10.0.0.9/TCP/12  010.000.000.009
8   3.0  z  z  z     10.0.0.40/TCP/80  010.000.000.040
9   3.0  z  z  z    10.0.0.41/TCP/443  010.000.000.041
0   1.0  x  x  x     10.0.0.50/TCP/50  010.000.000.050
6   2.0  y  y  y      10.0.3.4/TCP/34  010.000.003.004
5   2.0  y  y  y     10.0.4.10/TCP/65  010.000.004.010
1   1.0  x  x  x  192.168.1.90/TCP/51  192.168.001.090
10  3.0  z  z  z  192.168.2.70/UDP/98  192.168.002.070
4   2.0  y  y  y  192.168.3.90/UDP/53  192.168.003.090
7   2.0  y  y  y         host1/UDP/80            host1
2   1.0  x  x  x       server1/TCP/80          server1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...