Pandas: ฉันจะใช้ฟังก์ชัน Apply () สำหรับคอลัมน์เดียวได้อย่างไร


256

ฉันมีกรอบข้อมูลแพนด้าสองคอลัมน์ ฉันต้องการเปลี่ยนค่าของคอลัมน์แรกโดยไม่ส่งผลกระทบต่อค่าที่สองและกลับกรอบข้อมูลทั้งหมดโดยมีการเปลี่ยนแปลงค่าของคอลัมน์แรก ฉันจะทำเช่นนั้นโดยใช้การสมัครในแพนด้าได้อย่างไร?


4
โปรดโพสต์ข้อมูลตัวอย่างอินพุตและผลลัพธ์ที่ต้องการ
Fabio Lamanna

คุณแทบไม่ควรใช้applyในสถานการณ์เช่นนี้ ดำเนินการในคอลัมน์โดยตรงแทน
Ted Petrou

ตามที่ Ted Petrou พูดไว้ให้หลีกเลี่ยงการใช้applyให้มากที่สุด หากคุณไม่แน่ใจว่าคุณต้องใช้มันคุณอาจจะไม่ ฉันแนะนำให้ดูที่เมื่อใดที่ฉันควรจะใช้แพนด้าใช้ในรหัสของฉัน? .
cs95

คำถามไม่ชัดเจนอย่างสิ้นเชิง: มันใช้ฟังก์ชั่นกับทุกองค์ประกอบของคอลัมน์หรือใช้ฟังก์ชั่นกับคอลัมน์โดยรวม (ตัวอย่างเช่น: ย้อนกลับคอลัมน์)?
Pierre ALBARÈDE

คำตอบ:


336

รับ dataframe ตัวอย่างdfเป็น:

a,b
1,2
2,3
3,4
4,5

สิ่งที่คุณต้องการคือ:

df['a'] = df['a'].apply(lambda x: x + 1)

ที่ส่งคืน:

   a  b
0  2  2
1  3  3
2  4  4
3  5  5

9
applyไม่ควรใช้ในสถานการณ์เช่นนี้
Ted Petrou

5
@TedPetrou คุณพูดถูกมันเป็นเพียงตัวอย่างของวิธีการใช้ฟังก์ชั่นทั่วไปในหนึ่งคอลัมน์เดียวตามที่ OP ถาม
Fabio Lamanna

14
เมื่อฉันลองทำสิ่งนี้ฉันจะได้รับคำเตือนต่อไปนี้: "ค่ากำลังพยายามตั้งค่าบนสำเนาของชิ้นส่วนจาก DataFrame ลองใช้. loc [row_indexer, col_indexer] = ค่าแทน"
dagrun

24
เป็นเรื่องของความอยากรู้: เหตุใดจึงไม่ควรใช้ในสถานการณ์นั้น สถานการณ์เป็นอย่างไรกันแน่?
ลุง Ben Ben

19
@ UncleBenBen โดยทั่วไปapplyใช้การวนรอบภายในแถวที่ช้ากว่าฟังก์ชั่นเวกเตอร์อย่างเช่นdf.a = df.a / 2(ดูคำตอบ Mike Muller)
Fabio Lamanna

66

สำหรับการใช้คอลัมน์เดียวดีกว่าmap()เช่นนี้

df = pd.DataFrame([{'a': 15, 'b': 15, 'c': 5}, {'a': 20, 'b': 10, 'c': 7}, {'a': 25, 'b': 30, 'c': 9}])

    a   b  c
0  15  15  5
1  20  10  7
2  25  30  9



df['a'] = df['a'].map(lambda a: a / 2.)

      a   b  c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9

78
ทำไมmap()ดีกว่าapply()สำหรับคอลัมน์เดียว
ChaimG

2
มันมีประโยชน์มาก ฉันใช้มันเพื่อแยกชื่อไฟล์จากเส้นทางที่เก็บไว้ในคอลัมน์df['file_name'] = df['Path'].map(lambda a: os.path.basename(a))
mmann1123

46
map () ใช้สำหรับ Series (เช่นคอลัมน์เดียว) และดำเนินการกับเซลล์หนึ่งครั้งในขณะที่ใช้ () สำหรับ DataFrame และดำเนินการกับทั้งแถวในแต่ละครั้ง
jpcgt

3
@jpcgt นั่นหมายความว่าแผนที่นั้นเร็วกว่าการใช้งานในกรณีนี้หรือไม่
Viragos

