Pandas完全指南:数据处理的瑞士军刀

50 阅读5分钟

引言

在数据分析和处理领域,Pandas是Python生态系统中最受欢迎、功能最强大的库之一。它提供了DataFrame这一革命性的数据结构,让数据处理变得直观高效。无论你是数据分析师、数据科学家,还是机器学习工程师,Pandas都是必须掌握的技能。

一、Pandas核心数据结构:Series与DataFrame

1.1 Series:带标签的一维数组

import pandas as pd
import numpy as np

# 创建Series
s1 = pd.Series([1, 3, 5, np.nan, 6, 8])
s2 = pd.Series([10, 20, 30], index=['a', 'b', 'c'])

print("Series基本操作:")
print(f"值: {s2.values}")
print(f"索引: {s2.index}")
print(f"元素'b': {s2['b']}")
print(f"描述统计:\n{s2.describe()}")

1.2 DataFrame:二维表格数据结构

# 创建DataFrame的多种方式
# 从字典创建
data = {
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, 30, 35, 28],
    '城市': ['北京', '上海', '广州', '深圳'],
    '薪资': [15000, 22000, 18000, 25000]
}
df = pd.DataFrame(data)
print("DataFrame基本信息:")
print(df.info())
print("\n前3行数据:")
print(df.head(3))

二、数据加载与保存:多格式支持

# 读取各种数据格式
# CSV文件
df_csv = pd.read_csv('data.csv', encoding='utf-8')

# Excel文件
df_excel = pd.read_excel('data.xlsx', sheet_name='Sheet1')

# JSON数据
df_json = pd.read_json('data.json')

# SQL数据库
import sqlite3
conn = sqlite3.connect('database.db')
df_sql = pd.read_sql_query("SELECT * FROM users", conn)

# 保存数据
df.to_csv('output.csv', index=False, encoding='utf-8')
df.to_excel('output.xlsx', sheet_name='数据')
df.to_json('output.json', orient='records')

三、数据清洗与预处理实战

3.1 处理缺失值

# 创建含缺失值的数据
df = pd.DataFrame({
    'A': [1, 2, np.nan, 4],
    'B': [5, np.nan, np.nan, 8],
    'C': [10, 20, 30, 40]
})

print("缺失值统计:")
print(df.isnull().sum())

# 多种处理方式
df_filled = df.fillna({'A': df['A'].mean(), 'B': 0})  # 不同列不同填充
df_dropped = df.dropna(axis=0, how='any')  # 删除含缺失值的行
df_interpolated = df.interpolate()  # 插值填充

3.2 数据转换

# 类型转换
df['年龄'] = df['年龄'].astype('float32')

# 创建衍生特征
df['年龄段'] = pd.cut(df['年龄'], 
                     bins=[20, 25, 30, 35, 40],
                     labels=['20-25', '25-30', '30-35', '35-40'])

# 独热编码
df_encoded = pd.get_dummies(df, columns=['城市'], prefix='city')

# 数据规范化
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
df[['薪资_标准化']] = scaler.fit_transform(df[['薪资']])

四、高级数据操作技巧

4.1 分组聚合(GroupBy)

# 模拟销售数据
sales_data = {
    '日期': pd.date_range('2024-01-01', periods=100, freq='D'),
    '产品': np.random.choice(['手机', '电脑', '平板', '耳机'], 100),
    '地区': np.random.choice(['华北', '华东', '华南', '华西'], 100),
    '销售额': np.random.randint(1000, 10000, 100),
    '数量': np.random.randint(1, 20, 100)
}
sales_df = pd.DataFrame(sales_data)

# 多维度分组聚合
grouped = sales_df.groupby(['地区', '产品']).agg({
    '销售额': ['sum', 'mean', 'std'],
    '数量': 'sum'
}).round(2)

# 透视表
pivot_table = pd.pivot_table(sales_df,
                            values='销售额',
                            index='地区',
                            columns='产品',
                            aggfunc=['sum', 'mean'],
                            fill_value=0)

4.2 时间序列处理

# 创建时间序列数据
dates = pd.date_range('2024-01-01', periods=365, freq='D')
ts_data = pd.DataFrame({
    '日期': dates,
    '温度': np.random.normal(25, 5, 365),
    '湿度': np.random.normal(60, 10, 365)
})
ts_data.set_index('日期', inplace=True)

# 时间序列操作
monthly_avg = ts_data.resample('M').mean()  # 按月重采样
weekly_max = ts_data.resample('W').max()    # 按周重采样

# 滚动窗口计算
ts_data['7日均温'] = ts_data['温度'].rolling(window=7).mean()
ts_data['30日湿度标准差'] = ts_data['湿度'].rolling(window=30).std()

五、数据合并与连接

# 创建示例数据
df1 = pd.DataFrame({
    'ID': [1, 2, 3, 4],
    '姓名': ['张三', '李四', '王五', '赵六'],
    '部门': ['技术部', '市场部', '技术部', '人事部']
})

