我对Python相当陌生。我遇到了Pandas: Group by combination of two columns。不幸的是,已接受的答案不再适用于熊猫版本0.23.4
,该文章的目的是弄清楚组变量的组合,并为值创建字典。即group_by
应该忽略分组的顺序。
这是公认的答案:
import pandas as pd
from collections import Counter
d = pd.DataFrame([('a','b',1), ('a','c', 2), ('b','a',3), ('b','a',3)],
columns=['x', 'y', 'score'])
d[['x', 'y']] = d[['x', 'y']].apply(sorted, axis=1)
x = d.groupby(['x', 'y']).agg(Counter)
print(x)
在这里,...apply(sorted)
引发以下异常:
提高ValueError('必须具有相等的len键和值'ValueError: 设置可迭代项时必须具有相同的len键和值
这是我的熊猫版本:
> pd.__version__
Out: '0.23.4'
这是我在阅读https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.sort_values.html之后尝试过的方法:
d = pd.DataFrame([('a','b',1), ('a','c', 2), ('b','a',3), ('b','a',3)],
columns=['x', 'y', 'score'])
d=d.sort_values(by=['x','y'],axis=1).reset_index(drop=True)
x = d.groupby(['x', 'y']).agg(Counter)
print(x)
不幸的是,这也会引发错误:
1382,以_get_label_or_level_values 引发KeyError(key)KeyError:'x'
预期输出:
score count
x y
a b {1: 1, 3: 2} 2
c {2: 1} 1
有人可以帮我吗?附带说明一下,如果您还可以指导如何计算keys()
列中score
的计数,那就太好了。我正在寻找向量化的解决方案。
我正在使用python 3.6.7
非常感谢。
答案 0 :(得分:2)
问题是sorted
返回列表,所以有必要将ti转换为Series
:
d[['x', 'y']] = d[['x', 'y']].apply(lambda x: pd.Series(sorted(x)), axis=1)
但是将numpy.sort
与DataFrame
构造函数一起使用会更快,因为apply
是幕后的循环:
d = pd.DataFrame([('a','b',1), ('a','c', 2), ('b','a',3), ('b','a',3)],
columns=['x', 'y', 'score'])
d[['x', 'y']] = pd.DataFrame(np.sort(d[['x', 'y']], axis=1), index=d.index)
然后显示用于聚合的列,其中包含聚合函数的列表-例如nunique
用于计算唯一值的数量:
x = d.groupby(['x', 'y'])['score'].agg([Counter, 'nunique'])
print(x)
Counter nunique
x y
a b {1: 1, 3: 2} 2
c {2: 1} 1
x = d.groupby(['x', 'y'])['score'].agg([Counter, 'size'])
print(x)
Counter size
x y
a b {1: 1, 3: 2} 3
c {2: 1} 1
答案 1 :(得分:1)
使用-
a=d[['x','y']].values
a.sort(axis=1)
d[['x','y']] = a
x = d.groupby(['x', 'y']).agg(Counter)
print(x)
输出
score
x y
a b {1: 1, 3: 2}
c {2: 1}
答案 2 :(得分:1)
将result_type = 'broadcast'
添加为.apply()
的参数之一是可行的。
>>> d = pd.DataFrame([('a','b',1), ('a','c', 2), ('b','a',3), ('b','a',3)],
columns=['x', 'y', 'score'])
>>> d[['x', 'y']] = d[['x', 'y']].apply(sorted, axis=1, result_type='broadcast')
>>> x = d.groupby(['x', 'y']).agg(Counter)
>>> print(x)
score
x y
a b {1: 1, 3: 2}
c {2: 1}
请注意带和不带result_type = 'broadcast'
的区别。
>>> d[['x', 'y']].apply(sorted, axis=1)
0 [a, b]
1 [a, c]
2 [a, b]
3 [a, b]
dtype: object
>>> d[['x', 'y']].apply(sorted, axis=1, result_type='broadcast')
x y
0 a b
1 a c
2 a b
3 a b
如您所见,result_type = 'broadcast'
将.apply()
的结果从列表中拆分(广播)到相应的列中,从而可以分配给d[['x', 'y']]