Примените функцию Python к одному столбцу pandas и примените выходные данные к нескольким столбцам

#python #pandas #dataframe #lambda #apply

#python #pandas #dataframe #лямбда #применить

Вопрос:

Привет, сообщество,

Я прочитал так много ответов и блогов, но я не могу понять, какую простую вещь я упускаю!. Я использую функцию ‘conditions’, чтобы определить все условия и применить ее к одному столбцу dataframe. И если условие удовлетворяет, оно должно создать / обновить 2 новых столбца фрейма данных ‘cat’ и ‘subcat’.

Было бы большим подспорьем, если бы вы, ребята, могли мне здесь помочь!

 dict = {'remark':['NA','NA','Category1','Category2','Category3'],
        'desc':['Present','Present','NA','Present','NA']
} 

df = pd.DataFrame(dict) 
  

Фрейм данных выглядит примерно так:

           remark       desc
0         NA           Present      
1         NA           Present        
2         Category1    NA                   
3         Category2    Present                   
4         Category3    NA            

  

Я написал функцию для определения условий, как показано ниже:

 def conditions(s):

    if (s == 'Category1'):
        x = 'insufficient'
        y = 'resolution'
    elif (s=='Category2):
        x= 'insufficient'
        y= 'information'
    elif (s=='Category3):
        x= 'Duplicate'
        y= 'ID repeated'
    else:
        x= 'NA'
        y= 'NA'
    
    return (x,y)

  

У меня есть несколько идей по выполнению вышеупомянутой функции в столбце dataframe, но безуспешно.

 df[['cat','subcat']] = df['remark'].apply(lambda x: pd.Series([conditions(df)[0],conditions(df)[1]]))

  

Мой ожидаемый фрейм данных должен выглядеть примерно так:

           remark       desc        cat           subcat
0         NA           Present     NA            NA      
1         NA           Present     NA            NA
2         Category1    NA          insufficient  resolution         
3         Category2    Present     insufficient  information              
4         Category3    NA          Duplicate     ID repeated

  

Большое спасибо.

Ответ №1:

Один из способов обойти это — использовать понимание списка :

 df[['cat', 'subcat']] = [("insufficient", "resolution")  if word == "Category1" else 
                         ("insufficient", "information") if word == "Category2" else
                         ("Duplicate", "ID repeated")    if word == "Category3" else 
                         ("NA", "NA")
                         for word in df.remark]

  remark      desc               cat         subcat
0   NA        Present          NA              NA
1   NA        Present          NA              NA
2   Category1   NA          insufficient    resolution
3   Category2   Present     insufficient    information
4   Category3   NA          Duplicate       ID repeated
  

Ответ @dm2 показывает, как это сделать с помощью вашей функции. Первый apply(conditions) создает серию, содержащую кортежи, второй apply создает отдельные столбцы, формируя фрейм данных, который затем можно присвоить cat и subcat .

Причина, по которой я предлагаю использовать понимание списка, заключается в том, что вы имеете дело со строками, а в Pandas работа со строками через vanilla python чаще всего выполняется быстрее. Кроме того, при понимании списка обработка выполняется один раз, вам не нужно применять функцию conditions и затем вызывать pd.Series . Это дает вам более высокую скорость. Тестирование подтвердит или опровергнет это.

Комментарии:

1. Мне нравится ваша идея понимания списка. Я пробовал то же самое ранее, но поскольку столбец (‘cat’ amp;’subcat’) отсутствует в df. это выдает ‘KeyError’. Есть идея? Ошибка ключа: «Ни один из [Index([‘cat’, ‘subcat’], dtype=’object’)] не находится в [index]»

2. Да, используя timeit, это намного, намного быстрее: среднее значение 7 запусков по 1000 попыток для моего кода составляет 0,3 с, ваш код выполняется так же за 0,009 с.

3. я не уверен, почему у вас эта ошибка @nealkaps — приведенный выше код должен создать два новых столбца. Если вы используете ноутбук, вы могли бы перезапустить ядро и снова запустить ячейку.

Ответ №2:

Вы могли бы сделать:

  df[['cat','subcat']] = df['remark'].apply(conditions).apply(pd.Series)
  

Вывод:

   remark      desc               cat         subcat
0   NA        Present          NA              NA
1   NA        Present          NA              NA
2   Category1   NA          insufficient    resolution
3   Category2   Present     insufficient    information
4   Category3   NA          Duplicate       ID repeated
  

Редактировать: Это может быть более простым способом применить вашу функцию, которая у вас уже есть, но в случае, если у вас огромный фрейм данных, для более быстрого кода ознакомьтесь с ответом @sammywemmy, используя понимание списка.

Ответ №3:

Вы передаете все, dataframe где вам просто нужно передать лямбда-переменную ( x ).

 df[['cat','subcat']] = df['remark'].apply(lambda x: pd.Series([*conditions(x)]))
  

* в iterables можно unpack использовать их, поэтому вам не нужно вызывать одну и ту же функцию дважды для извлечения выходных данных. Возможно, компилятор решает это, но я так не думаю…

Ответ №4:

Вы можете использовать series.replace со словарем сопоставления

 df['cat'] = df.remark.replace({'Category1': 'insufficient',
    'Category2': 'insufficient', 'Category3': 'Duplicate'})
df['subcat'] = df.remark.replace({'Category1': 'resolution',
    'Category2': 'information', 'Category3': 'ID repeated'})

print(df)
      remark     desc           cat       subcat
0         NA  Present            NA           NA
1         NA  Present            NA           NA
2  Category1       NA  insufficient   resolution
3  Category2  Present  insufficient  information
4  Category3       NA     Duplicate  ID repeated