เงื่อนไขแทนที่นุ่น


123

ฉันมี DataFrame และฉันต้องการแทนที่ค่าในคอลัมน์ใดคอลัมน์หนึ่งที่เกินค่าด้วยศูนย์ ฉันคิดว่านี่เป็นวิธีหนึ่งในการบรรลุสิ่งนี้:

df[df.my_channel > 20000].my_channel = 0

ถ้าฉันคัดลอกช่องไปยัง data frame ใหม่มันง่ายมาก:

df2 = df.my_channel 

df2[df2 > 20000] = 0

สิ่งนี้ทำในสิ่งที่ฉันต้องการ แต่ดูเหมือนว่าจะไม่ทำงานกับช่องเป็นส่วนหนึ่งของ DataFrame ดั้งเดิม


พบสิ่งที่ฉันคิดว่าคุณกำลังมองหาอยู่ที่นี่
ฟุตเปียก

คำตอบ:


181

.ixตัวทำดัชนีทำงานได้ดีสำหรับแพนด้าเวอร์ชันก่อน 0.20.0 แต่เนื่องจากแพนด้า 0.20.0 .ixตัวสร้างดัชนีจึงเลิกใช้งานดังนั้นคุณควรหลีกเลี่ยงการใช้ คุณสามารถใช้.locหรือตัวilocสร้างดัชนีแทนได้ คุณสามารถแก้ปัญหานี้ได้โดย:

mask = df.my_channel > 20000
column_name = 'my_channel'
df.loc[mask, column_name] = 0

หรือในบรรทัดเดียว

df.loc[df.my_channel > 20000, 'my_channel'] = 0

maskช่วยให้คุณสามารถเลือกแถวที่df.my_channel > 20000เป็นTrueในขณะที่df.loc[mask, column_name] = 0ชุดค่า 0 ถึงแถวที่เลือกที่ถือในคอลัมน์ที่ชื่อmaskcolumn_name

ปรับปรุง: ในกรณีนี้คุณควรใช้locเพราะถ้าคุณใช้ilocคุณจะได้รับการNotImplementedErrorบอกคุณว่าiLocation ตามการจัดทำดัชนีบูลในชนิดจำนวนเต็มไม่สามารถใช้ได้


82

ลอง

df.loc[df.my_channel > 20000, 'my_channel'] = 0

หมายเหตุ: ตั้งแต่ v0.20.0 ix ได้เลิกใช้งานแล้วเนื่องจากloc/ iloc.


8
ขอบคุณ. ฉันพบวิธีแก้ปัญหาของตัวเองเช่นกันซึ่งก็คือ: df.my_channel [df.my_channel> 20000] = 0
BMichell

2
@BMichell ฉันคิดว่าโซลูชันของคุณอาจเริ่มให้คำเตือนคุณใน 0.13 ยังไม่มีโอกาสได้ลอง
lowtech

ข้อผิดพลาดผลตอบแทน: /opt/anaconda3/envs/python35/lib/python3.5/site-packages/ipykernel_launcher.py:1: SettingWithCopyWarning: กำลังพยายามตั้งค่าบนสำเนาของชิ้นส่วนจาก DataFrame ดูคำเตือนใน เอกสารประกอบ: pandas.pydata.org/pandas-docs/stable/… "" "จุดเริ่มต้นสำหรับการเรียกใช้เคอร์เนล IPython
Rutger Hofste

@RutgerHofste ขอบคุณที่พูดถึงเรื่องนั้น แต่อีกข้อโต้แย้งไม่เคยใช้ Python3
lowtech

34

np.where ฟังก์ชันทำงานดังนี้:

df['X'] = np.where(df['Y']>=50, 'yes', 'no')

ในกรณีของคุณคุณต้องการ:

import numpy as np
df['my_channel'] = np.where(df.my_channel > 20000, 0, df.my_channel)

19

สาเหตุที่ดาต้าเฟรมเดิมของคุณไม่อัปเดตเนื่องจากการจัดทำดัชนีแบบผูกมัดอาจทำให้คุณแก้ไขสำเนาแทนที่จะเป็นมุมมองของดาต้าเฟรมของคุณ เอกสารให้คำแนะนำนี้:

เมื่อตั้งค่าในวัตถุแพนด้าต้องใช้ความระมัดระวังเพื่อหลีกเลี่ยงสิ่งที่เรียกว่าการทำดัชนีแบบล่ามโซ่

คุณมีทางเลือกไม่กี่ทาง: -

loc + การสร้างดัชนีบูลีน

loc อาจใช้สำหรับการตั้งค่าและรองรับบูลีนมาสก์:

df.loc[df['my_channel'] > 20000, 'my_channel'] = 0

mask + การสร้างดัชนีบูลีน

คุณสามารถกำหนดให้กับซีรี่ส์ของคุณ:

df['my_channel'] = df['my_channel'].mask(df['my_channel'] > 20000, 0)

หรือคุณสามารถอัปเดตซีรีส์ของคุณได้:

df['my_channel'].mask(df['my_channel'] > 20000, 0, inplace=True)

np.where + การสร้างดัชนีบูลีน

คุณสามารถใช้ NumPy โดยกำหนดชุดเดิมของคุณเมื่อเงื่อนไขของคุณไม่เป็นที่พอใจ อย่างไรก็ตามสองโซลูชันแรกนั้นสะอาดกว่าเนื่องจากมีการเปลี่ยนแปลงเฉพาะค่าที่ระบุอย่างชัดเจน

df['my_channel'] = np.where(df['my_channel'] > 20000, 0, df['my_channel'])

0

ผมจะใช้lambdaฟังก์ชั่นในSeriesการDataFrameเช่นนี้

f = lambda x: 0 if x>100 else 1
df['my_column'] = df['my_column'].map(f)

ฉันไม่ยืนยันว่านี่เป็นวิธีที่มีประสิทธิภาพ แต่ก็ใช้ได้ดี


3
สิ่งนี้ไม่มีประสิทธิภาพและไม่แนะนำเนื่องจากเกี่ยวข้องกับลูประดับ Python ในการดำเนินการที่ชาญฉลาด
jpp

ขอขอบคุณคุณผมคิดว่าเราสามารถใช้ ที่นี่เช่นloc df.loc[: , 'my_column'] = df['my_column'].map(f)ไม่รู้ว่าเร็วเหมือนที่คุณเพิ่มไว้ด้านล่างหรือเปล่า
Ozkan Serttas

2
ไม่ยังคงช้าในขณะที่คุณยังคงใช้งานแบบ row-wise แทนที่จะเป็นแบบคอลัมน์
jpp

0

ลองสิ่งนี้:

df.my_channel = df.my_channel.where(df.my_channel <= 20000, other= 0)

หรือ

df.my_channel = df.my_channel.mask(df.my_channel > 20000, other= 0)

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