根据组的频率计数添加新列

时间:2017-09-05 07:37:47

标签: python pandas dataframe group-by

如果我的标题不是很具描述性,请道歉。但这正是我想要实现的目标: -

我有一个包含2个字段的数据帧,即用于tcp流量的src端口和目标端口。数据框的csv转储看起来像这样: -

srcp    dstp
55647    22
22       55670
2222    56354
55670   22
55670   22
2222    56354
56362   139
22      55670
22      55670
56354   2222
22      55670
56354   2222

coln 1是src端口,coln 2是目标端口。

我想查看对src端口 - 目标端口并获取它们的频率并将其存储在新的coln频率中。换句话说,对于上面的例子,我想这样做: -

  55647 22    1
  22   55670  6
  2222 56354  4
  55670 22    6
  55670 22    6
  2222  56354 4
  56362 139   1
  22    55670 6
  22    55670 6
  56354 2222  4
  22    55670 6
  56354 2222  4

正如您所看到的,端口2222-5634的频率为4(因为流量可以在任一方向流动,因此它们需要被识别为一个连接),因此在对应于的频率coln单元中重复值4目标/ src端口中的值2222-56354。

由于仍然在python中攀爬阶梯,我想知道如何实现这一目标。

3 个答案:

答案 0 :(得分:1)

首先按numpy.sort对每行的所有值进行排序,然后使用groupby函数transformsize进行排序:

注意sizecount之间的差异为count不计NaN个值。

df['a'] = pd.DataFrame(np.sort(df.values, 1)).groupby([0,1])[0].transform('size')
print (df)
     srcp   dstp  a
0   55647     22  1
1      22  55670  6
2    2222  56354  4
3   55670     22  6
4   55670     22  6
5    2222  56354  4
6   56362    139  1
7      22  55670  6
8      22  55670  6
9   56354   2222  4
10     22  55670  6
11  56354   2222  4

类似:

df['a'] =  pd.DataFrame(np.sort(df.values, 1))
             .groupby(list(range(len(df.columns))))[0]
             .transform('size')
print (df)

     srcp   dstp  a
0   55647     22  1
1      22  55670  6
2    2222  56354  4
3   55670     22  6
4   55670     22  6
5    2222  56354  4
6   56362    139  1
7      22  55670  6
8      22  55670  6
9   56354   2222  4
10     22  55670  6
11  56354   2222  4

答案 1 :(得分:1)

选项1

使用np.sort,但没有df.apply

df['freq'] = pd.DataFrame(np.sort(df.values, 1), columns=df.columns)\
                       .groupby(['srcp', 'dstp'])['srcp'].transform('count')
df

     srcp   dstp  freq
0   55647     22     1
1      22  55670     6
2    2222  56354     4
3   55670     22     6
4   55670     22     6
5    2222  56354     4
6   56362    139     1
7      22  55670     6
8      22  55670     6
9   56354   2222     4
10     22  55670     6
11  56354   2222     4

选项2

您还可以使用frozenset s

解决此问题
df2 = df.apply(frozenset, 1).reset_index()    
s = df2.groupby(df2.columns[-1]).index.transform('count')
print(s)

0     1
1     6
2     4
3     6
4     6
5     4
6     1
7     6
8     6
9     4
10    6
11    4

df['freq'] = s
df

     srcp   dstp  freq
0   55647     22     1
1      22  55670     6
2    2222  56354     4
3   55670     22     6
4   55670     22     6
5    2222  56354     4
6   56362    139     1
7      22  55670     6
8      22  55670     6
9   56354   2222     4
10     22  55670     6
11  56354   2222     4

<强>性能

1000 loops, best of 3: 1.82 ms per loop  # jezrael #1
1000 loops, best of 3: 1.84 ms per loop  # jezrael #2
1000 loops, best of 3: 1.78 ms per loop  # mine #1
100 loops, best of 3: 2.6 ms per loop    # mine #2    
100 loops, best of 3: 3.96 ms per loop   # John Galt

大( df * 10000

100 loops, best of 3: 12.1 ms per loop   # jezrael #1
100 loops, best of 3: 11.9 ms per loop   # jezrael #2
100 loops, best of 3: 11.9 ms per loop   # mine #1
1 loop, best of 3: 3.51 s per loop       # mine #2 
1 loop, best of 3: 14.8 s per loop       # John Galt

答案 2 :(得分:1)

您可以在列

上使用sortgroupby
In [1923]: df['freq'] = (df.apply(np.sort, 1)
                           .groupby(['srcp', 'dstp'])['srcp']
                           .transform('size'))

In [1924]: df
Out[1924]:
     srcp   dstp  freq
0   55647     22     1
1      22  55670     6
2    2222  56354     4
3   55670     22     6
4   55670     22     6
5    2222  56354     4
6   56362    139     1
7      22  55670     6
8      22  55670     6
9   56354   2222     4
10     22  55670     6
11  56354   2222     4