在pandas中按唯一列对组合进行计数

39

我正在尝试想出如何按照每个唯一的列对(ip,用户代理)进行行数计数,例如:

d = pd.DataFrame({'ip': ['192.168.0.1', '192.168.0.1', '192.168.0.1', '192.168.0.2'], 'useragent': ['a', 'a', 'b', 'b']})

     ip              useragent
0    192.168.0.1     a
1    192.168.0.1     a
2    192.168.0.1     b
3    192.168.0.2     b

生产:

ip           useragent  
192.168.0.1  a           2
192.168.0.1  b           1
192.168.0.2  b           1

有什么想法吗?

2个回答

64
如果您使用groupby,您将获得想要的结果。

如果您使用groupby,您将获得想要的结果。

d.groupby(['ip', 'useragent']).size()

生成:

ip          useragent               
192.168.0.1 a           2
            b           1
192.168.0.2 b           1

太好了,谢谢。在 groupby/count/[] 上漏掉了最后一步。 - barnybug
2
对我来说,这只是给出了“AttributeError: 'DataFrame'对象没有'size'属性”。 - Anaphory
1
这对我不起作用。我得到了 <class 'pandas.core.frame.DataFrame'> MultiIndex: 0 entries Empty DataFrame Pandas 版本 15.2。 - feinmann
9
明白了:d.groupby(['ip', 'useragent']).size() 就可以了 :) - feinmann
1
如果我想计算每个范围内唯一值的数量怎么办?例如:在“192.28.0.1”范围内有2个唯一值(a,b)。在“192.168.0.2”范围内,有1个唯一值是b。我该如何编写代码来获取它? - weefwefwqg3
显示剩余6条评论

7
print(d.groupby(['ip', 'useragent']).size().reset_index().rename(columns={0:''}))

提供:

            ip useragent   
0  192.168.0.1         a  2
1  192.168.0.1         b  1
2  192.168.0.2         b  1

另一个不错的选择可能是pandas.crosstab

print(pd.crosstab(d.ip, d.useragent) )
print('\nsome cosmetics:')
print(pd.crosstab(d.ip, d.useragent).reset_index().rename_axis('',axis='columns') )

提供:

useragent    a  b
ip               
192.168.0.1  2  1
192.168.0.2  0  1

some cosmetics:
            ip  a  b
0  192.168.0.1  2  1
1  192.168.0.2  0  1

我赞同使用groupby。我做了一个测试,发现crosstab比groupby慢得多(例如,在我的测试中,对于一个包含10K条记录的数据框,groupby花费了0.02秒,而crosstab花费了2.3秒)。 - pegah
@pegah:我非常惊讶!您只需在前面使用%time魔法命令即可调用命令(使用ipython)。我得到的运行时间为16.5毫秒与18.4毫秒。通常,可以期望更具体的函数(这里是crosstab)执行更好。尤其是在相同库中进行类似调用时,出现100倍的运行时差异应该会引起怀疑。您是否可能对完整的 df 计算了 crosstab ,然后仅选择了一些列,而在计算 group by 时仅针对所选列进行操作? - Markus Dutschke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接