วิธีการเลือกแถวที่มีค่า Null ตั้งแต่หนึ่งตัวขึ้นไปจาก DataFrame ของแพนด้าโดยไม่แสดงรายการคอลัมน์อย่างชัดเจน


233

ฉันมีชื่อไฟล์ที่มีแถว ~ 300K และ ~ 40 คอลัมน์ ฉันต้องการตรวจสอบว่าแถวใด ๆ มีค่า Null หรือไม่และใส่ 'Null'-Row เหล่านี้ลงใน dataframe ที่แยกต่างหากเพื่อให้ฉันสามารถสำรวจได้อย่างง่ายดาย

ฉันสามารถสร้างหน้ากากได้อย่างชัดเจน:

mask = False
for col in df.columns: 
    mask = mask | df[col].isnull()
dfnulls = df[mask]

หรือฉันสามารถทำสิ่งที่ชอบ:

df.ix[df.index[(df.T == np.nan).sum() > 1]]

มีวิธีที่สง่างามกว่าในการทำ (ระบุแถวที่มีค่า Null) หรือไม่?

คำตอบ:


384

[อัปเดตเพื่อปรับให้เข้ากับทันสมัยpandasซึ่งisnullเป็นวิธีการของDataFrame.. ]

คุณสามารถใช้isnullและanyสร้างซีรีส์บูลีนและใช้ดัชนีนั้นในดัชนีของคุณ:

>>> df = pd.DataFrame([range(3), [0, np.NaN, 0], [0, 0, np.NaN], range(3), range(3)])
>>> df.isnull()
       0      1      2
0  False  False  False
1  False   True  False
2  False  False   True
3  False  False  False
4  False  False  False
>>> df.isnull().any(axis=1)
0    False
1     True
2     True
3    False
4    False
dtype: bool
>>> df[df.isnull().any(axis=1)]
   0   1   2
1  0 NaN   0
2  0   0 NaN

[สำหรับเก่าpandas:]

คุณสามารถใช้ฟังก์ชั่นisnullแทนวิธีการ:

In [56]: df = pd.DataFrame([range(3), [0, np.NaN, 0], [0, 0, np.NaN], range(3), range(3)])

In [57]: df
Out[57]: 
   0   1   2
0  0   1   2
1  0 NaN   0
2  0   0 NaN
3  0   1   2
4  0   1   2

In [58]: pd.isnull(df)
Out[58]: 
       0      1      2
0  False  False  False
1  False   True  False
2  False  False   True
3  False  False  False
4  False  False  False

In [59]: pd.isnull(df).any(axis=1)
Out[59]: 
0    False
1     True
2     True
3    False
4    False

นำไปสู่ค่อนข้างกะทัดรัด:

In [60]: df[pd.isnull(df).any(axis=1)]
Out[60]: 
   0   1   2
1  0 NaN   0
2  0   0 NaN

75
def nans(df): return df[df.isnull().any(axis=1)]

เมื่อใดก็ตามที่คุณต้องการคุณสามารถพิมพ์:

nans(your_dataframe)

1
df[df.isnull().any(axis=1)]ทำงาน UserWarning: Boolean Series key will be reindexed to match DataFrame index.แต่พ่น เราจะเขียนสิ่งนี้อย่างชัดเจนมากขึ้นและในวิธีที่ไม่เรียกข้อความเตือนนั้นได้อย่างไร
Vishal

3
@vishal ฉันคิดว่าสิ่งที่คุณต้องทำคือเพิ่ม loc แบบนี้ df.loc[df.isnull().any(axis=1)]
James Draper


0

.any()และ.all()ยอดเยี่ยมสำหรับกรณีร้ายแรง แต่ไม่ใช่เมื่อคุณกำลังค้นหาค่า Null จำนวนหนึ่ง นี่เป็นวิธีที่ง่ายที่สุดในการทำสิ่งที่ฉันเชื่อว่าคุณกำลังขอ มันค่อนข้างละเอียด แต่ใช้งานได้

import pandas as pd
import numpy as np

# Some test data frame
df = pd.DataFrame({'num_legs':          [2, 4,      np.nan, 0, np.nan],
                   'num_wings':         [2, 0,      np.nan, 0, 9],
                   'num_specimen_seen': [10, np.nan, 1,     8, np.nan]})

# Helper : Gets NaNs for some row
def row_nan_sums(df):
    sums = []
    for row in df.values:
        sum = 0
        for el in row:
            if el != el: # np.nan is never equal to itself. This is "hacky", but complete.
                sum+=1
        sums.append(sum)
    return sums

# Returns a list of indices for rows with k+ NaNs
def query_k_plus_sums(df, k):
    sums = row_nan_sums(df)
    indices = []
    i = 0
    for sum in sums:
        if (sum >= k):
            indices.append(i)
        i += 1
    return indices

# test
print(df)
print(query_k_plus_sums(df, 2))

เอาท์พุต

   num_legs  num_wings  num_specimen_seen
0       2.0        2.0               10.0
1       4.0        0.0                NaN
2       NaN        NaN                1.0
3       0.0        0.0                8.0
4       NaN        9.0                NaN
[2, 4]

จากนั้นหากคุณเป็นเหมือนฉันและต้องการล้างแถวเหล่านั้นออกไปคุณแค่เขียนสิ่งนี้:

# drop the rows from the data frame
df.drop(query_k_plus_sums(df, 2),inplace=True)
# Reshuffle up data (if you don't do this, the indices won't reset)
df = df.sample(frac=1).reset_index(drop=True)
# print data frame
print(df)

เอาท์พุท:

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