2016-09-22 4 views
1

Как я могу использовать pandas для добавления нескольких значений KPI для одного клиента эффективно?Pandas добавить несколько столбцов для одного

Объединение pivoted df с customers df создает проблемы, поскольку страна является индексом поворотного фрейма данных, а национальность не указана в индексе.

countryKPI = pd.DataFrame({'country':['Austria','Germany', 'Germany', 'Austria'], 
          'indicator':['z','x','z','x'], 
          'value':[7,8,9,7]}) 
customers = pd.DataFrame({'customer':['first','second'], 
          'nationality':['Germany','Austria'], 
          'value':[7,8]}) 

См желаемый результат в розовый: enter image description here

ответ

1

Вы могли противодействие рассогласования в категориях через merge:

df = pd.pivot_table(data=countryKPI, index=['country'], columns=['indicator']) 
df.index.name = 'nationality'  
customers.merge(df['value'].reset_index(), on='nationality', how='outer') 

Image

данные:

countryKPI = pd.DataFrame({'country':['Austria','Germany', 'Germany', 'Austria'], 
          'indicator':['z','x','z','x'], 
          'value':[7,8,9,7]}) 
customers = pd.DataFrame({'customer':['first','second'], 
          'nationality':['Slovakia','Austria'], 
          'value':[7,8]}) 

Проблема заключается в том, что у вас есть CategoricalIndex в вашем DF в результате операции pivot, и когда вы выполняете reset_index, то вы жалуетесь на эту ошибку.

Просто сделать обратный инжиниринг, как и в проверке на dtypes из countryKPI и customers Dataframes и везде, где есть упоминаются category, конвертировать эти столбцы в их string представления через astype(str)


Воспроизуюся ошибку и Противодействие его:

Предположим, что DF:

countryKPI['indicator'] = countryKPI['indicator'].astype('category') 
countryKPI['country'] = countryKPI['country'].astype('category') 
customers['nationality'] = customers['nationality'].astype('category') 

countryKPI.dtypes 
country  category 
indicator category 
value   int64 
dtype: object 

customers.dtypes 
customer   object 
nationality category 
value    int64 
dtype: object 

pivot После операции:

df = pd.pivot_table(data=countryKPI, index=['country'], columns=['indicator']) 
df.index 
CategoricalIndex(['Austria', 'Germany'], categories=['Austria', 'Germany'], ordered=False, 
        name='country', dtype='category') 
# ^^ See the categorical index 

При выполнении reset_index на том, что:

df.reset_index() 

TypeError: cannot insert an item into a CategoricalIndex that is not already an existing category

Чтобы противостоять этой ошибки, просто отбрасывать категориальные столбцы str типа.

countryKPI['indicator'] = countryKPI['indicator'].astype('str') 
countryKPI['country'] = countryKPI['country'].astype('str') 
customers['nationality'] = customers['nationality'].astype('str') 

Теперь reset_index часть работы в и даже merge тоже.

+0

интересный и простой. Но http://imgur.com/a/PeCyh почему я получаю несколько других значений для исходного набора данных (0,1,2,3)? –

+0

Я вижу - ваше последнее изменение аннулирует мой последний комментарий. –

+0

Однако проблема все же заключается в том, что: невозможно вставить элемент в категориальный указатель, что я уже не существующая категория –

2

Я думаю, что вы можете использовать concat:

df_pivoted = countryKPI.pivot_table(index='country', 
           columns='indicator', 
           values='value', 
           fill_value=0) 
print (df_pivoted)  
indicator x z 
country   
Austria 7 7 
Germany 8 9 

print (pd.concat([customers.set_index('nationality'), df_pivoted], axis=1)) 
     customer value x z 
Austria second  8 7 7 
Germany first  7 8 9      


print (pd.concat([customers.set_index('nationality'), df_pivoted], axis=1) 
     .reset_index() 
     .rename(columns={'index':'nationality'}) 
     [['customer','nationality','value','x','z']]) 

    customer nationality value x z 
0 second  Austria  8 7 7 
1 first  Germany  7 8 9 

EDIT комментариев:

Проблема dtypes столбцов customers.nationality и countryKPI.countrycategory, и если некоторые категории являются missin г, это поднять ошибку:

ValueError: incompatible categories in categorical concat

Решения найти общие категории по union, а затем set_categories:

import pandas as pd 
import numpy as np 

countryKPI = pd.DataFrame({'country':['Austria','Germany', 'Germany', 'Austria'], 
          'indicator':['z','x','z','x'], 
          'value':[7,8,9,7]}) 
customers = pd.DataFrame({'customer':['first','second'], 
          'nationality':['Slovakia','Austria'], 
          'value':[7,8]}) 

customers.nationality = customers.nationality.astype('category') 
countryKPI.country = countryKPI.country.astype('category') 

print (countryKPI.country.cat.categories) 
Index(['Austria', 'Germany'], dtype='object') 

print (customers.nationality.cat.categories) 
Index(['Austria', 'Slovakia'], dtype='object') 

all_categories =countryKPI.country.cat.categories.union(customers.nationality.cat.categories) 
print (all_categories) 
Index(['Austria', 'Germany', 'Slovakia'], dtype='object') 

customers.nationality = customers.nationality.cat.set_categories(all_categories) 
countryKPI.country = countryKPI.country.cat.set_categories(all_categories) 
df_pivoted = countryKPI.pivot_table(index='country', 
           columns='indicator', 
           values='value', 
           fill_value=0) 
print (df_pivoted)  
indicator x z 
country   
Austria 7 7 
Germany 8 9 
Slovakia 0 0   

print (pd.concat([customers.set_index('nationality'), df_pivoted], axis=1) 
     .reset_index() 
     .rename(columns={'index':'nationality'}) 
     [['customer','nationality','value','x','z']]) 

    customer nationality value x z 
0 second  Austria 8.0 7 7 
1  NaN  Germany NaN 8 9 
2 first Slovakia 7.0 0 0 

Если необходима более высокая производительность, вместо pivot_table использовать groupby:

df_pivoted1 = countryKPI.groupby(['country','indicator']) 
         .mean() 
         .squeeze() 
         .unstack() 
         .fillna(0) 
print (df_pivoted1) 
indicator x z 
country    
Austria 7.0 7.0 
Germany 8.0 9.0 
Slovakia 0.0 0.0 

Timings:

In [177]: %timeit countryKPI.pivot_table(index='country', columns='indicator', values='value', fill_value=0) 
100 loops, best of 3: 6.24 ms per loop 

In [178]: %timeit countryKPI.groupby(['country','indicator']).mean().squeeze().unstack().fillna(0) 
100 loops, best of 3: 4.28 ms per loop 
+0

Это почти работает - но я получаю ошибку несовместимых категорий в категорическом concat –

+1

Проблема с реальными данными, не так ли? Думаю, Смайл работает отлично. – jezrael

+0

К сожалению, да. –

Смежные вопросы