@ChaimG ฉันเห็นระบบปฏิบัติการนี้อธิบายได้ดี: stackoverflow.com/a/19798528/571828
象嘉道

40

คุณไม่จำเป็นต้องมีฟังก์ชั่นเลย คุณสามารถทำงานกับทั้งคอลัมน์ได้โดยตรง

ข้อมูลตัวอย่าง:

>>> df = pd.DataFrame({'a': [100, 1000], 'b': [200, 2000], 'c': [300, 3000]})
>>> df

      a     b     c
0   100   200   300
1  1000  2000  3000

ครึ่งหนึ่งของค่าทั้งหมดในคอลัมน์a:

>>> df.a = df.a / 2
>>> df

     a     b     c
0   50   200   300
1  500  2000  3000

ถ้าฉันต้องการแยกทุกองค์ประกอบในคอลัมน์ด้วย "/" และใช้ส่วนแรกล่ะ
K47

12

แม้ว่าการตอบกลับที่ให้มานั้นถูกต้อง แต่พวกมันก็ปรับเปลี่ยนกรอบข้อมูลเริ่มต้นซึ่งไม่เป็นที่ต้องการเสมอไป (และถ้าให้ OP ขอตัวอย่าง "ใช้apply" มันอาจเป็นเพราะพวกเขาต้องการรุ่นที่ส่งกลับเฟรมข้อมูลใหม่เช่นเดียวกับapply)

สิ่งนี้เป็นไปได้โดยใช้assign: ใช้ได้กับassignคอลัมน์ที่มีอยู่ตามสถานะเอกสาร (เน้นเป็นของฉัน):

กำหนดคอลัมน์ใหม่ให้กับ DataFrame

ส่งคืนวัตถุใหม่ที่มีคอลัมน์เดิมทั้งหมดนอกเหนือจากวัตถุใหม่ คอลัมน์ที่มีอยู่ที่ใหม่ที่ได้รับมอบหมายจะถูกเขียนทับ

ในระยะสั้น:

In [1]: import pandas as pd

In [2]: df = pd.DataFrame([{'a': 15, 'b': 15, 'c': 5}, {'a': 20, 'b': 10, 'c': 7}, {'a': 25, 'b': 30, 'c': 9}])

In [3]: df.assign(a=lambda df: df.a / 2)
Out[3]: 
      a   b  c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9

In [4]: df
Out[4]: 
    a   b  c
0  15  15  5
1  20  10  7
2  25  30  9

โปรดทราบว่าฟังก์ชั่นจะถูกส่งผ่านทั้งชื่อไฟล์ไม่เพียง แต่คอลัมน์ที่คุณต้องการแก้ไขดังนั้นคุณจะต้องแน่ใจว่าคุณเลือกคอลัมน์ที่ถูกต้องในแลมบ์ดาของคุณ


9

หากคุณกังวลเกี่ยวกับความเร็วในการใช้งานของฟังก์ชั่นการใช้งานของคุณและคุณมีชุดข้อมูลขนาดใหญ่ที่จะใช้งานได้คุณสามารถใช้ swifter เพื่อการดำเนินการที่รวดเร็วยิ่งขึ้นนี่เป็นตัวอย่างสำหรับ swifter บนดาต้าดาต้าแพนด้า:

import pandas as pd
import swifter

def fnc(m):
    return m*3+4

df = pd.DataFrame({"m": [1,2,3,4,5,6], "c": [1,1,1,1,1,1], "x":[5,3,6,2,6,1]})

# apply a self created function to a single column in pandas
df["y"] = df.m.swifter.apply(fnc)

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


1

ให้ฉันลองคำนวณที่ซับซ้อนโดยใช้วันที่และเวลาพิจารณาโมฆะหรือช่องว่าง ฉันลด 30 ปีในคอลัมน์วันที่และการใช้applyวิธีตลอดจนlambdaและการแปลงรูปแบบวันที่และเวลา บรรทัดif x != '' else xจะดูแลช่องว่างหรือโมฆะทั้งหมดตามลำดับ

df['Date'] = df['Date'].fillna('')
df['Date'] = df['Date'].apply(lambda x : ((datetime.datetime.strptime(str(x), '%m/%d/%Y') - datetime.timedelta(days=30*365)).strftime('%Y%m%d')) if x != '' else x)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.