首先, 讀入一個 csv 檔案:
import pandas as pd
df = pd.read_csv('/Users/rachel/Sites/pandas/py/pandas/5_handling_missing_data_fillna_dropna_interpolate/weather_data.csv')
df
輸出:
檢視一下 day 列的資料型別:
type(df.day[0])
輸出:
str
所以目前 day 列裡資料型別是字串.
把 day 列裡的資料轉成時間戳, 加上第二個引數 parse_dates=['day'] 即可:
df = pd.read_csv('/Users/rachel/Sites/pandas/py/pandas/5_handling_missing_data_fillna_dropna_interpolate/weather_data.csv', parse_dates=['day'])
輸出:
再檢視一下 day 列的資料型別:
type(df.day[0])
輸出:
pandas._libs.tslibs.timestamps.Timestamp
把 day 列設定為索引列:
df.set_index('day', inplace=True)
輸出:
上面的輸出有很多空值 NaN, 我們要把它改成數字0:
new_df = df.fillna(0)
new_df
輸出:
可以看到所有的 NaN 都變成 0 了. 但其實, 並不是所有的列都適合用 0 來填充, 比如 event 列裡的 0 就沒有實際意義. Pandas 提供了自定義每個列空值填充的方法:
new_df = df.fillna({
'temperature': 0,
'windspeed': 0,
'event': 'no event'
})
new_df
輸出:
下面再介紹幾個在實際應用中更有意義的空值填充方式:
fillna()函式
參考上一行的值填充:
new_df = df.fillna(method='ffill')
參考下一行的值填充:
new_df = df.fillna(method='bfill')
橫向從右向左填充:
new_df = df.fillna(method='bfill', axis='columns')]
橫向從左向右填充:
new_df = df.fillna(method='ffill', axis='columns')
在使用上述幾個填充的方法時, 還可以再加一個引數限定具體要填充幾個格, 比如設定 limit=1, 就意味著只會向下填充一格, 後面的空格不管:
new_df = df.fillna(method='ffill', limit=1)
輸出如下, 可以看到 NaN 的部分就是未被填充的:
interpolate()函式
new_df = df.interpolate()
從輸出中, 可以看出, 這個方法取的是空值前後的中間值:
顯然, 取中間值的方式, 比簡單粗暴地用前面的值填充更為合理, 但是其實還有優化的空間, 就以 temperature 列為例, 原本 1月4日的值是空的, 如果我們取中間值, 就得到了30.0度, 但是從實際意義出發, 我們會認為1月4日的溫度應該與1月5日的溫度更加接近, 而不是1月1日. 所以, 我們可以這樣做:
new_df = df.interpolate(method='time')
輸出:
dropna() 函式
通過這個函式, 可以捨棄掉所有有空值的行:
new_df = df.dropna()
輸出:
我們看到所有有空值的行全部被刪除了, 但是這貌似也不是很合適, 我們只想捨棄所有列都為空值的行, 醬紫就可以了:
new_df = df.dropna(how='all')
輸出:
保留至少有一個列有值的行:
new_df = df.dropna(thresh=1)
輸出:
保留至少有兩個列有值的行:
new_df = df.dropna(thresh=2)
輸出:
補足所缺的日期
dt = pd.date_range('2017-01-01', '2017-01-11')
idx = pd.DatetimeIndex(dt)
df = df.reindex(idx)
df
輸出:
之後, 可以按照上面所講的方法, 根據實際需要填充空值.
以上, 就是關於空值填充的一些方法, 如有問題請留言, enjoy~~~