หลาม pandas: ใช้ฟังก์ชั่นที่มีข้อโต้แย้งกับซีรีส์


147

ฉันต้องการใช้ฟังก์ชั่นที่มีข้อโต้แย้งกับชุดใน python python:

x = my_series.apply(my_function, more_arguments_1)
y = my_series.apply(my_function, more_arguments_2)
...

เอกสารอธิบายการสนับสนุนสำหรับวิธีการใช้ แต่ก็ไม่ได้ยอมรับข้อโต้แย้งใด ๆ มีวิธีอื่นที่ยอมรับการขัดแย้งไหม? หรือมิฉะนั้นฉันไม่มีวิธีแก้ปัญหาง่ายๆ

อัปเดต (ตุลาคม 2017): โปรดทราบว่าเนื่องจากคำถามนี้ถูกถามตั้งแต่แรกว่าแพนด้าapply()ได้รับการอัปเดตเพื่อจัดการอาร์กิวเมนต์ตำแหน่งและคำหลักและลิงก์เอกสารด้านบนตอนนี้สะท้อนให้เห็นแล้วและแสดงวิธีรวมอาร์กิวเมนต์ประเภทใดประเภทหนึ่ง


3
ทำไมไม่เพียงใช้functools.partialหรือstarmap?
Joel Cornett

คำตอบ:


170

รุ่นใหม่ของหมีแพนด้าจะช่วยให้คุณสามารถส่งผ่านอาร์กิวเมนต์พิเศษ (ดูเอกสารใหม่ ) ดังนั้นตอนนี้คุณสามารถทำได้:

my_series.apply(your_function, args=(2,3,4), extra_kw=1)

อาร์กิวเมนต์ตำแหน่งจะถูกเพิ่มหลังจากองค์ประกอบของซีรีส์


สำหรับแพนด้ารุ่นเก่า:

เอกสารอธิบายอย่างชัดเจน วิธีการใช้รับฟังก์ชั่นหลามซึ่งควรมีพารามิเตอร์เดียว หากคุณต้องการส่งพารามิเตอร์เพิ่มเติมคุณควรใช้functools.partialตามที่ Joel Cornett แนะนำไว้ในความคิดเห็นของเขา

ตัวอย่าง:

>>> import functools
>>> import operator
>>> add_3 = functools.partial(operator.add,3)
>>> add_3(2)
5
>>> add_3(7)
10

partialนอกจากนี้คุณยังสามารถส่งผ่านข้อโต้แย้งคำหลักที่ใช้

อีกวิธีหนึ่งก็คือการสร้างแลมบ์ดา:

my_series.apply((lambda x: your_func(a,b,c,d,...,x)))

แต่ฉันคิดว่าการใช้partialดีกว่า


12
สำหรับวิธีการใช้ DataFrame ยอมรับการargsโต้แย้งซึ่งเป็น tuple ถืออาร์กิวเมนต์ตำแหน่งเพิ่มเติมหรือ ** kwds สำหรับคนที่มีชื่อ ฉันสร้างปัญหาเพื่อให้มีสิ่งนี้สำหรับ Series.apply () github.com/pydata/pandas/issues/1829
Wouter Overmeire

28
คุณลักษณะได้รับการดำเนินการแล้วจะมีการเปิดตัวแพนด้าที่กำลังจะจัดขึ้น
Wes McKinney

4
นี่เป็นคำตอบที่ดี แต่ 2/3 แรกในตอนนี้ล้าสมัยไปแล้วจริงๆ IMO คำตอบนี้อาจได้รับการปรับปรุงอย่างดีเพียงแค่เป็นลิงก์ไปยังเอกสารใหม่บวกกับตัวอย่างสั้น ๆ ของการใช้งานกับตำแหน่งและ / หรือ args คำหลัก เพียงแค่ FWIW และไม่ใช่คำวิจารณ์ของคำตอบดั้งเดิมเพียงได้รับประโยชน์จากการอัปเดต IMO โดยเฉพาะอย่างยิ่งเนื่องจากเป็นคำตอบที่อ่านบ่อย
JohnE

@watsonic เอกสารได้รับการปรับปรุงและคลิกที่ลิงค์เก่านำไปสู่เอกสารปัจจุบันซึ่งตอนนี้ตอบคำถามได้ดีมาก
JohnE

หมายเหตุ: หากคุณจะผ่านอาร์กิวเมนต์สตริงเดียวเช่น'abc'นั้นจะได้รับการประเมินว่าเป็นสามข้อโต้แย้งargs=('abc') ('a', 'b', 'c')เพื่อหลีกเลี่ยงปัญหานี้คุณต้องผ่าน tuple ที่มีสตริงและการทำเช่นนั้นรวมถึงเครื่องหมายจุลภาคต่อท้าย:args=('abc',)
Rocky K

82

