วิธีการวางแถวของ Pandas DataFrame ที่มีค่าในคอลัมน์หนึ่งคือ NaN


753

ฉันมีสิ่งนี้DataFrameและต้องการเฉพาะระเบียนที่ไม่มีEPSคอลัมน์NaN:

>>> df
                 STK_ID  EPS  cash
STK_ID RPT_Date                   
601166 20111231  601166  NaN   NaN
600036 20111231  600036  NaN    12
600016 20111231  600016  4.3   NaN
601009 20111231  601009  NaN   NaN
601939 20111231  601939  2.5   NaN
000001 20111231  000001  NaN   NaN

... คือบางสิ่งบางอย่างที่ต้องการdf.drop(....)รับข้อมูลชื่อนี้:

                  STK_ID  EPS  cash
STK_ID RPT_Date                   
600016 20111231  600016  4.3   NaN
601939 20111231  601939  2.5   NaN

ฉันจะทำอย่างไร



176
df.dropna(subset = ['column1_name', 'column2_name', 'column3_name'])
osa

คำตอบ:


655

อย่าวางลงไปใช้แถวที่ EPS ไม่ใช่ NA:

df = df[df['EPS'].notna()]

470
ฉันขอแนะนำให้ใช้pandas.notnullแทนnp.isfinite
Wes McKinney

11
มีข้อได้เปรียบใด ๆ ในการจัดทำดัชนีและการคัดลอกการวางหล่น?
Robert Muil

9
สร้างข้อผิดพลาด: TypeError: ufunc 'isfinite' ไม่สนับสนุนประเภทอินพุตและอินพุตไม่สามารถเชื่อมโยงกับประเภทที่รองรับได้อย่างปลอดภัยตามกฎการคัดเลือก '' ปลอดภัย ''
Philipp Schwarz

4
@ wes-mckinney ได้โปรดแจ้งให้เราทราบว่า dropna () เป็นตัวเลือกที่ดีกว่า pandas.notnull ในกรณีนี้หรือไม่ ถ้าเป็นเช่นนั้นทำไม
stormfield

4
@PhilippSchwarz ข้อผิดพลาดนี้เกิดขึ้นหากคอลัมน์ ( EPSในตัวอย่าง) มีสตริงหรือประเภทอื่น ๆ ที่ไม่สามารถย่อยnp.isfinite()ได้ ฉันแนะนำให้ใช้pandas.notnull()ที่จะจัดการเรื่องนี้อย่างไม่เห็นแก่ตัว
normanius

902

คำถามนี้ได้รับการแก้ไขแล้ว แต่ ...

... ยังพิจารณาวิธีการแก้ปัญหาโดย Wouter ในความคิดเห็นเดิมของเขา ความสามารถในการจัดการข้อมูลที่หายไปรวมถึงdropna()ถูกสร้างขึ้นในแพนด้าอย่างชัดเจน นอกเหนือจากการปรับปรุงประสิทธิภาพที่อาจเกิดขึ้นมากกว่าการทำด้วยตนเองฟังก์ชั่นเหล่านี้ยังมาพร้อมกับตัวเลือกที่หลากหลายซึ่งอาจเป็นประโยชน์

In [24]: df = pd.DataFrame(np.random.randn(10,3))

In [25]: df.iloc[::2,0] = np.nan; df.iloc[::4,1] = np.nan; df.iloc[::3,2] = np.nan;

In [26]: df
Out[26]:
          0         1         2
0       NaN       NaN       NaN
1  2.677677 -1.466923 -0.750366
2       NaN  0.798002 -0.906038
3  0.672201  0.964789       NaN
4       NaN       NaN  0.050742
5 -1.250970  0.030561 -2.678622
6       NaN  1.036043       NaN
7  0.049896 -0.308003  0.823295
8       NaN       NaN  0.637482
9 -0.310130  0.078891       NaN

In [27]: df.dropna()     #drop all rows that have any NaN values
Out[27]:
          0         1         2
1  2.677677 -1.466923 -0.750366
5 -1.250970  0.030561 -2.678622
7  0.049896 -0.308003  0.823295

In [28]: df.dropna(how='all')     #drop only if ALL columns are NaN
Out[28]:
          0         1         2