df2 = pd.DataFrame({
    'ID': [1, 2, 3, 5],
    '薪资': [15000, 22000, 18000, 20000],
    '入职年份': [2020, 2021, 2019, 2022]
})

# 多种合并方式
inner_join = pd.merge(df1, df2, on='ID', how='inner')      # 内连接
left_join = pd.merge(df1, df2, on='ID', how='left')        # 左连接
outer_join = pd.merge(df1, df2, on='ID', how='outer')      # 全外连接

# 纵向合并
df3 = pd.DataFrame({
    'ID': [5, 6],
    '姓名': ['钱七', '孙八'],
    '部门': ['财务部', '市场部']
})
vertical_concat = pd.concat([df1, df3], ignore_index=True)

六、性能优化与大数据处理

6.1 使用适当的数据类型

# 优化数据类型以减少内存占用
def optimize_dtypes(df):
    for col in df.columns:
        col_type = df[col].dtype
        
        if col_type == 'object':
            # 尝试转换为category类型
            if df[col].nunique() / len(df[col]) < 0.5:
                df[col] = df[col].astype('category')
                
        elif col_type in ['int64', 'int32']:
            # 向下转换整数类型
            c_min = df[col].min()
            c_max = df[col].max()
            
            if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
                df[col] = df[col].astype(np.int8)
            elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
                df[col] = df[col].astype(np.int16)
            elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
                df[col] = df[col].astype(np.int32)
                
    return df

# 应用优化
optimized_df = optimize_dtypes(df.copy())
print(f"内存减少: {(df.memory_usage().sum() - optimized_df.memory_usage().sum()) / 1024 ** 2:.2f} MB")

6.2 分块处理大文件

# 分块读取和处理大文件
chunk_size = 10000  # 每次读取10000行
chunks = []

for chunk in pd.read_csv('large_file.csv', 
                         chunksize=chunk_size,
                         encoding='utf-8'):
    # 对每个块进行处理
    processed_chunk = chunk[chunk['销售额'] > 1000]  # 示例过滤
    chunks.append(processed_chunk)

# 合并结果
result = pd.concat(chunks, ignore_index=True)

七、实战案例:电商数据分析

# 模拟电商数据分析
def analyze_ecommerce_data():
    # 生成模拟数据
    np.random.seed(42)
    n_customers = 1000
    
    data = {
        'customer_id': range(1, n_customers + 1),
        'age': np.random.randint(18, 65, n_customers),
        'gender': np.random.choice(['M', 'F'], n_customers),
        'total_spent': np.random.exponential(500, n_customers),
        'purchase_count': np.random.poisson(10, n_customers),
        'last_purchase_days': np.random.randint(1, 365, n_customers),
        'category_preference': np.random.choice(
            ['electronics', 'clothing', 'books', 'home'], n_customers)
    }
    
    df = pd.DataFrame(data)
    
    # 1. 客户分群
    df['customer_segment'] = pd.qcut(df['total_spent'], 
                                     q=4, 
                                     labels=['低价值', '中低价值', '中高价值', '高价值'])
    
    # 2. 计算关键指标
    segment_stats = df.groupby('customer_segment').agg({
        'total_spent': ['mean', 'median', 'count'],
        'purchase_count': 'mean',
        'last_purchase_days': 'mean'
    }).round(2)
    
    # 3. RFM分析
    rfm = df.groupby('customer_id').agg({
        'last_purchase_days': 'min',  # Recency
        'purchase_count': 'sum',      # Frequency
        'total_spent': 'sum'          # Monetary
    }).rename(columns={
        'last_purchase_days': 'recency',
        'purchase_count': 'frequency',
        'total_spent': 'monetary'
    })
    
    return df, segment_stats, rfm

# 执行分析
customer_df, stats, rfm_scores = analyze_ecommerce_data()

八、最佳实践总结

8.1 代码可读性

  • 使用链式方法时适当换行
  • 为复杂操作添加注释
  • 使用有意义的变量名

8.2 性能优化

  • 避免在DataFrame上使用循环
  • 使用向量化操作
  • 合理选择合并方式

8.3 常见陷阱规避

  • 注意SettingWithCopyWarning
  • 处理大数据时注意内存使用
  • 保存文件时指定合适的编码

总结

Pandas是Python数据分析的核心工具,掌握它意味着拥有了处理和分析数据的超能力。从简单的数据清洗到复杂的时间序列分析,Pandas都能提供优雅的解决方案。

关键要点

  1. 理解Series和DataFrame的核心概念
  2. 掌握数据清洗和预处理的常用方法
  3. 熟练使用分组聚合和时间序列操作
  4. 学会优化代码性能

记住:实践是最好的学习方式!多在实际项目中应用这些技巧,你会越来越熟练。