ขั้นตอน:

  1. สร้างดาต้าเฟรม
  2. สร้างฟังก์ชั่น
  3. ใช้อาร์กิวเมนต์ที่มีชื่อของฟังก์ชันในคำสั่ง Apply

ตัวอย่าง

x=pd.DataFrame([1,2,3,4])  

def add(i1, i2):  
    return i1+i2

x.apply(add,i2=9)

ผลลัพธ์ของตัวอย่างนี้คือแต่ละหมายเลขใน dataframe จะถูกเพิ่มเข้าไปในหมายเลข 9

    0
0  10
1  11
2  12
3  13

คำอธิบาย:

ฟังก์ชัน "เพิ่ม" มีสองพารามิเตอร์: i1, i2 พารามิเตอร์แรกจะเป็นค่าใน data frame และอย่างที่สองคือสิ่งที่เราส่งไปยังฟังก์ชัน "Apply" ในกรณีนี้เรากำลังส่งผ่าน "9" ไปยังฟังก์ชันใช้โดยใช้อาร์กิวเมนต์คำหลัก "i2"


2
สิ่งที่ฉันกำลังมองหา สิ่งนี้ไม่จำเป็นต้องสร้างฟังก์ชั่นที่กำหนดเองเพื่อจัดการกับ Series (หรือ df) ที่สมบูรณ์แบบ!
คอนเนอร์

คำถามเดียวที่เหลืออยู่คือ: จะส่งต่ออาร์กิวเมนต์คำหลักไปยังอาร์กิวเมนต์แรกใน add (i1) และทำซ้ำกับ i2 ได้อย่างไร
คอนเนอร์

ฉันคิดว่านี่เป็นคำตอบที่ดีที่สุด
crypdick

43
Series.apply(func, convert_dtype=True, args=(), **kwds)

args : tuple

x = my_series.apply(my_function, args = (arg1,))

11
ขอบคุณ! คุณช่วยอธิบายได้ไหมว่าเพราะเหตุใด args = (arg1,) จึงจำเป็นต้องใช้เครื่องหมายจุลภาคหลังอาร์กิวเมนต์แรก
DrMisha

21
@MishaTeplitskiy คุณจำเป็นต้องใช้เครื่องหมายจุลภาคเพื่อให้ Python เข้าใจเนื้อหาในวงเล็บเพื่อให้มีความยาว 1 เท่า
prooffreader

3
สิ่งที่เกี่ยวกับการวางใน args funcสำหรับ ดังนั้นถ้าฉันต้องการที่จะใช้pd.Series.mean(axis=1)ฉันจะใส่ในaxis=1?
ตาราง Bobby น้อย

1
คุณสามารถเพิ่มอาร์กิวเมนต์คำหลักโดยไม่ใช้พารามิเตอร์ <args> (เช่น: x = my_series.apply (my_function, keyword_arg = arg1) โดยที่ <keyword_arg> อยู่ท่ามกลางพารามิเตอร์อินพุตของ my_function)
lev

1
คำตอบนี้สั้นเกินไปและไม่อธิบายอะไรเลย
FistOfFury

23

คุณสามารถส่งผ่านจำนวนอาร์กิวเมนต์ใด ๆ ไปยังฟังก์ชันที่applyเรียกใช้ผ่านอาร์กิวเมนต์ที่ไม่มีชื่อใด ๆ ส่งผ่านเป็น tuple ไปยังargsพารามิเตอร์หรือผ่านอาร์กิวเมนต์คำหลักอื่น ๆ ที่จับภายในเป็นพจนานุกรมโดยkwdsพารามิเตอร์

ตัวอย่างเช่นลองสร้างฟังก์ชั่นที่คืนค่า True สำหรับค่าระหว่าง 3 ถึง 6 และเท็จอย่างอื่น

s = pd.Series(np.random.randint(0,10, 10))
s

0    5
1    3
2    1
3    1
4    6
5    0
6    3
7    4
8    9
9    6
dtype: int64

s.apply(lambda x: x >= 3 and x <= 6)

0     True
1     True
2    False
3    False
4     True
5    False
6     True
7     True
8    False
9     True
dtype: bool

ฟังก์ชั่นที่ไม่ระบุชื่อนี้ไม่ยืดหยุ่นมาก มาสร้างฟังก์ชั่นปกติพร้อมอาร์กิวเมนต์สองตัวเพื่อควบคุมค่า min และค่าสูงสุดที่เราต้องการในซีรี่ส์ของเรา

def between(x, low, high):
    return x >= low and x =< high

เราสามารถทำซ้ำเอาต์พุตของฟังก์ชันแรกโดยส่งอาร์กิวเมนต์ที่ไม่มีชื่อไปที่args:

s.apply(between, args=(3,6))

หรือเราสามารถใช้อาร์กิวเมนต์ที่มีชื่อ

s.apply(between, low=3, high=6)

หรือแม้กระทั่งการรวมกันของทั้งสอง

s.apply(between, args=(3,), high=6)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.