Pandas时间序列处理:数据分析师必备的核心技能
时间序列数据在金融、物联网、电商等领域无处不在,掌握Pandas的时间序列处理能力已成为数据分析师的必备技能。本文将深入讲解Pandas处理时间序列的核心知识点,帮助你在实际项目中游刃有余。
时间序列基础操作

Pandas提供了强大的时间序列处理功能,首先需要了解如何创建和转换时间序列数据。
创建时间戳最简单的方法是使用pd.Timestamp
:
import pandas as pd
# 创建单个时间戳
ts = pd.Timestamp('2023-06-15 09:30:00')
print(ts) # 输出: 2023-06-15 09:30:00
对于批量时间数据,可以使用pd.to_datetime
转换:
dates = ['2023-01-01', '2023-01-15', '2023-02-01']
date_series = pd.to_datetime(dates)
print(date_series)
生成规则时间序列最常用的是date_range
函数:
# 生成每日数据
daily_index = pd.date_range(start='2023-01-01', end='2023-01-31', freq='D')
# 生成工作日数据
bday_index = pd.date_range(start='2023-01-01', periods=22, freq='B')
# 生成每月最后一天
month_end = pd.date_range(start='2023-01-01', periods=12, freq='M')
时间属性提取与转换
从时间戳中提取特定成分是常见需求,Pandas提供了直观的方法:
# 创建一个包含日期时间的数据框
df = pd.DataFrame({
'date': pd.date_range('2023-01-01', periods=5, freq='D'),
'value': [10, 20, 30, 40, 50]
})
# 提取各种时间成分
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
df['weekday'] = df['date'].dt.weekday # 周一为0,周日为6
df['is_weekend'] = df['date'].dt.weekday >= 5
时区处理在全球化应用中尤为重要:
# 设置时区
ts = pd.Timestamp('2023-06-15 09:30:00', tz='US/Eastern')
print(ts) # 2023-06-15 09:30:00-04:00
# 转换时区
ts_utc = ts.tz_convert('UTC')
print(ts_utc) # 2023-06-15 13:30:00+00:00
重采样与频率转换
重采样是时间序列分析的核心操作,可以将高频数据转为低频,或反之。
# 创建示例数据
index = pd.date_range('2023-01-01', periods=24, freq='H')
data = pd.Series(range(24), index=index)
# 降采样为每日数据(取每日平均值)
daily_mean = data.resample('D').mean()
# 升采样并填充缺失值
upsampled = data.resample('30T').asfreq()
filled = upsampled.interpolate(method='linear')
常见的重采样方法包括:
mean()
: 计算平均值sum()
: 求和first()
: 取第一个值last()
: 取最后一个值ohlc()
: 金融领域常用的开盘、最高、最低、收盘价
滑动窗口计算
滑动窗口计算是时间序列分析的利器,可用于平滑数据、计算移动平均等。
# 创建示例数据
ts = pd.Series(np.random.randn(100),
index=pd.date_range('2023-01-01', periods=100, freq='D'))
# 7天简单移动平均
rolling_mean = ts.rolling(window=7).mean()
# 扩展窗口平均
expanding_mean = ts.expanding().mean()
# 带权重的移动平均
ewma = ts.ewm(span=7).mean()
高级窗口操作:
# 自定义聚合函数
def mid_range(x):
return (x.max() + x.min()) / 2
custom_roll = ts.rolling(window=5).apply(mid_range)
# 多列同时计算
df = pd.DataFrame({'A': ts, 'B': ts*2})
rolling_df = df.rolling(window=3).agg(['mean', 'std'])
时间序列索引操作
高效的时间序列查询依赖于正确的索引设置和操作方法。
# 设置时间索引
df = pd.DataFrame({
'value': [10, 20, 30, 40, 50]},
index=pd.to_datetime(['2023-01-01', '2023-01-02', '2023-01-03',
'2023-01-04', '2023-01-05'])
)
# 按年份切片
print(df['2023'])
# 按月份切片
print(df['2023-01'])
# 按日期范围切片
print(df['2023-01-02':'2023-01-04'])
处理不规则时间序列:
# 填充缺失日期
full_index = pd.date_range(start=df.index.min(), end=df.index.max(), freq='D')
filled_df = df.reindex(full_index)
# 前向填充
ffilled = filled_df.ffill()
# 带限制的填充
limited_fill = filled_df.fillna(method='ffill', limit=2)
实际应用案例
案例1:电商销售数据分析
# 假设sales_data包含日期和销售额
sales_data = pd.read_csv('sales.csv', parse_dates=['date'])
sales_data.set_index('date', inplace=True)
# 计算周销售额
weekly_sales = sales_data.resample('W').sum()
# 计算月环比增长率
monthly_sales = sales_data.resample('M').sum()
monthly_sales['growth_rate'] = monthly_sales['sales'].pct_change() * 100
# 季节性分析:按月份聚合
sales_data['month'] = sales_data.index.month
monthly_pattern = sales_data.groupby('month')['sales'].mean()
案例2:股票价格分析
# 获取股票数据
stock_data = pd.read_csv('stock_prices.csv', parse_dates=['date'])
stock_data.set_index('date', inplace=True)
# 计算20日移动平均
stock_data['20d_ma'] = stock_data['close'].rolling(window=20).mean()
# 计算布林带
stock_data['20d_std'] = stock_data['close'].rolling(window=20).std()
stock_data['upper_band'] = stock_data['20d_ma'] + 2*stock_data['20d_std']
stock_data['lower_band'] = stock_data['20d_ma'] - 2*stock_data['20d_std']
# 计算MACD指标
stock_data['12d_ema'] = stock_data['close'].ewm(span=12).mean()
stock_data['26d_ema'] = stock_data['close'].ewm(span=26).mean()
stock_data['MACD'] = stock_data['12d_ema'] - stock_data['26d_ema']
性能优化技巧
处理大规模时间序列数据时,性能优化至关重要:
-
使用正确的数据类型:
# 将datetime列转换为datetime64[ns]类型 df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d')
-
设置时间索引:
df.set_index('date', inplace=True)
-
使用
asof
进行高效查询:# 查找指定时间点之前的最新数据 latest_before = df.asof('2023-06-15 15:30:00')
-
批量操作替代循环:
# 不好的做法 for date in df.index: df.loc[date, 'weekday'] = date.weekday()
好的做法
df['weekday'] = df.index.weekday
5. **使用`eval`和`query`加速计算**:
```python
# 传统方式
result = df[(df['price'] > 100) & (df['volume'] < 1000)]
# 使用query
result = df.query('price > 100 and volume < 1000')
掌握这些Pandas时间序列处理技巧,你将能够高效地处理各种时间相关的数据分析任务,从基础的数据清洗到复杂的时序特征工程。随着实践经验的积累,这些技能将成为你数据分析工具箱中的利器。
还没有评论,来说两句吧...