Vanson's Eternal Blog

Python类库Pandas

Python pandas basic.png
Published on
/8 mins read/---

Pandas

基础

核心对象

对象维度核心属性关键语义
Series1D值 + 索引(标签)“带标签的列”
DataFrame2D行索引 + 列索引 + 块(block)“Excel 表 + SQL 表 + ndarray”
Index任意维不可变、可哈希、可切片轴标签容器

底层设计

  • BlockManager:列同类型连续存储 → NumPy 免拷贝视图
  • DatetimeIndex / PeriodIndex:时间维度高效切片、对齐
  • Categorical:低内存因子化
  • ExtensionArray:支持自定义列类型(如 IPv4、Decimal)

函数

类别常用函数/方法
数据读取read_csv, read_excel, read_json, read_sql, read_html
数据查看head, tail, info, describe, shape, columns, index
数据选择loc, iloc, at, iat, filter, query
数据清洗dropna, fillna, drop_duplicates, replace, drop
数据转换astype, apply, map, applymap, rename, set_index, reset_index
分组聚合groupby, agg, transform, pivot_table, crosstab
合并连接merge, join, concat, append
时间序列to_datetime, resample, rolling, shift, diff
可视化plot, hist, boxplot, scatter
输入输出to_csv, to_excel, to_json, to_sql, to_html
函数一行示例场景
applydf['col'].apply(lambda x: x**2)任意转换
groupbydf.groupby('city')['sales'].sum()分组聚合
fillnadf.fillna(method='ffill')缺失值补齐
mergepd.merge(df1, df2, on='key')多表连接
pivot_tablepd.pivot_table(df, values='sales', index='prod', columns='region')交叉汇总
value_countsdf['cat'].value_counts()频次分布
astypedf['col'] = df['col'].astype('int')类型转换
dropnadf.dropna(subset=['price'])清理无效行
sort_valuesdf.sort_values('date', ascending=False)排序
querydf.query('sales > 1000 & region=="East"')表达式筛选

数据结构创建

import pandas as pd
import numpy as np
 
# 创建Series
s = pd.Series([1, 3, 5, np.nan, 6, 8])
print(s)
 
# 创建DataFrame
data = {
    'Name': ['Alice', 'Bob', 'Charlie', 'David'],
    'Age': [25, 30, 35, 40],
    'City': ['NY', 'LA', 'Chicago', 'Miami']
}
df = pd.DataFrame(data)
print(df)

数据读取与写入

# 读取CSV
df = pd.read_csv('data.csv')
 
# 读取Excel
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')
 
# 读取SQL数据库
from sqlalchemy import create_engine
engine = create_engine('sqlite:///mydatabase.db')
df = pd.read_sql('SELECT * FROM mytable', engine)
 
# 写入CSV
df.to_csv('output.csv', index=False)
 
# 写入Excel
df.to_excel('output.xlsx', sheet_name='Results')

数据查看与检查

# 查看前n行
df.head(3)
 
# 查看后n行
df.tail(2)
 
# 查看基本信息
df.info()
 
# 统计描述
df.describe()
 
# 查看形状
df.shape
 
# 查看列名
df.columns
 
# 查看索引
df.index

数据选择与切片

# 选择单列
df['Name']
 
# 选择多列
df[['Name', 'Age']]
 
# 按标签选择行
df.loc[0]  # 第一行
df.loc[1:3]  # 第二到第四行
 
# 按位置选择行
df.iloc[0]  # 第一行
df.iloc[1:4]  # 第二到第四行
 
# 布尔索引
df[df['Age'] > 30]
 
# 复杂条件
df[(df['Age'] > 25) & (df['City'] == 'NY')]

缺失值处理

# 检测缺失值
df.isnull()
 
# 填充缺失值
df.fillna(0)  # 用0填充
df.fillna(method='ffill')  # 前向填充
 
# 删除缺失值
df.dropna()

重复值处理

# 检测重复行
df.duplicated()
 
# 删除重复行
df.drop_duplicates()

数据转换

# 重命名列
df.rename(columns={'Age': 'Years'})
 
# 类型转换
df['Age'] = df['Age'].astype(float)
 
# 应用函数
df['Age'] = df['Age'].apply(lambda x: x + 1)
 
# 向量化操作
df['Age'] += 1
 
# 替换值
df['City'].replace({'NY': 'New York', 'LA': 'Los Angeles'})

数据分组与聚合

# 基本分组
grouped = df.groupby('City')
 
# 聚合函数
grouped['Age'].mean()
grouped['Age'].agg(['mean', 'min', 'max', 'count'])
 
# 多列分组
df.groupby(['City', 'Gender'])['Age'].mean()
 
# 透视表
pd.pivot_table(df, values='Age', index='City', columns='Gender', aggfunc='mean')

数据合并与连接

# 连接两个DataFrame
pd.concat([df1, df2])
 
# 数据库式连接
pd.merge(left_df, right_df, on='key')
pd.merge(left_df, right_df, left_on='lkey', right_on='rkey', how='inner')
pd.merge(left_df, right_df, how='outer')

时间序列处理

# 创建时间序列
date_rng = pd.date_range(start='2023-01-01', end='2023-01-10', freq='D')
ts = pd.Series(np.random.randn(len(date_rng)), index=date_rng)
 
# 时间重采样
ts.resample('W').mean()
 
# 移动窗口计算
ts.rolling(window=3).mean()

应用

销售数据分析

# 读取销售数据
sales = pd.read_csv('sales_data.csv')
 
# 数据清洗
sales['Date'] = pd.to_datetime(sales['Date'])
sales = sales.dropna(subset=['Amount'])
 
