去除含有NaN、inf等數值的樣本的方法


  關於刪除數據集中含有NaNinf等異常值,有很多種方法,在stackoverflow的這個問題下,高票回答中使用的方法

df[~df.isin([np.nan, np.inf, -np.inf]).any(1)]

在某些情況下並不可行,原因在於所使用的isin是基於等號==進行判斷數值是否相等的,而在Python中運行np.nan == np.nan時,結果為False,故而在有些數據集下無法刪除含有NaN的樣本(按理說應該在所有數據集下均無法刪除含有NaN的樣本才對,但是在某些數據集下又能夠刪除,比如上述stackoverflow帖子中的情況,目前還是沒有完全弄懂)。
  如果一定要用類似於上述isin的方式刪除含有NaN的樣本,可以自己寫一個NaN類(見參考鏈接3最后一個回答),用np.isnan()來判斷兩個NaN值是否相等,因為np.isnan(np.nan)返回的是True。具體方法如下:

import numpy as np

class NaN():
    def __eq__(self, v):
        return np.isnan(v)

    def __hash__(self):
        return hash(np.nan)

nan = NaN()
df[~df.isin([nan]).any(1)]

另外,雖然np.nan == np.nan時,結果為False,但是np.inf == np.inf時,結果為True。所以可以直接用df[~df.isin([inf]).any(1)]來刪除含有inf的樣本,無須單獨寫一個類。
  如果不想像上面那樣自己寫一個類來刪除含有NaN的樣本,最簡單也比較保險的做法就是在

df[~df.isin([np.nan, np.inf, -np.inf]).any(1)]

后面再加一個dropna(),即用

df[~df.isin([np.nan, np.inf, -np.inf]).any(1)].dropna()

便可同時清除含有NaNinf-inf等異常值的樣本,當然isin里面的np.nan可要可不要。
  還有一種處理方式是將除NaN的其余異常值均替換成NaN,最后統一dropna()一下即可,

df.replace([np.inf, -np.inf], np.nan).dropna()

最后,這里有一篇文章詳細地介紹了Python中NoneNaN的區別,有興趣的可以學習學習。

參考

[1] https://stackoverflow.com/questions/45745085/python-pandas-how-to-remove-nan-and-inf-values
[2] https://stackoverflow.com/questions/1565164/what-is-the-rationale-for-all-comparisons-returning-false-for-ieee754-nan-values
[3] https://stackoverflow.com/questions/31833635/pandas-checking-for-nan-not-working-using-isin


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM