การแก้ไขชุดย่อยของแถวใน dataframe ของ pandas

สมมติว่าฉันมี DataFrame แพนด้าที่มีสองคอลัมน์ A และ B ฉันต้องการแก้ไข DataFrame นี้ (หรือสร้างสำเนา) เพื่อให้ B อยู่เสมอ NaN ทุกครั้งที่ A เป็น 0 ฉันจะบรรลุเป้าหมายนั้นได้อย่างไร

ฉันลองทำสิ่งต่อไปนี้

df['A'==0]['B'] = np.nan

และ

df['A'==0]['B'].values.fill(np.nan)

ปราศจากความสำเร็จ.


person Arthur B.    schedule 06.09.2012    source แหล่งที่มา
comment
หากคุณกำลังมองหาวิธีแก้ปัญหาที่รวดเร็วมากให้ใช้ where ของ NumPy ตามที่เห็นใน วิธีแก้ปัญหาด้านล่างนี้   -  person Ted Petrou    schedule 03.11.2017


คำตอบ (5)


ใช้ .loc สำหรับการจัดทำดัชนีตามป้ายกำกับ:

df.loc[df.A==0, 'B'] = np.nan

นิพจน์ df.A==0 จะสร้างชุดบูลีนที่จัดทำดัชนีแถว ส่วน 'B' จะเลือกคอลัมน์ คุณยังสามารถใช้สิ่งนี้เพื่อแปลงชุดย่อยของคอลัมน์ได้ เช่น:

df.loc[df.A==0, 'B'] = df.loc[df.A==0, 'B'] / 2

ฉันไม่รู้เกี่ยวกับแพนด้าภายในมากพอที่จะรู้ว่าเหตุใดจึงใช้งานได้ แต่ปัญหาพื้นฐานคือบางครั้งการจัดทำดัชนีใน DataFrame จะส่งคืนสำเนาของผลลัพธ์ และบางครั้งก็ส่งคืนมุมมองบนออบเจ็กต์ต้นฉบับ ตามเอกสาร ที่นี่ พฤติกรรมนี้ ขึ้นอยู่กับพฤติกรรมตัวเลขที่ซ่อนอยู่ ฉันพบว่าการเข้าถึงทุกสิ่งในการดำเนินการครั้งเดียว (แทนที่จะเป็น [หนึ่ง] [สอง]) มีแนวโน้มที่จะได้ผลมากกว่าสำหรับการตั้งค่า

person BrenBarn    schedule 06.09.2012
comment
ส่วนที่สองของสิ่งนี้เป็นคำตอบที่ดีสำหรับคำถามที่ไม่ได้ถามด้วยซ้ำ ;-) ฉันสงสัยว่านี่ยังคงเป็นคำตอบของแพนด้าตามรูปแบบบัญญัติหรือไม่ โดยเฉพาะอย่างยิ่ง b/c มันเป็นการละเมิด DRY ที่ชัดเจน แม้ว่าฉันจะถือว่ามันอยู่ใน ข้อเท็จจริงที่จำเป็นในการละเมิด DRY เนื่องจากข้อ จำกัด ของแพนด้าภายใน? (ฉันอาจโพสต์คำถามประเภทนี้ทุกประการในรายละเอียดมากขึ้น แต่ต้องการดูว่าคุณมีคำตอบอย่างรวดเร็วก่อนที่จะทำเช่นนั้นหรือไม่) - person JohnE; 12.03.2019
comment
จะสับเซ็ต Dataframe ที่ไม่มีชื่อคอลัมน์ได้อย่างไร จะสับเซ็ต df ด้วยดัชนีได้อย่างไร df.loc[df[0]==0] ใช้งานไม่ได้ ... ทางเลือกอื่นคืออะไร ขอบคุณ - person amipro; 10.04.2019

ที่นี่ มาจากเอกสาร pandas เกี่ยวกับการจัดทำดัชนีขั้นสูง:

ในส่วนนี้จะอธิบายสิ่งที่คุณต้องการอย่างชัดเจน! ปรากฎว่า df.loc (เนื่องจาก .ix เลิกใช้แล้ว - ดังที่หลายๆ คนได้ชี้ให้เห็นด้านล่าง) สามารถใช้สำหรับการแบ่งส่วน/การตัด dataframe ได้อย่างยอดเยี่ยม และ. นอกจากนี้ยังสามารถใช้เพื่อจัดสิ่งของต่างๆ

df.loc[selection criteria, columns I want] = value

คำตอบของเบรนคือการพูดว่า 'หาสถานที่ทั้งหมดที่ df.A == 0 ให้เจอ เลือกคอลัมน์ B แล้วตั้งค่าเป็น np.nan'

