2014-11-11 2 views
0

Рассмотрим следующий код, который направлен на разделение колонки по его сгруппированных среднее:Панды группа по добавляет индекс

df = pd.DataFrame({'expenditure' : np.random.choice(['foo','bar'], n), 
        'groupid' : np.random.choice(['one','two'], n), 
        'coef' : np.random.randn(n)}) 
df.set_index('expenditure', inplace=True) 
test = df.groupby(level=0).apply(lambda x: x['coef']/x.coef.mean()) 

Мне нравится эта структура данных перед apply Инг, прежде чем я нахожусь обычно в состоянии только df['someNewColumn'] = df.apply(...). Но как ни странно, на этот раз я не могу мгновенно повторить результаты.

test следует проиндексировать по индексам, которые произошли groupby, expenditure. Тем не менее, он имеет двойной индекс:

>>> test 
expenditure expenditure 
bar   bar   -0.491900 
      bar   -9.332964 
      bar   8.019472 
      bar   -4.540905 
      bar   5.627947 
      bar   -0.171765 
      bar   5.698813 
      bar   6.476207 
      bar   8.796249 
      bar   -8.284087 
      bar   1.426311 
      bar   -1.223377 
foo   foo   1.900897 
      foo   7.057078 
      foo   0.060856 
      foo   3.850323 
      foo   2.928085 
      foo   -3.249857 
      foo   3.176616 
      foo   -1.433766 
      foo   0.910017 
      foo   1.395376 
      foo   1.898315 
      foo   -1.903462 
      foo   -3.590479 
Name: coef, dtype: float64 

Почему это двойной индекс, и как я могу получить мой нормализованной колонку?

>>> test.index 
MultiIndex(levels=[[u'bar', u'foo'], [u'bar', u'foo']], 
      labels=[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], 
      names=[u'expenditure', u'expenditure']) 

Моя pandas версия 0.15.0.

ответ

0

Я не совсем уверен, если это поможет вам, но так как вы проиндексировали столбец expenditure, вам необходимо GroupBy этого показателя до применения для достижения того, что я верю, что вы хотите, что-то вроде этого:

import pandas as pd 

n = 10 
df = pd.DataFrame({'expenditure' : np.random.choice(['foo','bar'], n), 
        'groupid' : np.random.choice(['one','two'], n), 
        'coef' : np.random.randn(n)}) 

df.set_index('expenditure', inplace=True) 

# when you try to apply, you need to groupby 'expenditure' -- which is the df.index 
test = df.groupby(df.index).apply(lambda x: x['coef'] /x.coef.mean()) 

test 

expenditure 
bar   expenditure 
bar   2.013101 
bar  ... 
foo   expenditure 
foo   1 
Name: coef, dtype... 
dtype: object 

test.index 
Index([u'bar', u'foo'], dtype='object') 
+0

Копировавший неправильный код, извините. Обновлен вопрос. Я делаю почти то же самое, но я группирую «level = 0», что то же самое. Тем не менее я получаю вывод для 'test', который я перечислял выше. Не совсем ясно, как выглядит ваш вывод из-за '...'.Это похоже на мое? Если нет, какую версию 'pandas' вы используете? – FooBar

+0

@FooBar, 'level = 0' даст тот же результат, что и выше, поскольку к моменту, когда вы выполняете' apply', у вас есть только 1 индекс. ** ... ** - это точно из результата, поскольку вы пытаетесь применить '.../x.coef.mean()' на уровне группы. Тем не менее, я думаю, что предложение Дж. Д. Лонга более вероятно, чего вы пытаетесь достичь. И моя версия pandas ** 0.14.1 ** – Anzel

1

Для меня не очевидна, какая версия панд вы используете, но ваш прием не работает для меня вообще.

У меня проблемы с группировкой по индексу. Поэтому я всегда сбрасывать индекс и группу на обычной колонке:

df = pd.DataFrame({'expenditure' : np.random.choice(['foo','bar'], n), 
        'groupid' : np.random.choice(['one','two'], n), 
        'coef' : np.random.randn(n)}) 

, то вы можете сделать что-либо:

df.groupby('expenditure').coef.apply(lambda x: x/x.mean()) 

или после чего почти точно, что вы пробовали раньше

df.groupby('expenditure').apply(lambda x: x.coef/x.coef.mean()) 
+0

Функции, применяемые к объектам 'groupby', видят всю группу (блок данных или серию). Основная проблема здесь в том, что лямбда не возвращает ни одного значения, а серии. Я согласен с вашим предлагаемым решением, но, возможно, последний бит должен быть 'df.coef.mean (level = 'costs')'. –

+0

кричит. Ты прав. Я прочитал его код слишком быстро и не заметил, что заявление было записано в сгруппированных данных. Я исправлю свои комментарии выше. –

+0

Кроме того, использование метода '.div' будет транслировать результаты на основе индекса:' test = df ['coef']. Div (df ['coef']. Mean (level = 'costs')) ' –

0

Давайте сделаем ваш dataframe несколько проще для иллюстрации:

import numpy as np 
import pandas as pd 
n = 10 
np.random.seed(0) 
df = pd.DataFrame(
    data = { 
     'groupid' : np.random.choice(['one','two'], n), 
     'coef' : np.arange(n) 
    }, 
    index=pd.Index(np.random.choice(['foo','bar'], n), name='expenditure'), 
) 
df 


      coef groupid 
expenditure    
bar    0  one 
foo    1  two 
foo    2  two 
bar    3  one 
foo    4  two 
foo    5  two 
foo    6  two 
foo    7  two 
foo    8  two 
bar    9  two 

Вы можете вычислить среднее coef для каждой expenditure группы, используя два различных метода:

means = df['coef'].mean(level='expenditure') 

или

means = df['coef'].groupby(level='expenditure').mean() 

Оба дают мне:

expenditure 
bar   4.000000 
foo   4.714286 
Name: coef, dtype: float64 

Итак, мы можем разделить coef сгруппированными средствами и транслировать их по отношению к expenditure значения:

test = df['coef'].div(means, level='expenditure') 
test 

expenditure 
bar   0.000000 
bar   0.750000 
bar   2.250000 
foo   0.212121 
foo   0.424242 
foo   0.848485 
foo   1.060606 
foo   1.272727 
foo   1.484848 
foo   1.696970 
Name: coef, dtype: float64 

Наши первоначальные значения в bar группе 0, 3 и 9, так что результаты 0.0, 0.75, 2.25 проверить.

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