TypeError: аргумент типа float не может быть повторен при использовании лямбда-функции в кадре данных - PullRequest
0 голосов
/ 06 августа 2020

Следуя этому вопросу , у меня есть этот фрейм данных:

    ChildID   MotherID   preWeight
0     20      455        3500
1     20      455        4040
2     13      102        NaN
3     702     946        5000
4     82      571        2000
5     82      571        3500
6     82      571        3800

, где я преобразовал функцию preWeight, которая имеет несколько наблюдений на один MotherID, в функцию preMacro с одним наблюдение за MotherID на основе следующих правил:

  • если preWeight> = 4000 для определенного MotherID, я присвоил preMacro значение «Да» независимо от остальных наблюдений
  • В противном случае Я присвоил preMacro значение «Нет»

Используя эту строку кода:

    df.groupby(['ChildID','MotherID']).agg(lambda x: 'Yes' if (x>4000).any() else 'No').reset_index().rename(columns={"preWeight": "preMacro"})

Однако я понял, что таким образом я не сохраняю значения NaN в наборе данных , которые в идеале следует вменять, а не просто присваивать им значения «Нет». Поэтому я попытался изменить указанную выше строку на:

    df=df.groupby(['MotherID', 'ChildID'])['preWeight'].agg(
        lambda x: 'Yes' if (x>4000).any() else (np.NaN if 'no_value' in x.values.all() else 'No')).reset_index().rename(
        columns={"preWeight": "preMacro"})

Я хотел, чтобы эта строка преобразовывала указанный выше фрейм данных в следующее:

    ChildID   MotherID   preMacro
0   20        455        Yes
1   13        102        NaN
2   702       946        Yes
3   82        571        No

Однако при запуске я получил эту ошибку:

TypeError: аргумент типа 'float' не может быть повторен

Я понимаю, что в случае не пропущенных значений значения x.values.all () являются числами с плавающей запятой, которые не повторяются, но я не уверен, как еще это кодировать, есть идеи?

Спасибо.

1 Ответ

1 голос
/ 06 августа 2020

Для производительности не проверять в пользовательской функции для каждой группы лучше всего агрегировать по GroupBy.agg по вспомогательному столбцу для логической маски с GroupBy.all и GroupBy.any, а затем установите столбец preMacro на numpy.select:

df = (df.assign(testconst = df['preWeight'] > 4000,
                testna = df['preWeight'].notna())
        .groupby(['ChildID','MotherID'], sort=False)
        .agg({'testconst':'any', 'testna':'all'}))


masks = [df['testconst'] & df['testna'], df['testconst'] | df['testna']]
df['preMacro'] = np.select(masks, ['Yes','No'], default=None)
df = df.drop(['testconst','testna'], axis=1).reset_index()
print (df)
   ChildID  MotherID preMacro
0       20       455      Yes
1       13       102     None <- for avoid convert np.NaN to string nan is used None
2      702       946      Yes
3       82       571       No

Если небольшой DataFrame или производительность не важны:

f = lambda x: 'Yes' if (x>4000).any() else ('No' if x.notna().all() else np.NaN)
df1 = (df.groupby(['ChildID','MotherID'], sort=False)['preWeight']
         .agg(f)
         .reset_index(name='preMacro'))
print (df1)
   ChildID  MotherID preMacro
0       20       455      Yes
1       13       102      NaN
2      702       946      Yes
3       82       571       No
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...