1  2.677677 -1.466923 -0.750366
2       NaN  0.798002 -0.906038
3  0.672201  0.964789       NaN
4       NaN       NaN  0.050742
5 -1.250970  0.030561 -2.678622
6       NaN  1.036043       NaN
7  0.049896 -0.308003  0.823295
8       NaN       NaN  0.637482
9 -0.310130  0.078891       NaN

In [29]: df.dropna(thresh=2)   #Drop row if it does not have at least two values that are **not** NaN
Out[29]:
          0         1         2
1  2.677677 -1.466923 -0.750366
2       NaN  0.798002 -0.906038
3  0.672201  0.964789       NaN
5 -1.250970  0.030561 -2.678622
7  0.049896 -0.308003  0.823295
9 -0.310130  0.078891       NaN

In [30]: df.dropna(subset=[1])   #Drop only if NaN in specific column (as asked in the question)
Out[30]:
          0         1         2
1  2.677677 -1.466923 -0.750366
2       NaN  0.798002 -0.906038
3  0.672201  0.964789       NaN
5 -1.250970  0.030561 -2.678622
6       NaN  1.036043       NaN
7  0.049896 -0.308003  0.823295
9 -0.310130  0.078891       NaN

นอกจากนี้ยังมีตัวเลือกอื่น ๆ (ดูเอกสารได้ที่http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html ) รวมถึงการดร็อปคอลัมน์แทนแถว

มีประโยชน์มาก!


282
df.dropna(subset = ['column_name'])คุณยังสามารถใช้ หวังว่าจะช่วยคนอย่างน้อยหนึ่งคนในอีก 5 วินาทีของ 'สิ่งที่ฉันทำผิด' คำตอบที่ดี +1
James Tobin

10
@ JamesTobin ฉันใช้เวลา 20 นาทีเพื่อเขียนฟังก์ชั่นสำหรับสิ่งนั้น! เอกสารอย่างเป็นทางการมีความลับมาก: "ฉลากตามแกนอื่น ๆ ที่จะต้องพิจารณาเช่นหากคุณวางแถวสิ่งเหล่านี้จะเป็นรายการของคอลัมน์ที่ต้องการรวม" ฉันไม่สามารถเข้าใจสิ่งที่พวกเขาหมายถึง ...
osa

df.dropna(subset = ['column_name'])เป็นสิ่งที่ฉันกำลังมองหา! ขอบคุณ!
amalik2205

123

ฉันรู้ว่าสิ่งนี้ได้รับการตอบแล้ว แต่เพียงเพื่อประโยชน์ของการแก้ปัญหาแพนด้าอย่างหมดจดสำหรับคำถามเฉพาะนี้ซึ่งตรงข้ามกับคำอธิบายทั่วไปจาก Aman (ซึ่งยอดเยี่ยม) และในกรณีที่มีคนอื่นเกิดขึ้นกับเรื่องนี้:

import pandas as pd
df = df[pd.notnull(df['EPS'])]

10
ที่จริงแล้วคำตอบเฉพาะจะเป็น: df.dropna(subset=['EPS'])(ตามคำอธิบายทั่วไปของอามันแน่นอนว่าสิ่งนี้ยังใช้งานได้)
joris

2
notnullก็เป็นสิ่งที่เวสสตรีท (ผู้เขียนของ Pandas) แนะนำไว้ในความคิดเห็นของเขาเกี่ยวกับคำตอบอื่น
เพ้อฝัน