person badgley    schedule 26.09.2012
comment
ใช่แล้ว loc[selection criteria, columns I want] ติดอยู่ในใจของคุณอย่างสมบูรณ์แบบ... - person EmEs; 10.01.2019

เริ่มต้นจาก pandas 0.20 ix เลิกใช้แล้ว . วิธีที่ถูกต้องคือการใช้ df.loc

นี่คือตัวอย่างการทำงาน

>>> import pandas as pd 
>>> import numpy as np 
>>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB'))
>>> df.loc[df.A == 0, 'B'] = np.nan
>>> df
   A   B
0  0 NaN
1  1   0
2  0 NaN
>>> 

คำอธิบาย:

ตามที่อธิบายไว้ในเอกสารที่นี่ .loc อิงตามป้ายกำกับเป็นหลัก แต่ยังอาจใช้กับอาร์เรย์บูลีนด้วย

ดังนั้นสิ่งที่เรากำลังทำข้างต้นคือการใช้ df.loc[row_index, column_index] โดย:

  • ใช้ประโยชน์จากข้อเท็จจริงที่ว่า loc สามารถใช้อาร์เรย์บูลีนเป็นมาสก์ที่บอกแพนด้าว่าเราต้องการเปลี่ยนชุดย่อยของแถวใดใน row_index
  • การใช้ประโยชน์จากข้อเท็จจริง loc ยังเป็นป้ายกำกับเพื่อเลือกคอลัมน์โดยใช้ป้ายกำกับ 'B' ใน column_index

เราสามารถใช้ตรรกะ เงื่อนไข หรือการดำเนินการใดๆ ที่ส่งคืนชุดของบูลีนเพื่อสร้างอาร์เรย์ของบูลีน ในตัวอย่างข้างต้น เราต้องการ rows ใดๆ ที่มี 0 ซึ่งเราสามารถใช้ df.A == 0 ได้ ดังที่คุณเห็นในตัวอย่างด้านล่าง ซึ่งจะคืนค่าชุดของบูลีน

>>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB'))
>>> df 
   A  B
0  0  2
1  1  0
2  0  5
>>> df.A == 0 
0     True
1    False
2     True
Name: A, dtype: bool
>>> 

จากนั้น เราใช้อาร์เรย์บูลีนด้านบนเพื่อเลือกและแก้ไขแถวที่จำเป็น:

>>> df.loc[df.A == 0, 'B'] = np.nan
>>> df
   A   B
0  0 NaN
1  1   0
2  0 NaN

สำหรับข้อมูลเพิ่มเติม โปรดดูเอกสารประกอบการจัดทำดัชนีขั้นสูงที่นี่

person Mohamed Ali JAMAOUI    schedule 04.07.2017

หากต้องการเพิ่มความเร็วอย่างมาก ให้ใช้ฟังก์ชัน Where ของ NumPy

ติดตั้ง

สร้าง DataFrame สองคอลัมน์ที่มี 100,000 แถวโดยมีเลขศูนย์บางตัว

df = pd.DataFrame(np.random.randint(0,3, (100000,2)), columns=list('ab'))

วิธีแก้ปัญหาที่รวดเร็วด้วย numpy.where

df['b'] = np.where(df.a.values == 0, np.nan, df.b.values)

การกำหนดเวลา

%timeit df['b'] = np.where(df.a.values == 0, np.nan, df.b.values)
685 µs ± 6.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df.loc[df['a'] == 0, 'b'] = np.nan
3.11 ms ± 17.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

where ของ Numpy เร็วขึ้นประมาณ 4 เท่า

person Ted Petrou    schedule 02.11.2017
comment
ฉันอยากรู้เกี่ยวกับเรื่องนี้ ดังนั้นฉันจึงทดสอบด้วยตัวเอง และความแตกต่างก็ยิ่งใหญ่ยิ่งขึ้นเมื่อใช้พารามิเตอร์อื่น Numpy เร็วกว่าเกือบ 10 เท่าในการแทนที่ 0s ด้วยจำนวนเต็มแทนที่จะเป็น np.nan ฉันสงสัยว่าต้องใช้เวลาพิเศษอะไร - person Alexander; 21.08.2018
comment
จำเป็นต้องใช้ .values ใน np.where(df.a.values == 0, np.nan, df.b.values) หรือไม่ ดูเหมือนว่า np.where(df.a == 0, np.nan, df.b) จะใช้งานได้ด้วยเหรอ? - person hsl; 03.02.2020

หากต้องการแทนที่หลายคอลัมน์ให้แปลงเป็นอาร์เรย์ numpy โดยใช้ .values:

df.loc[df.A==0, ['B', 'C']] = df.loc[df.A==0, ['B', 'C']].values / 2
person Adrien Renaud    schedule 25.10.2017