การใช้ฟังก์ชั่นที่มีหลายอาร์กิวเมนต์เพื่อสร้างคอลัมน์แพนด้าใหม่


165

ฉันต้องการสร้างคอลัมน์ใหม่ในpandasกรอบข้อมูลโดยใช้ฟังก์ชั่นกับสองคอลัมน์ที่มีอยู่ ทำตามคำตอบนี้ฉันสามารถสร้างคอลัมน์ใหม่เมื่อฉันต้องการเพียงหนึ่งคอลัมน์เป็นอาร์กิวเมนต์:

import pandas as pd
df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})

def fx(x):
    return x * x

print(df)
df['newcolumn'] = df.A.apply(fx)
print(df)

อย่างไรก็ตามฉันไม่สามารถหาวิธีทำสิ่งเดียวกันได้เมื่อฟังก์ชันต้องการอาร์กิวเมนต์หลายตัว ตัวอย่างเช่นฉันจะสร้างคอลัมน์ใหม่โดยผ่านคอลัมน์ A และคอลัมน์ B ไปยังฟังก์ชันด้านล่างได้อย่างไร

def fxy(x, y):
    return x * y

คำตอบ:


136

อีกทางเลือกหนึ่งคุณสามารถใช้ฟังก์ชันพื้นฐาน numpy:

>>> import numpy as np
>>> df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})
>>> df['new_column'] = np.multiply(df['A'], df['B'])
>>> df
    A   B  new_column
0  10  20         200
1  20  30         600
2  30  10         300

หรือ vectorize ฟังก์ชั่นโดยพลการในกรณีทั่วไป:

>>> def fx(x, y):
...     return x*y
...
>>> df['new_column'] = np.vectorize(fx)(df['A'], df['B'])
>>> df
    A   B  new_column
0  10  20         200
1  20  30         600
2  30  10         300

2
ขอบคุณสำหรับคำตอบ! ฉันอยากรู้ว่านี่เป็นวิธีแก้ปัญหาที่เร็วที่สุดหรือไม่
MV23

6
เวอร์ชัน vectorized ที่ใช้np.vectorize()นั้นรวดเร็วอย่างน่าอัศจรรย์ ขอบคุณ.
stackoverflowuser2010

นี่คือทางออกที่มีประโยชน์ หากขนาดของอินพุตอาร์กิวเมนต์ของฟังก์ชัน x และ y ไม่เท่ากันคุณจะได้รับข้อผิดพลาด ในกรณีนั้นโซลูชัน @RomanPekar ทำงานได้โดยไม่มีปัญหา ฉันไม่ได้เปรียบเทียบประสิทธิภาพ
Ehsan Sadr

ฉันรู้ว่านี่เป็นคำตอบที่เก่า แต่: ฉันมีกรณีขอบซึ่งnp.vectorizeไม่ได้ทำงาน เหตุผลก็คือคอลัมน์หนึ่งในนั้นเป็นประเภทpandas._libs.tslibs.timestamps.Timestampที่ได้รับการเปลี่ยนเป็นประเภทnumpy.datetime64โดย vectorization ทั้งสองประเภทไม่สามารถใช้แทนกันได้ทำให้ฟังก์ชันทำงานได้ไม่ดี ข้อเสนอแนะเกี่ยวกับเรื่องนี้? (นอกเหนือจาก.applyนี้ดูเหมือนจะหลีกเลี่ยง)
ElRudi

สุดยอดทางออก! ในกรณีที่ทุกคนสงสัยว่า vectorize ทำงานได้ดีและเร็วสุดสำหรับฟังก์ชั่นการเปรียบเทียบสตริงเช่นกัน
infiniteloop

227

คุณสามารถไปกับตัวอย่าง @greenAfrican หากเป็นไปได้ที่คุณจะเขียนฟังก์ชันใหม่ แต่ถ้าคุณไม่ต้องการเขียนฟังก์ชั่นของคุณใหม่คุณสามารถใส่มันเข้าไปในฟังก์ชั่นที่ไม่ระบุชื่อได้เช่น:

>>> def fxy(x, y):
...     return x * y

>>> df['newcolumn'] = df.apply(lambda x: fxy(x['A'], x['B']), axis=1)
>>> df
    A   B  newcolumn
0  10  20        200
1  20  30        600
2  30  10        300

4
นี่เป็นเคล็ดลับที่ยอดเยี่ยมและจะทิ้งการอ้างอิงคอลัมน์ไว้ใกล้กับการเรียกใช้ (ในความเป็นจริง) ฉันใช้เคล็ดลับนี้และเคล็ดลับผลลัพธ์หลายคอลัมน์ @toto_tico ที่จัดทำขึ้นเพื่อสร้าง 3 คอลัมน์ในฟังก์ชั่น 4 คอลัมน์ ใช้งานได้ดี!
RufusVS

7
ว้าวดูเหมือนว่าคุณเป็นคนเดียวที่ไม่ได้มุ่งเน้นตัวอย่างเล็ก ๆ น้อย ๆ ของ OP แต่ให้ความสำคัญกับปัญหาทั้งหมดขอบคุณสิ่งที่ฉันต้องการ! :)
Matt

38

วิธีนี้จะช่วยแก้ปัญหา:

df['newcolumn'] = df.A * df.B

คุณสามารถทำได้:

def fab(row):
  return row['A'] * row['B']

df['newcolumn'] = df.apply(fab, axis=1)

10
คำตอบนี้แก้ตัวอย่างของเล่นนี้และจะเพียงพอสำหรับฉันที่จะเขียนฟังก์ชันจริงของฉันใหม่ แต่ไม่ได้ระบุวิธีใช้ฟังก์ชันที่กำหนดไว้ก่อนหน้านี้โดยไม่ต้องเขียนใหม่ไปยังคอลัมน์อ้างอิง
ไมเคิล

23

หากคุณต้องการสร้างหลายคอลัมน์พร้อมกัน:

  1. สร้างดาต้าเฟรม:

    import pandas as pd
    df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})
  2. สร้างฟังก์ชั่น:

    def fab(row):                                                  
        return row['A'] * row['B'], row['A'] + row['B']
  3. กำหนดคอลัมน์ใหม่:

    df['newcolumn'], df['newcolumn2'] = zip(*df.apply(fab, axis=1))

1
ฉันสงสัยว่าฉันจะสร้างหลายคอลัมน์ได้อย่างไรโดยใช้อย่างใดอย่างหนึ่ง! ฉันใช้สิ่งนี้กับคำตอบของ @Roman Pekar เพื่อสร้างฟังก์ชั่น 3 คอลัมน์, 4 คอลัมน์ออกมา! ใช้งานได้ดี!
RufusVS

15

ไวยากรณ์สะอาดสไตล์ dict มากกว่าหนึ่งแบบ:

df["new_column"] = df.apply(lambda x: x["A"] * x["B"], axis = 1)

หรือ,

df["new_column"] = df["A"] * df["B"]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.