Группировка и применение лямбды с условием для первого ряда - панды - PullRequest
3 голосов
/ 13 октября 2019

У меня есть фрейм данных с идентификаторами, и выбор, который был сделан этими идентификаторами. Набор альтернатив (вариантов) представляет собой список целых чисел: [10, 20, 30, 40]. Примечание. Важно использовать этот список. Давайте назовем его «choice_list».

Это фрейм данных:

ID  Choice
1   10
1   30
1   10
2   40
2   40
2   40
3   20
3   40
3   10

Я хочу создать переменную для каждой альтернативы: '10_Var', '20_Var', '30_Var','40_Var. В первой строке каждого идентификатора, если, например, в качестве первого варианта выбрано «10», переменная «10_Var» получит значение 0,6 (некоторый параметр), а каждая из других переменных («20_Var», «30_Var»,«40_Var») получит значение (1 - 0,6) / 4. Число 4 означает число альтернатив.

Ожидаемый результат:

ID  Choice  10_Var  20_Var  30_Var  40_Var
1   10      0.6     0.1     0.1     0.1
1   30              
1   10              
2   40      0.1     0.1     0.1     0.6
2   40              
2   40              
3   20      0.1     0.6     0.1     0.1
3   40              
3   10              

Ответы [ 3 ]

2 голосов
/ 13 октября 2019

вы можете использовать np.where для этого. Эффективно, чтобы df.where

df = pd.DataFrame([['1', 10], ['1', 30], ['1', 10], ['2', 40], ['2', 40], ['2', 40], ['3', 20], ['3', 40], ['3', 10]], columns=('ID', 'Choice'))

choices = np.unique(df.Choice)
for choice in choices:
    df[f"var_{choice}"] = np.where(df.Choice==choice, 0.6, (1 - 0.6) / 4)

df

Результат

    ID  Choice  var_10  var_20  var_30  var_40
0  1      10     0.6     0.1     0.1     0.1
1  1      30     0.1     0.1     0.6     0.1
2  1      10     0.6     0.1     0.1     0.1
3  2      40     0.1     0.1     0.1     0.6
4  2      40     0.1     0.1     0.1     0.6
5  2      40     0.1     0.1     0.1     0.6
6  3      20     0.1     0.6     0.1     0.1
7  3      40     0.1     0.1     0.1     0.6
8  3      10     0.6     0.1     0.1     0.1

Редактировать Чтобы установить значения только для 1-й строки группы

df = pd.DataFrame([['1', 10], ['1', 30], ['1', 10], ['2', 40], ['2', 40], ['2', 40], ['3', 20], ['3', 40], ['3', 10]], columns=('ID', 'Choice'))
df=df.set_index("ID")

## create unique index for each row if not already
df = df.reset_index()

choices = np.unique(df.Choice)

## get unique id of 1st row of each group
grouped = df.loc[df.reset_index().groupby("ID")["index"].first()]

## set value for each new variable 
for choice in choices:
    grouped[f"var_{choice}"] = np.where(grouped.Choice==choice, 0.6, (1 - 0.6) / 4)

pd.concat([df, grouped.iloc[:, -len(choices):]], axis=1)
1 голос
/ 14 октября 2019

Смесь раствора numpy и pandas:

rows = np.unique(df.ID.values, return_index=1)[1]
df1 = df.loc[rows].assign(val=0.6)
df2 = (pd.crosstab([df1.index, df1.ID, df1.Choice], df1.Choice, df1.val, aggfunc='first')
         .reindex(choice_list, axis=1)
         .fillna((1-0.6)/len(choice_list)).reset_index(level=[1,2], drop=True))

pd.concat([df, df2], axis=1)

Out[217]:
   ID  Choice   10   20   30   40
0   1      10  0.6  0.1  0.1  0.1
1   1      30  NaN  NaN  NaN  NaN
2   1      10  NaN  NaN  NaN  NaN
3   2      40  0.1  0.1  0.1  0.6
4   2      40  NaN  NaN  NaN  NaN
5   2      40  NaN  NaN  NaN  NaN
6   3      20  0.1  0.6  0.1  0.1
7   3      40  NaN  NaN  NaN  NaN
8   3      10  NaN  NaN  NaN  NaN
1 голос
/ 13 октября 2019

Мы можем использовать insert o для создания строк на основе уникальных значений идентификаторов, полученных с помощью Series.unique . Мы также можем создать маску для заполнения только первой строки, используя np.where . В начале sort_values ​​ используется для сортировки значений на основе идентификатора. Вы можете пропустить этот шаг, если ваш фрейм данных уже хорошо отсортирован (как показано в примере):

df=df.sort_values('ID')
n=df['Choice'].nunique()
mask=df['ID'].ne(df['ID'].shift())
for choice in df['Choice'].sort_values(ascending=False).unique():
    df.insert(2,column=f'{choice}_Var',value=np.nan)
    df.loc[mask,f'{choice}_Var']=np.where(df.loc[mask,'Choice'].eq(choice),0.6,0.4/n)
print(df)

       ID  Choice  10_Var  20_Var  30_Var  40_Var
0   1      10     0.6     0.1     0.1     0.1
1   1      30     NaN     NaN     NaN     NaN
2   1      10     NaN     NaN     NaN     NaN
3   2      40     0.1     0.1     0.1     0.6
4   2      40     NaN     NaN     NaN     NaN
5   2      40     NaN     NaN     NaN     NaN
6   3      20     0.1     0.6     0.1     0.1
7   3      40     NaN     NaN     NaN     NaN
8   3      10     NaN     NaN     NaN     NaN
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...