# Python清洗數據的方法是什么
## 引言
在數據分析和機器學習項目中,數據清洗(Data Cleaning)是至關重要的一環。據統計,數據科學家80%的時間都花在數據清洗和準備上。Python憑借其豐富的生態系統和強大的庫支持,成為數據清洗的首選工具。本文將系統介紹Python中常用的數據清洗方法,涵蓋從基礎到進階的完整流程。
## 一、數據清洗概述
### 1.1 什么是數據清洗
數據清洗是指識別并糾正(或刪除)數據集中的不準確、不完整、不合理或重復的記錄的過程。主要包括:
- 處理缺失值
- 處理異常值
- 數據格式標準化
- 處理重復數據
- 數據轉換
### 1.2 為什么需要數據清洗
- 提高數據質量
- 確保分析結果準確
- 提升模型性能
- 符合數據規范要求
## 二、Python數據清洗核心庫
### 2.1 Pandas
```python
import pandas as pd
Pandas是Python數據處理的核心庫,提供DataFrame數據結構。
import numpy as np
用于數值計算,特別是處理缺失值。
re
:正則表達式datetime
:日期處理scipy.stats
:統計處理# 從CSV加載
df = pd.read_csv('data.csv')
# 從Excel加載
df = pd.read_excel('data.xlsx')
# 從數據庫加載
import sqlite3
conn = sqlite3.connect('database.db')
df = pd.read_sql_query("SELECT * FROM table", conn)
# 查看前5行
df.head()
# 數據基本信息
df.info()
# 統計描述
df.describe()
# 查看列名
df.columns
# 形狀(行數,列數)
df.shape
# 每列缺失值數量
df.isnull().sum()
# 缺失值比例
df.isnull().mean()
# 可視化缺失值
import seaborn as sns
sns.heatmap(df.isnull(), cbar=False)
# 刪除含有缺失值的行
df.dropna(axis=0)
# 刪除含有缺失值的列
df.dropna(axis=1)
# 刪除全為NA的行
df.dropna(how='all')
# 刪除NA超過閾值的行
df.dropna(thresh=len(df.columns)-2) # 允許最多2個NA
# 用固定值填充
df.fillna(0)
# 前向填充
df.fillna(method='ffill')
# 后向填充
df.fillna(method='bfill')
# 用均值/中位數填充
df['column'].fillna(df['column'].mean(), inplace=True)
df['column'].fillna(df['column'].median(), inplace=True)
# 用眾數填充
df['column'].fillna(df['column'].mode()[0], inplace=True)
# 分組填充
df['column'] = df.groupby('group_column')['column'].transform(
lambda x: x.fillna(x.mean()))
# 線性插值
df['column'].interpolate()
# 時間序列插值
df['column'].interpolate(method='time')
使用KNN、隨機森林等算法預測缺失值:
from sklearn.impute import KNNImputer
imputer = KNNImputer(n_neighbors=5)
df_filled = imputer.fit_transform(df)
# 查看數值列的五數概括
df.describe()
# 定義IQR范圍
Q1 = df['column'].quantile(0.25)
Q3 = df['column'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5*IQR
upper_bound = Q3 + 1.5*IQR
# 箱線圖
df['column'].plot(kind='box')
# 直方圖
df['column'].plot(kind='hist', bins=50)
# 散點圖
df.plot(kind='scatter', x='col1', y='col2')
from scipy import stats
z_scores = stats.zscore(df['column'])
abs_z_scores = np.abs(z_scores)
outliers = (abs_z_scores > 3)
使用DBSCAN等聚類算法識別離群點。
df = df[(df['column'] >= lower_bound) & (df['column'] <= upper_bound)]
# 用邊界值替換
df['column'] = np.where(df['column'] > upper_bound, upper_bound,
np.where(df['column'] < lower_bound, lower_bound, df['column']))
# 用中位數替換
median = df['column'].median()
df['column'] = np.where(outliers, median, df['column'])
bins = [0, 25, 50, 75, 100]
labels = ['low', 'medium', 'high', 'very_high']
df['column_binned'] = pd.cut(df['column'], bins=bins, labels=labels)
# 對數變換
df['column_log'] = np.log1p(df['column'])
# 標準化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df['column_scaled'] = scaler.fit_transform(df[['column']])
# 完全重復的行
df.duplicated()
# 基于某些列的重復
df.duplicated(subset=['col1', 'col2'])
# 重復行計數
df.duplicated().sum()
# 刪除完全重復的行
df.drop_duplicates(inplace=True)
# 基于某些列刪除重復
df.drop_duplicates(subset=['col1', 'col2'], keep='first')
# 保留最后出現的重復項
df.drop_duplicates(keep='last')
# 刪除所有重復項
df.drop_duplicates(keep=False)
df.dtypes
# 轉換為數值
df['column'] = pd.to_numeric(df['column'], errors='coerce')
# 轉換為日期
df['date_column'] = pd.to_datetime(df['date_column'], format='%Y-%m-%d')
# 轉換為分類
df['category_column'] = df['category_column'].astype('category')
# 轉換為字符串
df['str_column'] = df['str_column'].astype(str)
# 去除空格
df['text_column'] = df['text_column'].str.strip()
# 大小寫轉換
df['text_column'] = df['text_column'].str.lower()
# 去除標點
import string
df['text_column'] = df['text_column'].str.translate(
str.maketrans('', '', string.punctuation))
import re
# 提取數字
df['numbers'] = df['text_column'].str.extract('(\d+)')
# 替換模式
df['clean_text'] = df['text_column'].str.replace(r'\b[A-Z]{2,}\b', '', regex=True)
# 復雜模式匹配
phone_pattern = r'(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}'
df['phones'] = df['text_column'].str.findall(phone_pattern)
df['date'] = pd.to_datetime(df['date_str'], format='%m/%d/%Y')
# 自動推斷格式
df['date'] = pd.to_datetime(df['date_str'], infer_datetime_format=True)
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
df['weekday'] = df['date'].dt.weekday
df['is_weekend'] = df['date'].dt.weekday >= 5
# 日期差
df['days_diff'] = (df['date1'] - df['date2']).dt.days
# 日期偏移
from pandas.tseries.offsets import Day, MonthEnd
df['next_month'] = df['date'] + MonthEnd(1)
# 標簽編碼
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
df['encoded'] = le.fit_transform(df['category_column'])
# 獨熱編碼
pd.get_dummies(df, columns=['category_column'])
# 有序類別編碼
size_order = ['S', 'M', 'L', 'XL']
df['size_code'] = df['size'].astype(
pd.CategoricalDtype(categories=size_order, ordered=True)).cat.codes
# 低頻類別合并
value_counts = df['category_column'].value_counts()
to_merge = value_counts[value_counts < 10].index
df['category_column'] = df['category_column'].replace(to_merge, 'Other')
# 等寬分箱
df['bin'] = pd.cut(df['value'], bins=5)
# 等頻分箱
df['bin'] = pd.qcut(df['value'], q=5)
# 自定義分箱
bins = [0, 18, 35, 60, 100]
labels = ['child', 'young', 'adult', 'senior']
df['age_group'] = pd.cut(df['age'], bins=bins, labels=labels)
# Min-Max標準化
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
df['scaled'] = scaler.fit_transform(df[['value']])
# Z-score標準化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df['standardized'] = scaler.fit_transform(df[['value']])
# 數值特征相乘
df['feature_cross'] = df['col1'] * df['col2']
# 類別特征組合
df['combined_category'] = df['category1'] + '_' + df['category2']
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
num_pipeline = Pipeline([
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
df_num = num_pipeline.fit_transform(df.select_dtypes(include=[np.number]))
from sklearn.base import BaseEstimator, TransformerMixin
class CustomCleaner(BaseEstimator, TransformerMixin):
def __init__(self, columns=None):
self.columns = columns
def fit(self, X, y=None):
return self
def transform(self, X):
X = X.copy()
if self.columns:
for col in self.columns:
X[col] = X[col].str.lower().str.strip()
return X
import great_expectations as ge
df_ge = ge.from_pandas(df)
df_ge.expect_column_values_to_not_be_null('important_column')
df_ge.expect_column_values_to_be_between('age', min_value=0, max_value=120)
def validate_data(df):
errors = []
# 檢查缺失值
if df['id'].isnull().any():
errors.append("ID列存在缺失值")
# 檢查范圍
if (df['age'] < 0).any() or (df['age'] > 120).any():
errors.append("年齡值超出合理范圍")
return errors
Python提供了豐富的數據清洗工具和方法,從基礎的缺失值處理到高級的特征工程。掌握這些技術可以顯著提高數據質量,為后續分析和建模奠定堅實基礎。實際項目中,應根據數據特點和業務需求選擇合適的清洗策略,并通過自動化流程提高效率。
本文共約4750字,詳細介紹了Python數據清洗的完整流程和方法。 “`
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。