2015-11-24 4 views
0

Я пытаюсь найти наилучший способ применения функции к группам в пределах кадра данных Pandas, где функция зависит от группы.Применить групповую функцию к группам в Pandas

Скажем, у меня есть следующий dataframe:

>>> df=pd.DataFrame(np.random.randint(50,200,9), columns=['Value']) 
>>> df['Year']=[2001,2002,2003]*3 
>>> df['Location']=['A','A','A','B','B','B','C','C','C'] 
>>> df.set_index(['Location','Year'], inplace=True) 
>>> df 
       Value 
Location Year  
A  2001 134 
     2002 162 
     2003 108 
B  2001  59 
     2002  52 
     2003 124 
C  2001 148 
     2002 162 
     2003  66 
>>> 

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

>>> YearDict={2001:1.3, 2002:1.2, 2003:1.1} 
>>> YearDict 
{2001: 1.3, 2002: 1.2, 2003: 1.1} 

Что бы лучший способ умножить ' Столбец «Значение» в моей базе данных по конкретному значению года в моем словаре?

В настоящее время я делаю что-то вроде этого:

>>> df.reset_index(inplace=True) 
>>> def f(row): 
...  return row['Value']*YearDict[row['Year']] 
... 
>>> 
>>> df.apply(f, axis=1) 
0  84.5 
1 210.0 
2 201.3 
3 248.3 
4  94.8 
5 177.1 
6 140.4 
7 218.4 
8  68.2 
dtype: float64 
>>> 

Является ли это лучший подход? Является ли их метод, который не требует сброса индекса dataframe?

ответ

1

Вы можете отобразить функцию по индексу. Каждая строка в dataframe имеет (Место, год) кортеж, как его индекс, так что вы можете сделать:

df.index.map(lambda t: YearDict[t[1]]) 
Out[11]: array([ 1.3, 1.2, 1.1, 1.3, 1.2, 1.1, 1.3, 1.2, 1.1]) 

Так умножения этих значений выглядит следующим образом:

year_mults = df.index.map(lambda t: YearDict[t[1]]) 

df['Value'] * year_mults 
Out[13]: 
Location Year 
A   2001 247.0 
      2002 160.8 
      2003 119.9 
B   2001 102.7 
      2002 182.4 
      2003 202.4 
C   2001  71.5 
      2002 178.8 
      2003 211.2 
Name: Value, dtype: float64 
1

Похоже, я немного поздно на вечеринку, но вы можете сделать groupby.transform. Например, если ваш необработанный DF, прежде чем установить индекс:

In [4]: df 
Out[4]: 
    Value Year Loc 
0  50 2001 A 
1 141 2002 A 
2  77 2003 A 
3 143 2001 B 
4 152 2002 B 
5 123 2003 B 
6 131 2001 C 
7 196 2002 C 
8 160 2003 C 

In [5]: df.groupby('Year')['Value'].transform(lambda v: v * YearDict[v.name]) 
Out[5]: 
0  65.0 
1 169.2 
2  84.7 
3 185.9 
4 182.4 
5 135.3 
6 170.3 
7 235.2 
8 176.0 
Name: Value, dtype: float64 

Это работает, потому что преобразование поставляет функцию аргументы серии а также name сгруппированных-по переменной (в случае стоимости ' Год').

В качестве альтернативы, учитывая ваш DataFrame с мультииндексным, вы можете просто сделать:

In [6]: df2 = df.set_index(['Loc', 'Year']) 

In [7]: df2.groupby(level=1).transform(lambda v: v * YearDict[v.name]) 
Out[7]: 
      Value 
Loc Year  
A 2001 65.0 
    2002 169.2 
    2003 84.7 
B 2001 185.9 
    2002 182.4 
    2003 135.3 
C 2001 170.3 
    2002 235.2 
    2003 176.0 

, который я думаю, что это довольно компактный и читаемый. Аргумент level=1 означает группировать второй уровень вашего MultiIndex, который в этом случае является «Годом».

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