# 按产品类别分析
category_sales = sales.groupby('Category')['Amount'].sum().sort_values(ascending=False)
 
# 按月分析销售趋势
monthly_sales = sales.resample('M', on='Date')['Amount'].sum()
 
# 计算每个客户的购买频率
customer_analysis = sales.groupby('CustomerID').agg(
    Total_Spent=('Amount', 'sum'),
    Purchase_Count=('InvoiceID', 'nunique'),
    Avg_Purchase=('Amount', 'mean')
)

股票数据分析

# 读取股票数据
stocks = pd.read_csv('stock_prices.csv', parse_dates=['Date'], index_col='Date')
 
# 计算每日收益率
stocks['Return'] = stocks['Close'].pct_change()
 
# 计算移动平均
stocks['MA50'] = stocks['Close'].rolling(window=50).mean()
stocks['MA200'] = stocks['Close'].rolling(window=200).mean()
 
# 计算波动率
stocks['Volatility'] = stocks['Return'].rolling(window=30).std() * np.sqrt(252)
 
# 相关性分析
correlation_matrix = stocks[['AAPL', 'MSFT', 'GOOGL']].corr()

客户流失预测(数据预处理)

# 读取客户数据
customers = pd.read_csv('customers.csv')
 
# 处理缺失值
customers['Age'].fillna(customers['Age'].median(), inplace=True)
customers['Income'].fillna(customers.groupby('Occupation')['Income'].transform('mean'), inplace=True)
 
# 特征工程
customers['Tenure'] = (pd.to_datetime('today') - pd.to_datetime(customers['Join_Date'])).dt.days
customers['Monthly_Spend_Ratio'] = customers['Monthly_Spend'] / customers['Income']
 
# 编码分类变量
customers = pd.get_dummies(customers, columns=['Occupation', 'Region'], drop_first=True)
 
# 准备机器学习数据
X = customers.drop('Churned', axis=1)
y = customers['Churned']

电商用户行为分析

# 读取用户行为日志
logs = pd.read_json('user_logs.json', lines=True)
 
# 转换时间戳
logs['timestamp'] = pd.to_datetime(logs['timestamp'], unit='ms')
 
# 提取特征
logs['hour'] = logs['timestamp'].dt.hour
logs['day_of_week'] = logs['timestamp'].dt.dayofweek
 
# 会话分割
logs['session_id'] = (logs['timestamp'].diff() > pd.Timedelta('30min')).cumsum()
 
# 会话分析
session_analysis = logs.groupby('session_id').agg(
    duration=('timestamp', lambda x: (x.max() - x.min()).seconds),
    page_views=('url', 'count'),
    user_id=('user_id', 'first')
)

时间序列预测(ARIMA)

from statsmodels.tsa.arima.model import ARIMA
 
# 准备数据
air_passengers = pd.read_csv('air_passengers.csv', parse_dates=['Month'], index_col='Month')
 
# 拆分训练测试集
train = air_passengers[:'1959-12-01']
test = air_passengers['1960-01-01':]
 
# 拟合ARIMA模型
model = ARIMA(train, order=(2,1,1))
model_fit = model.fit()
 
# 预测
forecast = model_fit.forecast(steps=12)

大数据并行 ETL

需求:5 GB CSV → 分组聚合 → 内存不足 → Dask + Pandas 语法。

import dask.dataframe as dd
ddf = dd.read_csv('big.csv')
out = (ddf.groupby('client_id')
         .agg({'amount': ['sum','mean']})
         .compute())         # 触发并行
out.to_parquet('result.parquet')

文本列数字提取

需求:订单备注含金额,正则提取数字。

df = pd.DataFrame({'note':['满100减20','满200减50','无优惠']})
df['money'] = df['note'].str.extract(r'(\d+)').astype(float)

技巧

性能优化

# 使用向量化操作替代循环
df['new_col'] = df['col1'] * 2 + df['col2']
 
# 使用eval()进行高效计算
df.eval('result = col1 + col2 * 3', inplace=True)
 
# 使用类别数据类型节省内存
df['category_col'] = df['category_col'].astype('category')
 
# 分块处理大数据
chunk_size = 10000
for chunk in pd.read_csv('large_file.csv', chunksize=chunk_size):
    process(chunk)

可视化集成

import matplotlib.pyplot as plt
 
# 直接绘制DataFrame
df.plot(kind='line', x='Date', y='Price')
plt.title('Price Trend')
plt.show()
 
# 箱线图
df.boxplot(column='Age', by='City')
plt.suptitle('')
plt.title('Age Distribution by City')
plt.show()
 
# 相关矩阵热力图
import seaborn as sns
corr = df.corr()
sns.heatmap(corr, annot=True)
plt.show()

实用技巧

# 多条件赋值
df.loc[(df['Age'] > 30) & (df['City'] == 'NY'), 'Status'] = 'Senior'
 
# 应用复杂函数
def complex_function(row):
    if row['Age'] > 40 and row['Income'] > 100000:
        return 'High Value'
    else:
        return 'Standard'
 
df['Segment'] = df.apply(complex_function, axis=1)
 
# 交叉表分析
pd.crosstab(df['City'], df['Gender'], values=df['Age'], aggfunc='mean')
 
# 样式化输出
(df.style
   .background_gradient(cmap='Blues', subset=['Age'])
   .format({'Income': '${:,.2f}'})
   .bar(subset=['Score'], color='lightgreen'))

与NumPy集成

# DataFrame转NumPy数组
array = df.values
 
# NumPy数组转DataFrame
new_df = pd.DataFrame(array, columns=df.columns)
 
# 在Pandas中使用NumPy函数
df['log_income'] = np.log(df['Income'])
← Previous postPython框架Flask
Next post →Python类库Numpy