นี่อาจเป็นคำถาม noob แต่เมื่อฉันทำ df [pd.notnull (... ) หรือ df.dropna ดัชนีจะลดลง ดังนั้นหากมีค่า null ใน row-index 10 ใน df ของความยาว 200 dataframe หลังจากเรียกใช้ฟังก์ชั่นการปล่อยมีค่าดัชนีจาก 1 ถึง 9 และ 11 ถึง 200 ต่อไปที่ "re-index"
Aakash Gupta

คุณสามารถทำdf[pd.notnull(df[df.columns[INDEX]])]ที่INDEXจะเป็นคอลัมน์หมายเลขถ้าคุณไม่ทราบชื่อ
ocean800

60

คุณสามารถใช้สิ่งนี้:

df.dropna(subset=['EPS'], how='all', inplace=True)

18
how='all'มีความซ้ำซ้อนที่นี่เนื่องจากคุณเซทย่อย dataframe กับฟิลด์เดียวเท่านั้นดังนั้นทั้งคู่'all'และ'any'จะมีผลเหมือนกัน
Anton Protopopov

35

วิธีแก้ปัญหาที่ง่ายที่สุด:

filtered_df = df[df['EPS'].notnull()]

การแก้ปัญหาข้างต้นเป็นวิธีที่ดีกว่าการใช้ np.isfinite ()


22

คุณสามารถใช้วิธีdataframe notnullหรือ inverse ของisnullหรือnumpy.isnan :

In [332]: df[df.EPS.notnull()]
Out[332]:
   STK_ID  RPT_Date  STK_ID.1  EPS  cash
2  600016  20111231    600016  4.3   NaN
4  601939  20111231    601939  2.5   NaN


In [334]: df[~df.EPS.isnull()]
Out[334]:
   STK_ID  RPT_Date  STK_ID.1  EPS  cash
2  600016  20111231    600016  4.3   NaN
4  601939  20111231    601939  2.5   NaN


In [347]: df[~np.isnan(df.EPS)]
Out[347]:
   STK_ID  RPT_Date  STK_ID.1  EPS  cash
2  600016  20111231    600016  4.3   NaN
4  601939  20111231    601939  2.5   NaN

18

วิธีที่ง่ายและสะดวก

df.dropna(subset=['EPS'],inplace=True)

แหล่งที่มา: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html


inplace=TrueDataFrame.dropna()เป็นเรื่องที่แปลกประหลาดและมีผลกระทบต่อ ดู: github.com/pandas-dev/pandas/issues/16529
AMC

คำตอบนี้แตกต่างจากคำตอบของ @ Joe อย่างไร นอกจากนี้ inplace จะถูกคัดค้านในที่สุดไม่ควรใช้เลย
misantroop

10

วิธีการแก้ปัญหาอื่นซึ่งใช้ความจริงที่ว่าnp.nan != np.nan:

In [149]: df.query("EPS == EPS")
Out[149]:
                 STK_ID  EPS  cash
STK_ID RPT_Date
600016 20111231  600016  4.3   NaN
601939 20111231  601939  2.5   NaN


2

ในชุดข้อมูลที่มีคอลัมน์จำนวนมากจะดียิ่งขึ้นเพื่อดูว่ามีกี่คอลัมน์ที่มีค่า Null และจำนวนไม่รวม

print("No. of columns containing null values")
print(len(df.columns[df.isna().any()]))

print("No. of columns not containing null values")
print(len(df.columns[df.notna().all()]))

print("Total no. of columns in the dataframe")
print(len(df.columns))

ตัวอย่างเช่นใน dataframe ของฉันมี 82 คอลัมน์ซึ่งมี 19 ค่าอย่างน้อยหนึ่งค่า

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

df = df.drop(df.columns[df.isna().sum()>len(df.columns)],axis = 1)
df = df.dropna(axis = 0).reset_index(drop=True)

หมายเหตุ:โค้ดด้านบนจะลบค่า Null ของคุณทั้งหมด หากคุณต้องการค่า Null ให้ประมวลผลก่อน



0

มันอาจถูกเพิ่มที่ '&' สามารถใช้เพื่อเพิ่มเงื่อนไขเพิ่มเติมเช่น

df = df[(df.EPS > 2.0) & (df.EPS <4.0)]

ขอให้สังเกตว่าเมื่อประเมินข้อความคำสั่งแพนด้าต้องการวงเล็บ


2
ขออภัย OP ต้องการสมการอื่น Btw ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().รหัสของคุณผิดกลับ คุณต้องเพิ่มวงเล็บ - df = df[(df.EPS > 2.0) & (df.EPS <4.0)]แต่ยังไม่ได้คำตอบสำหรับคำถามนี้
jezrael

-1

ด้วยเหตุผลบางอย่างไม่มีคำตอบที่ส่งไปก่อนหน้านี้ทำงานได้สำหรับฉัน วิธีแก้ปัญหาพื้นฐานนี้:

df = df[df.EPS >= 0]

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

df = df[df.EPS <= 0]

สิ่งนี้แตกต่างอย่างสิ้นเชิงใช่มั้ย
AMC

-1

หนึ่งในวิธีการแก้ปัญหาสามารถ

df = df[df.isnull().sum(axis=1) <= Cutoff Value]

อีกวิธีหนึ่งที่สามารถ

df= df.dropna(thresh=(df.shape[1] - Cutoff_value))

ฉันหวังว่าสิ่งเหล่านี้มีประโยชน์

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