Как я могу применить функцию для создания фиктивной переменной? - PullRequest
0 голосов
/ 30 апреля 2018
import numpy as np
import pandas as pd 
import matplotlib.pyplot as plt

data={'state':[1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4],
      'year':[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3],
      'pop':[11, 22, 0, 33, 44, 32, 45, 66, 34, 12, 32, 0],
      'gdp':[123, 341, 554, 654, 245, 665, 332 ,321, 344, 232, 542, 221]}
frame=pd.DataFrame(data)

def treat(group):
        if group.ix[group.year==3, 'pop']!=0:  
            group['Treated']=1
        else:
            group['Treated']=0    

frame.groupby('state').apply(treat)

Я пытаюсь создать переменную frame['Treated'] в соответствии с некоторым условием. if ('year'==3) and ('pop'!=0) - Я думаю, что «состояние» находится в группе «Обработано» (поэтому я создал переменную «Обработано»).

К сожалению, я получаю сообщение об ошибке:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Что не так с моим кодом? Вы знаете, как я мог решить эту проблему?

Пересоздать Спасибо за ваш добрый ответ, и я извиняюсь за то, что не описал мою проблему ясно.

Я снова пытаюсь описать свою проблему. Для состояния 1 значение pop равно 0 в году 3, поэтому состояние 1 не входит в обработанную группу (как показано ниже, frame ['Treated'] = 0 для состояния 1 в каждом году) Для состояния 2 pop значение не равно 0 в 3-м году, поэтому состояние 2 находится в обработанной группе (как показано ниже, кадр ['Обработано'] = 1 для состояния 2 в каждом году) другие состояния обрабатываются по аналогичной причине. Окончательный результат выглядит следующим образом.

    state  year  pop  gdp  Treated
0       1     1   11  123        0
1       1     2   22  341        0
2       1     3    0  554        0
3       2     1   33  654        1
4       2     2   44  245        1
5       2     3   32  665        1
6       3     1   45  332        1
7       3     2   66  321        1
8       3     3   34  344        1
9       4     1   12  232        0
10      4     2   32  542        0
11      4     3    0  221        0

Ответы [ 3 ]

0 голосов
/ 30 апреля 2018

Альтернативой np.where будет преобразование соответствующей логической маски в целочисленный тип.

frame['Treated'] = (frame.year.eq(3) & frame['pop'].ne(0)).astype(int)

Ваш текущий код не работает, потому что

group.ix[group.year==3, 'pop']!=0

оставляет вас с серией Pandas, которую вы не можете безопасно использовать в операторе if. В любом случае, использование apply, как это плохо, когда вы можете решить свою проблему с помощью логической маски.

0 голосов
/ 30 апреля 2018

Использование pandas.DataFrame.assign и pandas.DataFrame.eval

frame.assign(Treated=frame.eval('pop != 0 & year == 3') * 1)

    gdp  pop  state  year  Treated
0   123   11      1     1        0
1   341   22      1     2        0
2   554    0      1     3        0
3   654   33      2     1        0
4   245   44      2     2        0
5   665   32      2     3        1
6   332   45      3     1        0
7   321   66      3     2        0
8   344   34      3     3        1
9   232   12      4     1        0
10  542   32      4     2        0
11  221    0      4     3        0

Я умножаю на единицу, чтобы получить целое число. Это более короткий код, но не такой эффективный, как у @ miradulo astype(int)

0 голосов
/ 30 апреля 2018

groupby здесь не нужно, просто нужно np.where

frame['Treated']=np.where((frame.year==3)&(frame.pop!=0),1,0)
frame
Out[429]: 
    gdp  pop  state  year  Treated
0   123   11      1     1        0
1   341   22      1     2        0
2   554    0      1     3        1
3   654   33      2     1        0
4   245   44      2     2        0
5   665   32      2     3        1
6   332   45      3     1        0
7   321   66      3     2        0
8   344   34      3     3        1
9   232   12      4     1        0
10  542   32      4     2        0
11  221    0      4     3        1
...