ใช้ฟังก์ชัน Python กับคอลัมน์แพนด้าหนึ่งคอลัมน์และใช้ผลลัพธ์กับหลายคอลัมน์

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สร้างแต่ละคอลัมน์รูป dataframe ที่แล้วคุณสามารถกำหนดให้และcatsubcat

เหตุผลที่ฉันแนะนำให้มีการทำความเข้าใจรายการเป็นเพราะสิ่งที่คุณกำลังจัดการกับ Strings และใน Pandas การทำงานกับสตริงผ่าน vanilla python นั้นมักจะไม่เร็วกว่า 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)]))

*บน iterables 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