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

Aug 20 2020

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

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

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

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

df = pd.DataFrame(dict) 

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

          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)

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

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

Огромное спасибо.

Ответы

2 sammywemmy Aug 20 2020 at 04:10

Один из способов обойти это - составить список:

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, работа со строками через ванильный питон чаще всего выполняется быстрее. Кроме того, с пониманием списка обработка выполняется один раз, вам не нужно применять функцию условий, а затем вызывать pd.Series. Это дает вам более высокую скорость. Тестирование подтвердит или опровергнет это.

2 dm2 Aug 20 2020 at 04:12

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

 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

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

1 Quentin Aug 20 2020 at 04:13

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

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

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

RichieV Aug 20 2020 at 04:11

Вы можете использовать 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