Индексирование панд по парам столбцов (5-кортеж)

#python #pandas #pcap #network-flow

Вопрос:

Я пытаюсь установить идентификатор потока для сетевого 5-кортежа, исходный кадр данных выглядит так:

 tup = [['192.168.0.1', '1032', '192.168.0.2', '443'],
   ['192.168.0.1', '1032', '192.168.0.2', '443'],
   ['192.168.0.1', '1034', '192.168.0.2', '443'],
   ['192.168.0.2', '443', '192.168.0.1', '1034'],
   ['192.168.0.1', '1034', '192.168.0.2', '443'],
   ['192.168.0.1', '1034', '192.168.0.2', '443'],
   ['192.168.0.2', '443', '192.168.0.1', '1034'],
   ['192.168.0.2', '443', '192.168.0.1', '1034'],
   ['192.168.0.1', '1032', '192.168.0.2', '443'],
   ['192.168.0.2', '443', '192.168.0.1', '1032']]

df = pd.DataFrame(tup,columns=['src','src_port','dst','dst_port'])
 

Для трафика из одного и того же потока (входящего/исходящего) идентификатор потока должен быть установлен следующим образом:

 src src_port    dst dst_port    flow_id
0   192.168.0.1 1032    192.168.0.2 443 1
1   192.168.0.1 1032    192.168.0.2 443 1
2   192.168.0.1 1034    192.168.0.2 443 2
3   192.168.0.2 443 192.168.0.1 1034    2
4   192.168.0.1 1034    192.168.0.2 443 2
5   192.168.0.1 1034    192.168.0.2 443 2
6   192.168.0.2 443 192.168.0.1 1034    2
7   192.168.0.2 443 192.168.0.1 1034    2
8   192.168.0.1 1032    192.168.0.2 443 1
9   192.168.0.2 443 192.168.0.1 1032    1
 

Я преобразовал фрейм данных в значения и отсортировал их вместе, но застрял на установке правильного индекса потока.

Есть ли какой-нибудь более быстрый/элегантный способ?

Ответ №1:

Одна идея сортируется по парам — вложенным кортежам, а затем вызывается factorize :

 a = df[['src','src_port','dst','dst_port']].to_numpy()
s = [tuple(sorted(((x[0], x[1]), (x[2], x[3])))) for x in a]
df['flow_id'] = pd.factorize(s)[0]   1

print (df)
           src src_port          dst dst_port  flow_id
0  192.168.0.1     1032  192.168.0.2      443        1
1  192.168.0.1     1032  192.168.0.2      443        1
2  192.168.0.1     1034  192.168.0.2      443        2
3  192.168.0.2      443  192.168.0.1     1034        2
4  192.168.0.1     1034  192.168.0.2      443        2
5  192.168.0.1     1034  192.168.0.2      443        2
6  192.168.0.2      443  192.168.0.1     1034        2
7  192.168.0.2      443  192.168.0.1     1034        2
8  192.168.0.1     1032  192.168.0.2      443        1
9  192.168.0.2      443  192.168.0.1     1032        1