Как мы можем применить лямбда-функцию к этому категориальному фрейму данных? Обратите внимание, что оценки категориальные. Я ожидаю, что те, кто выше C, выполнят «Пройдено». вместо этого отображается "Неудача".
import pandas as pd
dfg = pd.DataFrame(['A+', 'A', 'A-', 'B+', 'B', 'B-', 'C+', 'C', 'C-', 'D+', 'D'],
index=['excellent', 'excellent', 'excellent', 'good', 'good', 'good', 'ok', 'ok', 'ok', 'poor', 'poor'])
dfg.rename(columns = {0: 'Grades'}, inplace=True)
dfg['Grades'] = dfg['Grades'].astype('category',
categories=['D', 'D+', 'C-', 'C', 'C+', 'B-', 'B', 'B+', 'A-', 'A', 'A+'],
ordered=True)
def Assess(row):
if row>'C':
return 'Pass'
return 'Fail'
dfg['Asses'] = dfg.apply(lambda x: Assess(x.Grades), axis=1)
dfg
увидеть результат
Grades Asses
excellent A+ Fail
excellent A Fail
excellent A- Fail
good B+ Fail
good B Fail
good B- Fail
ok C+ Pass
ok C Fail
ok C- Pass
poor D+ Pass
poor D Pass






Использовать:
dfg['Assess'] = np.where(dfg['Grades']>'C','Pass','Fail')
dfg
Выход:
Grades Assess
excellent A+ Pass
excellent A Pass
excellent A- Pass
good B+ Pass
good B Pass
good B- Pass
ok C+ Pass
ok C Fail
ok C- Fail
poor D+ Fail
poor D Fail
Спасибо @ScottBoston, отличный ответ! Я бы никогда об этом не подумал. Было бы проще, если бы для меня был SQL.
@MEdwin Да, я тоже из SQL. Однако два года назад я прошел курс по пандам и действительно изучил основы панд. Это очень важно для понимания лучших способов использования Python для анализа данных.
хорошая идея. Можно ли для этого использовать лямбда / применить?
@MEdwin - это намного лучший подход к apply, поскольку apply - это просто тонко завуалированная оболочка вокруг итерации, в то время как np.where векторизован.
В духе создания чего-то из ничего. "Векторизация" часто преувеличивается. Во многих случаях «векторизованный» подход представляет собой плотно завуалированную оболочку вокруг итерации. В некоторых случаях существует алгоритмический подход, уменьшающий временную сложность. В этом случае временная сложность не уменьшается, но использование numpy.where по-прежнему намного быстрее.
То, как вы использовали apply, передает в функцию строку, а не категориальную вещь.
Вместо этого используйте операцию сравнения с самой серией и позвольте Pandas обрабатывать ее категориальный характер.
dfg.assign(Assess=dfg.Grades > 'C')
Grades Asses
excellent A+ True
excellent A True
excellent A- True
good B+ True
good B True
good B- True
ok C+ True
ok C False
ok C- False
poor D+ False
poor D False
Вы можете следить за этим с помощью map, чтобы пройти / не пройти
dfg.assign(Asses=dfg.Grades.gt('C').map({True: 'Pass', False: 'Fail'}))
Grades Asses
excellent A+ Pass
excellent A Pass
excellent A- Pass
good B+ Pass
good B Pass
good B- Pass
ok C+ Pass
ok C Fail
ok C- Fail
poor D+ Fail
poor D Fail
Если вам действительно нужен lambda (а я бы не стал), вам нужно создать словарь, который отображает буквенные оценки обратно в числовые значения.
m = dict(map(reversed, enumerate(dfg.Grades.cat.categories)))
dfg.assign(Asses=dfg.apply(lambda row: 'Pass' if m[row.Grades] > m['C'] else 'Fail', 1))
Grades Asses
excellent A+ Pass
excellent A Pass
excellent A- Pass
good B+ Pass
good B Pass
good B- Pass
ok C+ Pass
ok C Fail
ok C- Fail
poor D+ Fail
poor D Fail
Спасибо @pirsquared. Можно ли было бы использовать лямбда / применить для этого?
Очень элегантный. Спасибо @piRSquared.
Опять же, вы выбираете второе значение, поэтому оцениваете строку, а не используете категориальные методы pd.Series. И по возможности избегайте использования apply с axis = 1. В этом случае лучше всего найти методы векторизации, такие как
np.where.