Python中數(shù)據(jù)清洗與預(yù)處理技巧分享
前言
我們不論在學(xué)習(xí)機器學(xué)習(xí)還是數(shù)據(jù)分析中,都會涉及很多數(shù)據(jù)。但原數(shù)據(jù)不可避免有很多雜志,為了確保結(jié)果的準確性,我們需要首先進行數(shù)據(jù)清洗和預(yù)處理。
了解數(shù)據(jù)清洗
數(shù)據(jù)清洗就像是一場數(shù)據(jù)的“大掃除”。它是從原始數(shù)據(jù)中找出并修正那些錯誤、不完整、重復(fù)或不一致的數(shù)據(jù)。通過數(shù)據(jù)清洗,能顯著提升數(shù)據(jù)質(zhì)量,為后續(xù)數(shù)據(jù)分析、挖掘和建模等工作提供準確、可靠、干凈的數(shù)據(jù)基礎(chǔ),從而讓基于數(shù)據(jù)得出的結(jié)論更具可信度和價值。
數(shù)據(jù)清洗的步驟
1. 環(huán)境準備與庫導(dǎo)入
import pandas as pd # 數(shù)據(jù)處理核心庫 import numpy as np # 數(shù)值計算庫 import matplotlib.pyplot as plt # 基礎(chǔ)可視化庫 import seaborn as sns # 高級可視化庫 # 設(shè)置顯示參數(shù),確保中文正常顯示 plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"] pd.set_option('display.max_columns', None) # 顯示所有列 pd.set_option('display.width', 1000) # 顯示寬度
函數(shù) / 參數(shù)解釋:
import pandas as pd
:導(dǎo)入 pandas 庫并簡寫為 pd。pandas 是數(shù)據(jù)處理的核心工具,提供了DataFrame
數(shù)據(jù)結(jié)構(gòu)和豐富的數(shù)據(jù)操作方法。plt.rcParams
:設(shè)置 matplotlib 的全局參數(shù),這里用于配置中文字體,避免圖表中中文顯示為亂碼。pd.set_option
:配置 pandas 的顯示選項,確保查看數(shù)據(jù)時不會截斷列或內(nèi)容。
2. 數(shù)據(jù)加載
# 從CSV文件加載數(shù)據(jù) df = pd.read_csv('data.csv') # 從Excel文件加載數(shù)據(jù)(支持多工作表) excel_file = pd.ExcelFile('data.xlsx') df = excel_file.parse('Sheet1') # 讀取名為Sheet1的工作表 # 查看數(shù)據(jù)規(guī)模 print(f"數(shù)據(jù)集規(guī)模:{df.shape[0]}行,{df.shape[1]}列")
函數(shù)解釋:
pd.read_csv()
:讀取 CSV 文件并返回 DataFrame
對象。
- 常用參數(shù):
sep
(分隔符,默認逗號)、header
(表頭行索引,默認 0)、na_values
(指定缺失值標識)、usecols
(指定讀取的列) - 示例:
pd.read_csv('data.csv', sep=';', na_values=['NA', 'missing'])
pd.ExcelFile()
與 parse()
:
pd.ExcelFile()
:創(chuàng)建 Excel 文件對象,用于高效讀取包含多個工作表的 Excel 文件parse()
:從 ExcelFile 對象中讀取指定工作表,參數(shù)sheet_name
指定工作表名稱或索引
3. 數(shù)據(jù)初探與理解
# 查看數(shù)據(jù)基本信息 print("數(shù)據(jù)基本信息:") df.info() # 查看前5行數(shù)據(jù) print("\n數(shù)據(jù)前5行:") print(df.head()) # 查看數(shù)值型列的統(tǒng)計描述 print("\n數(shù)值型列統(tǒng)計描述:") print(df.describe()) # 查看類別型列的取值分布 print("\n類別型列取值分布:") for col in df.select_dtypes(include=['object', 'category']).columns: print(f"\n{col}列分布:") print(df[col].value_counts())
函數(shù)解釋:
info()
:查看DataFrame
的基本信息,包括索引類型、列信息、數(shù)據(jù)類型、非空值數(shù)量和內(nèi)存占用。head(n)
:返回前 n 行數(shù)據(jù)(默認 n=5),用于快速預(yù)覽數(shù)據(jù)內(nèi)容。對應(yīng)的tail(n)
返回后 n 行。describe()
:生成數(shù)值型列的統(tǒng)計摘要,包括計數(shù)、均值、標準差、最值和四分位數(shù)。select_dtypes(include=[])
:篩選指定數(shù)據(jù)類型的列,include=['object', 'category']
用于篩選類別型列。value_counts()
:計算類別型列中每個取值的出現(xiàn)次數(shù),用于了解數(shù)據(jù)分布。
4. 缺失值處理
# 1. 檢測缺失值 missing_count = df.isnull().sum() # 計算每列缺失值數(shù)量 missing_ratio = missing_count / len(df) # 計算缺失比例 missing_df = pd.DataFrame({ '缺失值數(shù)量': missing_count, '缺失比例': missing_ratio }) print("缺失值統(tǒng)計:") print(missing_df[missing_df['缺失值數(shù)量'] > 0]) # 只顯示有缺失值的列 # 2. 處理缺失值 # 方法1:刪除缺失值(適用于缺失比例極低的情況) df_drop = df.dropna(axis=0) # 按行刪除,axis=1按列刪除 # 方法2:填充缺失值 # 數(shù)值型列用均值/中位數(shù)填充 df['數(shù)值列1'] = df['數(shù)值列1'].fillna(df['數(shù)值列1'].mean()) # 均值填充 df['數(shù)值列2'] = df['數(shù)值列2'].fillna(df['數(shù)值列2'].median()) # 中位數(shù)填充 # 類別型列用眾數(shù)填充 df['類別列1'] = df['類別列1'].fillna(df['類別列1'].mode()[0]) # 眾數(shù)填充 # 方法3:用前后值填充(適用于時間序列) df['時間序列列'] = df['時間序列列'].fillna(method='ffill') # 向前填充 # df['時間序列列'] = df['時間序列列'].fillna(method='bfill') # 向后填充
函數(shù)解釋:
isnull()
:返回布爾型DataFrame
,標記每個元素是否為缺失值(NaN)。sum()
:對isnull()
的結(jié)果求和,得到每列缺失值數(shù)量。dropna(axis=0)
:刪除包含缺失值的行(axis=0)或列(axis=1)。- 常用參數(shù):
how='any'
(默認,任何缺失值即刪除)、how='all'
(所有值都缺失才刪除)
- 常用參數(shù):
fillna()
:填充缺失值,支持固定值、統(tǒng)計量(均值 / 中位數(shù) / 眾數(shù))和前后值填充。
5. 重復(fù)值處理
# 1. 檢測重復(fù)行 duplicate_rows = df.duplicated() # 返回布爾型Series,標記是否為重復(fù)行 print(f"重復(fù)行數(shù)量:{duplicate_rows.sum()}") # 2. 查看重復(fù)行內(nèi)容 if duplicate_rows.sum() > 0: print("重復(fù)行內(nèi)容:") print(df[duplicate_rows]) # 3. 刪除重復(fù)行 df_clean = df.drop_duplicates(keep='first') # 保留第一次出現(xiàn)的行 # df_clean = df.drop_duplicates(keep='last') # 保留最后一次出現(xiàn)的行 # df_clean = df.drop_duplicates(keep=False) # 刪除所有重復(fù)行 print(f"刪除重復(fù)行后:{df_clean.shape[0]}行")
函數(shù)解釋:
duplicated():檢測重復(fù)行,返回布爾型 Series。
- 參數(shù)
subset=['col1', 'col2']
:指定用于判斷重復(fù)的列 - 默認保留第一次出現(xiàn)的行,標記后續(xù)重復(fù)行為 True
drop_duplicates():刪除重復(fù)行,參數(shù)keep控制保留策略:
keep='first'
:保留第一次出現(xiàn)的行(默認)keep='last'
:保留最后一次出現(xiàn)的行keep=False
:刪除所有重復(fù)行
6. 異常值處理
# 1. 繪制箱線圖可視化異常值 plt.figure(figsize=(12, 6)) sns.boxplot(data=df.select_dtypes(include=np.number)) # 只對數(shù)值列繪圖 plt.title('數(shù)值列箱線圖(用于檢測異常值)') plt.tight_layout() plt.show() # 2. 使用IQR方法檢測異常值 def detect_outliers(df, col): """檢測指定列的異常值""" Q1 = df[col].quantile(0.25) # 下四分位數(shù) Q3 = df[col].quantile(0.75) # 上四分位數(shù) IQR = Q3 - Q1 # 四分位距 lower_bound = Q1 - 1.5 * IQR # 下界 upper_bound = Q3 + 1.5 * IQR # 上界 outliers = df[(df[col] < lower_bound) | (df[col] > upper_bound)] return outliers, lower_bound, upper_bound # 處理每個數(shù)值列的異常值 for col in df.select_dtypes(include=np.number).columns: outliers, lower, upper = detect_outliers(df, col) if not outliers.empty: print(f"{col}列異常值數(shù)量:{len(outliers)}") # 方法1:刪除異常值 # df = df.drop(outliers.index) # 方法2:截斷異常值(替換為邊界值) df.loc[df[col] < lower, col] = lower df.loc[df[col] > upper, col] = upper
函數(shù)解釋:
sns.boxplot()
:繪制箱線圖,直觀展示數(shù)據(jù)分布和異常值。箱線圖中,超出上下須線(Q1-1.5IQR 和 Q3+1.5IQR)的點被視為異常值。quantile(q)
:計算分位數(shù),q=0.25 表示下四分位數(shù)(Q1),q=0.75 表示上四分位數(shù)(Q3)。- 異常值處理策略:刪除(適用于錯誤數(shù)據(jù))、截斷(替換為邊界值)、轉(zhuǎn)換(如對數(shù)轉(zhuǎn)換)。
7. 數(shù)據(jù)類型轉(zhuǎn)換
# 查看當前數(shù)據(jù)類型 print("原始數(shù)據(jù)類型:") print(df.dtypes) # 1. 轉(zhuǎn)換為數(shù)值類型(處理字符串格式的數(shù)值) df['數(shù)值列'] = pd.to_numeric(df['數(shù)值列'], errors='coerce') # 無法轉(zhuǎn)換的值變?yōu)镹aN # 2. 轉(zhuǎn)換為日期類型 df['日期列'] = pd.to_datetime(df['日期列'], format='%Y-%m-%d') # 指定格式加速轉(zhuǎn)換 # 3. 轉(zhuǎn)換為類別類型(適用于取值有限的字符串列) df['類別列'] = df['類別列'].astype('category') # 查看轉(zhuǎn)換后的數(shù)據(jù)類型 print("\n轉(zhuǎn)換后數(shù)據(jù)類型:") print(df.dtypes)
函數(shù)解釋:
dtypes
:查看各列的數(shù)據(jù)類型。pd.to_numeric()
:將列轉(zhuǎn)換為數(shù)值類型,errors='coerce'
參數(shù)將無法轉(zhuǎn)換的值設(shè)為 NaN。pd.to_datetime()
:將列轉(zhuǎn)換為日期時間類型,format
參數(shù)指定日期格式。astype('category')
:將字符串列轉(zhuǎn)換為類別類型,減少內(nèi)存占用并提高效率。
8. 數(shù)據(jù)標準化 / 歸一化(預(yù)處理)
# 1. 標準化(Z-score標準化,使均值為0,標準差為1) from sklearn.preprocessing import StandardScaler scaler = StandardScaler() numeric_cols = df.select_dtypes(include=np.number).columns df[numeric_cols] = scaler.fit_transform(df[numeric_cols]) # 2. 歸一化(Min-Max歸一化,將值縮放到[0,1]范圍) from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() df[numeric_cols] = scaler.fit_transform(df[numeric_cols]) # 查看處理后的統(tǒng)計描述 print("標準化/歸一化后統(tǒng)計描述:") print(df[numeric_cols].describe())
函數(shù)解釋:
StandardScaler()
:Z-score 標準化,公式為:(x’ = (x - \mu) / \sigma),其中(\mu)是均值,(\sigma)是標準差。適用于數(shù)據(jù)近似正態(tài)分布的情況。MinMaxScaler()
:Min-Max 歸一化,將值縮放到 [0,1] 范圍,公式為:(x’ = (x - \min) / (\max - \min))。適用于需要將數(shù)據(jù)限制在特定范圍的場景。
實例實踐
以鳶尾花數(shù)據(jù)集為例
原數(shù)據(jù)集:在資源綁定中
#導(dǎo)入庫 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns #設(shè)置顯示選項 pd.set_option('display.max_columns', None) pd.set_option('display.max_rows', None) # 使用原始字符串處理文件路徑 excel_file = r'C:\Users\einsc\PycharmProjects\PythonProject\.venv\share\yuan\iris_dataset.xlsx' #獲取表名 sheet_names = pd.ExcelFile(excel_file).sheet_names print(sheet_names) #讀取數(shù)據(jù) df = pd.ExcelFile(excel_file).parse('Sheet1') print("數(shù)據(jù)基本信息") df.info() rows, columns = df.shape print(f"數(shù)據(jù)的行數(shù): {rows}") print(f"數(shù)據(jù)的列數(shù): {columns}") print("數(shù)據(jù)的前幾行") print(df.head()) # 處理缺失值 print("缺失值統(tǒng)計:") print(df.isnull().sum()) # 若存在缺失值,這里選擇用列均值填充數(shù)值型列,用眾數(shù)填充類別型列 for col in df.columns: if df[col].dtype == 'object': df[col] = df[col].fillna(df[col].mode()[0]) else: df[col] = df[col].fillna(df[col].mean()) # 處理重復(fù)值 print("重復(fù)值數(shù)量:", df.duplicated().sum()) # 刪除重復(fù)值 df = df.drop_duplicates() # 處理異常值(使用 IQR 方法) numerical_columns = df.select_dtypes(include=[np.number]).columns for col in numerical_columns: Q1 = df[col].quantile(0.25) Q3 = df[col].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR df = df[(df[col] >= lower_bound) & (df[col] <= upper_bound)] # 重置索引 df = df.reset_index(drop=True) print("清洗后數(shù)據(jù)基本信息") df.info() print("清洗后數(shù)據(jù)行數(shù): ", df.shape[0]) print("清洗后數(shù)據(jù)列數(shù): ", df.shape[1]) # 定義保存路徑 output_file = r'C:\Users\einsc\PycharmProjects\PythonProject\.venv\share\yuan\iris_dataset_cleaned.xlsx' # 將清洗后的數(shù)據(jù)保存到新的 Excel 文件 df.to_excel(output_file, index=False, sheet_name='CleanedData') print(f"清洗后的數(shù)據(jù)已保存到 {output_file}") print("數(shù)據(jù)的前幾行")
處理結(jié)果:
總結(jié)
本文聚焦機器學(xué)習(xí)中的數(shù)據(jù)清洗與預(yù)處理。先闡述其重要性,如同為數(shù)據(jù)“大掃除”,能提升數(shù)據(jù)質(zhì)量、保障結(jié)論可靠。接著分八個步驟詳細講解,從環(huán)境準備與庫導(dǎo)入,到數(shù)據(jù)加載、初探,再到缺失值、重復(fù)值、異常值處理,以及數(shù)據(jù)類型轉(zhuǎn)換和標準化/歸一化,每個步驟都有代碼示例和函數(shù)解釋。最后以鳶尾花數(shù)據(jù)集為例實踐,經(jīng)各環(huán)節(jié)處理后保存清洗數(shù)據(jù)。整體內(nèi)容系統(tǒng)全面,理論與實踐結(jié)合,助讀者掌握數(shù)據(jù)清洗與預(yù)處理的關(guān)鍵要點和操作。
以上就是Python中數(shù)據(jù)清洗與預(yù)處理技巧分享的詳細內(nèi)容,更多關(guān)于Python數(shù)據(jù)清洗與預(yù)處理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
TensorFlow2.1.0安裝過程中setuptools、wrapt等相關(guān)錯誤指南
這篇文章主要介紹了TensorFlow2.1.0安裝時setuptools、wrapt等相關(guān)錯誤指南,本文通過安裝錯誤分析給出大家解決方案,感興趣的朋友跟隨小編一起看看吧2020-04-04python 地圖經(jīng)緯度轉(zhuǎn)換、糾偏的實例代碼
這篇文章主要介紹了python 地圖經(jīng)緯度轉(zhuǎn)換、糾偏的實例代碼,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-08-08在VS2017中用C#調(diào)用python腳本的實現(xiàn)
這篇文章主要介紹了在VS2017中用C#調(diào)用python腳本的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07解決Jupyter因卸載重裝導(dǎo)致的問題修復(fù)
這篇文章主要介紹了解決Jupyter因卸載重裝導(dǎo)致的問題修復(fù),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04python list.sort()根據(jù)多個關(guān)鍵字排序的方法實現(xiàn)
Python list內(nèi)置sort()方法用來排序,也可以用python內(nèi)置的全局sorted()方法來對可迭代的序列排序生成新的序列,本文詳細的介紹了python list.sort()根據(jù)多個關(guān)鍵字排序,感興趣的可以了解一下2021-12-12pycharm創(chuàng)建一個python包方法圖解
在本篇文章中小編給大家分享了關(guān)于pycharm怎么創(chuàng)建一個python包的相關(guān)知識點,需要的朋友們學(xué)習(xí)下。2019-04-04idea2020手動安裝python插件的實現(xiàn)方法
這篇文章主要介紹了idea2020手動安裝python插件的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07