การแก้ไขเซ็ตย่อยของแถวใน pafas dataframe


143

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

ฉันพยายามต่อไปนี้

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

และ

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

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


หากคุณกำลังมองหาวิธีแก้ปัญหาที่รวดเร็วมากให้ใช้ NumPy whereตามที่เห็นในวิธีแก้ปัญหาด้านล่างนี้
Ted Petrou

คำตอบ:


243

ใช้.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 จะส่งคืนสำเนาของผลลัพธ์และบางครั้งก็ส่งคืนมุมมองบนวัตถุต้นฉบับ ตามเอกสารที่นี่พฤติกรรมนี้ขึ้นอยู่กับพฤติกรรมพื้นฐาน ฉันพบว่าการเข้าถึงทุกสิ่งในการดำเนินการเดียว (แทนที่จะเป็น [หนึ่ง] [สอง]) มีแนวโน้มที่จะทำงานเพื่อตั้งค่ามากกว่า


ส่วนที่สองของคำตอบนี้เป็นคำตอบที่ดีสำหรับคำถามที่ไม่ได้ถามแม้แต่ ;-) ฉันสงสัยว่านี่ยังคงเป็นคำตอบของ pandas โดยเฉพาะ b / c เป็นการละเมิด DRY ที่เห็นได้ชัดแม้ว่าฉันคิดว่ามันอยู่ใน ข้อเท็จจริงที่จำเป็นในการละเมิด DRY เนื่องจากข้อ จำกัด ของการฝึกงานภายในนุ่น? (ฉันอาจโพสต์คำถามประเภทนี้อย่างละเอียดโดยละเอียด แต่ต้องการดูว่าคุณมีคำตอบอย่างรวดเร็วก่อนที่ฉันจะทำหรือไม่)
34424

วิธีเซ็ตย่อย Dataframe ที่ไม่มีชื่อคอลัมน์, วิธีเซ็ตย่อย df โดยใช้ดัชนี? df.loc [df [0] == 0] ไม่ทำงาน ... เป็นทางเลือกอะไร? ขอขอบคุณ
amipro

89

นี่คือจากเอกสารหมีแพนด้าในการจัดทำดัชนีขั้นสูง:

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

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

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


2
คุณทำวันของฉัน คำอธิบายที่ชัดเจน
TwinPenguins

1
ใช่อย่างloc[selection criteria, columns I want]สมบูรณ์ยึดติดอยู่กับความคิดของคุณ ...
38411

29

เริ่มต้นจากหมีแพนด้า 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

เราสามารถใช้ตรรกะเงื่อนไขหรือการดำเนินการใด ๆ ที่ส่งกลับชุดของ booleans เพื่อสร้างอาร์เรย์ของ booleans ในตัวอย่างด้านบนเราต้องการสิ่งใด ๆrowsที่มี a 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

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


11

สำหรับการเพิ่มความเร็วขนาดใหญ่ให้ใช้ฟังก์ชันของ 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)

Numpy whereนั้นเร็วกว่า 4x


ฉันอยากรู้เกี่ยวกับสิ่งนี้ดังนั้นฉันจึงทดสอบด้วยตนเองและความแตกต่างนั้นยิ่งใหญ่กว่าการใช้พารามิเตอร์อื่น ๆ Numpy เร็วขึ้นเกือบ 10 เท่าเมื่อทำการแทนที่ 0s ด้วยจำนวนเต็มแทนที่จะเป็น np.nan ฉันสงสัยว่าอะไรต้องใช้เวลาเพิ่ม
Alexander

มันเป็นสิ่งจำเป็นที่จะใช้.valuesในnp.where(df.a.values == 0, np.nan, df.b.values)? ดูเหมือนว่าnp.where(df.a == 0, np.nan, df.b)ยังใช้งานได้?
hsl

4

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

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