2015-06-02 2 views
4

У меня есть некоторый dataframe из трех переменных, и я хочу создать словарь относительного подсчета каждой метки для каждой переменной.Pandas value_counts() for loop failed as 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 

Этот цикл производит точный результат я хочу:

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}} 

Однако это лямбда терпит неудачу по неизвестной причине:

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 

ответ

1

На самом деле я не могу понять, что здесь происходит, кроме того, что он не распаковывает 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 
1

Я думаю, проблема в том, что функция lambda возвращает объект, который не может быть tranformed к Series или DataFrame по панд (но должны быть подтверждены специалистами панд).

Вы можете достичь почти то же самое с незначительными изменениями вашего кода:

ratio = lambda x: x.value_counts(normalize=True) 
output_lambda = df.apply(ratio).to_dict() 

Если вы не хотите иметь nan в output_lambda, вы можете использовать решение, как один предложенный в этом ответе: https://stackoverflow.com/a/26033302/4709400