# Python優化數據預處理方法是什么
數據預處理是機器學習和數據分析中至關重要的步驟,約占整個項目70%的時間。Python作為數據科學的主流語言,提供了豐富的工具庫和優化方法。本文將深入探討Python中優化數據預處理的8大核心方法,并結合實際代碼示例說明其應用場景。
## 一、向量化操作替代循環
### 1.1 NumPy向量化優勢
```python
import numpy as np
# 傳統循環方式
def standardize_loop(data):
result = []
mean_val = sum(data)/len(data)
std_val = (sum((x-mean_val)**2 for x in data)/len(data))**0.5
for x in data:
result.append((x-mean_val)/std_val)
return result
# 向量化方式
def standardize_vector(data):
arr = np.array(data)
return (arr - arr.mean()) / arr.std()
# 性能對比
data = list(range(1, 1000000))
%timeit standardize_loop(data) # 約1.2秒
%timeit standardize_vector(data) # 約20毫秒
import pandas as pd
df = pd.DataFrame({'A': np.random.randint(1,100,1000000)})
# 低效方式
df['B'] = df['A'].apply(lambda x: x**2 + 2*x + 1)
# 優化方式
df['B'] = df['A']**2 + 2*df['A'] + 1 # 速度提升5-10倍
# 原始數據類型
df = pd.read_csv('large_dataset.csv')
print(df.memory_usage(deep=True).sum() # 假設輸出120MB
# 優化后
for col in df.columns:
if df[col].dtype == 'float64':
df[col] = pd.to_numeric(df[col], downcast='float')
elif df[col].dtype == 'int64':
df[col] = pd.to_numeric(df[col], downcast='integer')
print(df.memory_usage(deep=True).sum()) # 輸出降為65MB
chunk_size = 100000
chunks = pd.read_csv('very_large_file.csv', chunksize=chunk_size)
result = []
for chunk in chunks:
# 對每個分塊進行處理
processed = chunk[chunk['value'] > 0]
result.append(processed)
final_df = pd.concat(result)
from joblib import Parallel, delayed
def process_feature(col):
return df[col].fillna(df[col].median())
# 順序執行
%time result = [process_feature(col) for col in df.columns]
# 并行執行
%time result = Parallel(n_jobs=4)(delayed(process_feature)(col) for col in df.columns)
import dask.dataframe as dd
# 創建Dask DataFrame
ddf = dd.from_pandas(df, npartitions=4)
# 并行執行操作
result = ddf.groupby('category').mean().compute()
import re
# 預編譯正則表達式
pattern = re.compile(r'\b\d{3}-\d{2}-\d{4}\b') # 美國社保號格式
# 復用編譯后的模式
df['ssn_valid'] = df['info'].str.contains(pattern)
# 低效方式
df['name_upper'] = df['name'].apply(lambda x: x.upper())
# 高效方式
df['name_upper'] = df['name'].str.upper() # 快3-5倍
from sklearn.preprocessing import OrdinalEncoder
# 高基數特征處理
high_card_cols = [col for col in df.columns if df[col].nunique() > 50]
# 使用序數編碼替代獨熱編碼
encoder = OrdinalEncoder(handle_unknown='use_encoded_value', unknown_value=-1)
df[high_card_cols] = encoder.fit_transform(df[high_card_cols])
# 轉換前
df['category'] = df['category'].astype('object') # 占用較大內存
# 轉換后
df['category'] = df['category'].astype('category') # 內存減少80%
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_cols] = num_pipeline.fit_transform(df[num_cols])
from sklearn.base import BaseEstimator, TransformerMixin
class LogTransformer(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
return self
def transform(self, X):
return np.log1p(X)
# 集成到流水線
pipeline = Pipeline([
('log', LogTransformer()),
('scaler', StandardScaler())
])
# 傳統列表推導式
result = [process(x) for x in large_list] # 立即占用內存
# 生成器方式
result = (process(x) for x in large_list) # 惰性求值
from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate()
df = spark.read.csv('huge_dataset.csv')
# 轉換操作不會立即執行
df_filtered = df.filter(df['value'] > 0)
df_transformed = df_filtered.withColumn('new_col', df['col1'] + df['col2'])
# 觸發實際執行
df_transformed.show()
# 處理中間步驟
df_processed = complex_processing_pipeline(df)
# 保存中間結果
df_processed.to_parquet('processed_data.parquet')
# 后續直接加載
df_final = pd.read_parquet('processed_data.parquet')
from joblib import Memory
memory = Memory(location='./cachedir')
@memory.cache
def expensive_computation(data):
# 復雜計算過程
return result
# 第一次調用會執行計算并緩存
result1 = expensive_computation(data)
# 后續調用直接讀取緩存
result2 = expensive_computation(data)
%timeit
測試不同實現的性能df.memory_usage()
和sys.getsizeof()
通過綜合應用這些方法,可以在保持代碼簡潔的同時,將數據預處理效率提升10-100倍,特別是在處理GB級以上數據集時效果更為顯著。 “`
注:實際使用時可根據需要調整代碼示例中的數據集路徑和具體參數。文章包含了代碼示例、性能對比和實用建議,總字數約1900字,符合Markdown格式要求。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。