我有一些包含三个变量的数据帧,我想为每个变量的每个标签的相对计数创建一个字典。
我很容易地创建了一个forloop,输出我想要的结果,但是我的lambda产生了奇怪的结果。
数据如下:
In [3]:
import pandas as pd
raw_data = {
'category1': ['Red', 'Red', 'Red', 'Green'],
'category2': ['Plane', 'Plane', 'Plane', 'Car'],
'category3': ['Orange', 'Orange', 'Orange', 'Banana'],
}
df = pd.DataFrame(raw_data)
df
Out[3]:
category1 category2 category3
0 Red Plane Orange
1 Red Plane Orange
2 Red Plane Orange
3 Green Car Banana
这个for循环产生我想要的确切输出:
In [4]:
forloop = {}
for column in df:
forloop[column] = df[column].value_counts(normalize=True).to_dict()
forloop
Out[4]:
{'category1': {'Green': 0.25, 'Red': 0.75},
'category2': {'Car': 0.25, 'Plane': 0.75},
'category3': {'Banana': 0.25, 'Orange': 0.75}}
然而,由于某些未知的原因,这个lambda失败了:
In [6]:
ratio = lambda x: x.value_counts(normalize=True).to_dict()
output_lambda = df.apply(ratio)
output_lambda
Out[6]:
category1 <built-in method values of dict object at 0x10...
category2 <built-in method values of dict object at 0x10...
category3 <built-in method values of dict object at 0x10...
dtype: object
我实际上不明白这里出了什么问题,除了没有解包dict
调用,这里有一个迂回的方法来实现你想要的:
In [86]:
ratio = lambda x: x.value_counts(normalize=True)
output_lambda = df.apply(lambda x: [x.value_counts().to_dict()]).apply(lambda x: x[0]).to_dict()
output_lambda
Out[86]:
{'category1': {'Green': 1, 'Red': 3},
'category2': {'Car': 1, 'Plane': 3},
'category3': {'Banana': 1, 'Orange': 3}}
它看起来像是将函数对象绑定为列值,而不是将其解包到字典中,我上面所做的是返回value_counts
作为列表,然后再次调用apply
来解包单个元素列表。这将强制在初始apply
调用中将字典解压缩为单个元素列表:
In [87]:
output_lambda = df.apply(lambda x: [x.value_counts().to_dict()])
output_lambda
Out[87]:
category1 [{'Green': 1, 'Red': 3}]
category2 [{'Plane': 3, 'Car': 1}]
category3 [{'Banana': 1, 'Orange': 3}]
dtype: object
我猜问题是lambda
函数返回的对象不能被熊猫转换为Series
或DataFrame
(但应该由熊猫专家确认)。
您只需稍微修改一下代码就可以达到几乎相同的效果:
ratio = lambda x: x.value_counts(normalize=True)
output_lambda = df.apply(ratio).to_dict()
如果你不想在output_lambda
中有nan
,你可以使用像这个答案中提出的解决方案:https://stackoverflow.com/a/26033302/4709400