如何在 Python Pandas 中比較包含缺失值的兩個 DataFrame


介紹

Pandas 使用 NumPy NaN (np.nan) 物件來表示缺失值。這個 Numpy NaN 值有一些有趣的數學特性。例如,它不等於自身。然而,當與自身比較時,Python None 物件會評估為 True。

操作方法..

讓我們看一些例子來了解 np.nan 的行為。

import pandas as pd
import numpy as np

# Python None Object compared against self.
print(f"Output \n *** {None == None} ")

輸出

*** True


# Numpy nan compared against self.
print(f"Output \n *** {np.nan == np.nan} ")

輸出

*** False


# Is nan > 10 or 1000 ?
print(f"Output \n *** {np.nan > 10} ")

輸出

*** False

傳統上,Series 和 DataFrames 使用等於運算子 == 來進行比較。比較的結果是一個物件。讓我們首先看看如何使用等於運算子。

# create a dataframe with tennis players and their grandslam titles.
df = pd.DataFrame(data={"players": ['Federer', 'Nadal', 'Djokovic', 'Murray','Medvedev','Zverev'],
"titles": [20, 19, 17, 3,np.nan,np.nan]})
# set the index
df.index = df['players']

# sort the index in ascending
df.sort_index(inplace=True, ascending=True)

# check if the index is set
df.index.is_monotonic_increasing

# see records
print(f"Output \n{df}")

輸出

         players    titles
players
Djokovic Djokovic     17.0
Federer  Federer      20.0
Medvedev Medvedev     NaN
Murray   Murray       3.0
Nadal    Nadal        19.0
Zverev Zverev      NaN

1. 為了更好地理解,我們將首先將所有球員與標量值“Federer”進行比較,並檢視結果。

print(f'Output \n {df == "Federer"}')

輸出

          players    titles
players
Djokovic  False       False
Federer   True        False
Medvedev   False      False
Murray     False      False
Nadal      False      False
Zverev     False      False


C:\Users\sasan\anaconda3\lib\site-packages\pandas\core\ops\array_ops.py:253: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison
res_values = method(rvalues)

2. 這按預期工作,但每當您嘗試比較包含缺失值的 DataFrame 時就會出現問題。為了觀察這一點,讓我們將 df 與自身進行比較。

df_compare = df == df
print(f'Output \n {df_compare}')

輸出

players titles
players
Djokovic True True
Federer True True
Medvedev True False
Murray True True
Nadal True True
Zverev True False

3. 乍一看,所有值似乎都是正確的,正如您所期望的那樣。但是,使用 .all 方法檢視每列是否僅包含 True 值(因為我們正在比較兩個相似的物件,對吧?)會產生意外的結果。

print(f'Output \n {df_compare.all()}')

輸出

players True
titles False
dtype: bool

4. 如前所述,發生這種情況是因為缺失值彼此之間不進行相等比較。看,我們清楚地知道 medvedev 和 Zverev 沒有頭銜(即 NaN),所以如果我們新增每列中缺失值的數量,我們應該為頭銜獲得值 2,為球員獲得值 0。讓我們看看會發生什麼。

print(f'Output \n {(df_compare == np.nan).sum()}')

輸出

players 0
titles 0
dtype: int64

5. 以上結果出乎意料,因為 nan 的行為非常不同。

6. 將兩個完整的 DataFrame 彼此比較的正確方法不是使用等於運算子 (==),而是使用 .equals 方法。

此方法將位於相同位置的 NaN 視為相等。

需要注意的是,.eq 方法等效於 ==,而不是 .equals。

print(f'Output \n {df_compare.equals(df_compare)}')

輸出

True

7. 如果您嘗試將兩個 DataFrame 作為單元測試的一部分進行比較,還有另一種方法。assert_frame_equal 函式如果兩個 DataFrame 不相等,則引發 AssertionError。如果兩個 DataFrame 相等,則返回 None。

from pandas.testing import assert_frame_equal
print(f'Output \n {assert_frame_equal(df_compare, df_compare) is None}')

輸出

True

更新於: 2020-11-09

2K+ 閱讀量

開啟您的 職業生涯

透過完成課程獲得認證

開始學習
廣告