本文目录导读:

我来为你详细介绍如何使用Pandas进行数据分组和高可用重采样,我会通过多个实用案例来展示。
基础环境准备
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
# 创建示例数据
np.random.seed(42)
# 生成时间序列数据
dates = pd.date_range('2024-01-01', periods=1000, freq='H')
data = pd.DataFrame({
'date': dates,
'group': np.random.choice(['A', 'B', 'C'], 1000),
'value1': np.random.randn(1000) * 10 + 50,
'value2': np.random.randn(1000) * 5 + 20
})
print("数据预览:")
print(data.head())
print(f"数据形状: {data.shape}")
数据分组操作
1 基本分组统计
# 按组进行基础统计
group_stats = data.groupby('group').agg({
'value1': ['mean', 'std', 'min', 'max'],
'value2': ['mean', 'std', 'min', 'max']
})
print("分组统计结果:")
print(group_stats)
# 分组并计算多个统计量
detailed_stats = data.groupby('group').agg(
value1_mean=('value1', 'mean'),
value1_median=('value1', 'median'),
value1_std=('value1', 'std'),
value2_mean=('value2', 'mean'),
count=('value1', 'count')
)
print("\n详细分组统计:")
print(detailed_stats)
2 多级分组
# 创建更多分组维度
data['category'] = np.random.choice(['X', 'Y', 'Z'], 1000)
data['month'] = data['date'].dt.month
# 多级分组
multi_group = data.groupby(['group', 'category', 'month']).agg({
'value1': ['mean', 'count'],
'value2': 'sum'
})
print("多级分组结果:")
print(multi_group.head(12))
# 重置索引便于查看
multi_group_flat = multi_group.reset_index()
print("\n重置索引后的数据:")
print(multi_group_flat.head())
时间序列重采样
1 设置时间索引
# 将date列设置为索引
data_ts = data.set_index('date')
print("时间序列数据:")
print(data_ts.head())
2 不同频率的重采样
# 日重采样
daily_resample = data_ts.resample('D').agg({
'value1': ['mean', 'max', 'min'],
'value2': 'sum'
})
print("日重采样结果:")
print(daily_resample.head())
# 周重采样
weekly_resample = data_ts.resample('W').agg({
'value1': 'mean',
'value2': 'sum'
})
print("\n周重采样结果:")
print(weekly_resample.head())
# 月重采样
monthly_resample = data_ts.resample('M').agg({
'value1': ['mean', 'std'],
'value2': ['sum', 'mean']
})
print("\n月重采样结果:")
print(monthly_resample.head())
分组+重采样(高可用方案)
1 按组重采样
# 按组分组的重采样
def resample_by_group(df, group_col='group', date_col='date', freq='D'):
"""
按组分组的重采样函数
Parameters:
-----------
df : DataFrame
group_col : str, 分组列名
date_col : str, 日期列名
freq : str, 重采样频率
Returns:
--------
DataFrame : 重采样后的数据
"""
# 确保日期列是datetime类型
df[date_col] = pd.to_datetime(df[date_col])
# 按组设置索引并重采样
result = df.set_index(date_col).groupby(group_col).resample(freq).mean()
return result
# 使用函数进行分组重采样
group_resampled = resample_by_group(data, freq='W')
print("分组周重采样结果:")
print(group_resampled.head(12))
2 高性能分组重采样
import pandas as pd
from concurrent.futures import ThreadPoolExecutor
import functools
class HighAvailabilityResampler:
"""高可用分组重采样器"""
def __init__(self, df, date_col='date', group_col='group'):
self.df = df
self.date_col = date_col
self.group_col = group_col
self.df[date_col] = pd.to_datetime(self.df[date_col])
def resample_group(self, group_data, freq='D', agg_func='mean'):
"""对单个组进行重采样"""
try:
result = (group_data
.set_index(self.date_col)
.resample(freq)
.agg(agg_func))
result[self.group_col] = group_data[self.group_col].iloc[0]
return result
except Exception as e:
print(f"重采样错误: {e}")
return None
def parallel_resample(self, freq='D', agg_func='mean', n_workers=4):
"""并行重采样"""
# 按组分批
groups = [group for name, group in self.df.groupby(self.group_col)]
# 使用线程池并行处理
with ThreadPoolExecutor(max_workers=n_workers) as executor:
partial_func = functools.partial(
self.resample_group,
freq=freq,
agg_func=agg_func
)
results = list(executor.map(partial_func, groups))
# 合并结果
final_result = pd.concat(results, ignore_index=False)
return final_result.sort_index()
# 使用高可用重采样器
resampler = HighAvailabilityResampler(data)
result_high_avail = resampler.parallel_resample(freq='D', n_workers=3)
print("高可用并行重采样结果:")
print(result_high_avail.head())
实际应用案例
1 股票数据分组重采样
# 模拟股票数据
def generate_stock_data(n_stocks=5, days=365):
"""生成模拟股票数据"""
stocks = [f'Stock_{i}' for i in range(n_stocks)]
dates = pd.date_range('2024-01-01', periods=days, freq='D')
data_list = []
for stock in stocks:
base_price = np.random.uniform(50, 200)
prices = np.random.randn(days) * 2 + base_price
prices = np.abs(prices) * 0.5 + np.cumsum(np.random.randn(days) * 0.5)
prices = base_price + prices.cumsum()
df = pd.DataFrame({
'date': dates,
'stock': stock,
'open': prices,
'high': prices * (1 + np.random.uniform(0, 0.05, days)),
'low': prices * (1 - np.random.uniform(0, 0.05, days)),
'close': prices * (1 + np.random.randn(days) * 0.02),
'volume': np.random.randint(1000, 100000, days)
})
data_list.append(df)
return pd.concat(data_list, ignore_index=True)
# 生成股票数据
stock_data = generate_stock_data(5, 365)
print("股票数据预览:")
print(stock_data.head())
# 按股票分组并计算周度统计
weekly_stock_stats = (stock_data
.set_index('date')
.groupby('stock')
.resample('W')
.agg({
'open': 'first',
'high': 'max',
'low': 'min',
'close': 'last',
'volume': 'sum'
}))
print("\n股票周度统计:")
print(weekly_stock_stats.head(10))
2 传感器数据分组重采样
# 模拟物联网传感器数据
def generate_sensor_data(n_sensors=10, hours=720):
"""生成模拟传感器数据"""
sensors = [f'Sensor_{i:03d}' for i in range(n_sensors)]
timestamps = pd.date_range('2024-01-01', periods=hours, freq='H')
data_list = []
for sensor in sensors:
# 每个传感器有不同的基准值
base_temp = np.random.uniform(20, 30)
base_humidity = np.random.uniform(40, 70)
df = pd.DataFrame({
'timestamp': timestamps,
'sensor_id': sensor,
'temperature': base_temp + np.random.randn(hours) * 2,
'humidity': base_humidity + np.random.randn(hours) * 5,
'pressure': 1013 + np.random.randn(hours) * 10,
'battery': np.random.uniform(3.3, 4.2, hours)
})
data_list.append(df)
return pd.concat(data_list, ignore_index=True)
# 生成传感器数据
sensor_data = generate_sensor_data(10, 720)
print("传感器数据预览:")
print(sensor_data.head())
# 按传感器分组进行日度统计
daily_sensor_stats = (sensor_data
.set_index('timestamp')
.groupby('sensor_id')
.resample('D')
.agg({
'temperature': ['mean', 'min', 'max', 'std'],
'humidity': ['mean', 'std'],
'pressure': 'mean',
'battery': 'min'
}))
print("\n传感器日度统计:")
print(daily_sensor_stats.head(10))
性能优化技巧
class OptimizedResampler:
"""优化的分组重采样器"""
def __init__(self, df):
self.df = df
def chunked_resample(self, group_col='group', date_col='date',
freq='D', chunksize=1000):
"""分块重采样,适用于大数据"""
chunks = []
for chunk_start in range(0, len(self.df), chunksize):
chunk = self.df.iloc[chunk_start:chunk_start + chunksize]
# 处理当前块
processed = (chunk
.set_index(date_col)
.groupby(group_col)
.resample(freq)
.mean()
.fillna(method='ffill'))
chunks.append(processed)
return pd.concat(chunks)
def cached_resample(self, group_col='group', date_col='date', freq='D'):
"""带缓存的重采样"""
from functools import lru_cache
@lru_cache(maxsize=128)
def _cached_resample(group_name, start_date, end_date, freq):
mask = (self.df[group_col] == group_name) & \
(self.df[date_col] >= start_date) & \
(self.df[date_col] <= end_date)
subset = self.df[mask]
return (subset
.set_index(date_col)
.resample(freq)
.mean())
# 使用缓存的示例
results = []
for group in self.df[group_col].unique():
date_range = self.df[self.df[group_col] == group][date_col]
result = _cached_resample(
group,
date_range.min(),
date_range.max(),
freq
)
results.append(result)
return pd.concat(results)
# 性能测试
import time
# 创建较大数据集
large_data = pd.DataFrame({
'date': pd.date_range('2024-01-01', periods=10000, freq='H'),
'group': np.random.choice(['A', 'B', 'C', 'D', 'E'], 10000),
'value1': np.random.randn(10000),
'value2': np.random.randn(10000)
})
# 测试不同方法
print("性能测试结果:")
# 方法1: 直接重采样
start = time.time()
result1 = (large_data
.set_index('date')
.groupby('group')
.resample('D')
.mean())
print(f"直接重采样: {time.time()-start:.3f}秒")
# 方法2: 使用优化重采样器
start = time.time()
optimized = OptimizedResampler(large_data)
result2 = optimized.chunked_resample(chunksize=2000)
print(f"分块重采样: {time.time()-start:.3f}秒")
异常处理和监控
import logging
from datetime import datetime
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class RobustResampler:
"""健壮的分组重采样器,带有异常处理和监控"""
def __init__(self, df):
self.df = df
self.metrics = {
'total_groups': 0,
'successful_groups': 0,
'failed_groups': 0,
'total_records': len(df)
}
def resample_with_fallback(self, group_col='group', date_col='date',
freq='D', agg_func='mean'):
"""带失败转移的重采样"""
result_data = []
for name, group in self.df.groupby(group_col):
self.metrics['total_groups'] += 1
try:
# 尝试标准重采样
resampled = (group
.set_index(date_col)
.resample(freq)
.agg(agg_func))
self.metrics['successful_groups'] += 1
result_data.append(resampled)
except Exception as e:
self.metrics['failed_groups'] += 1
logger.warning(f"组 {name} 重采样失败: {e}")
# 尝试替代方法
try:
# 使用前向填充作为回退
resampled = (group
.set_index(date_col)
.resample(freq)
.ffill()
.iloc[0:1])
logger.info(f"组 {name} 使用前向填充成功")
self.metrics['successful_groups'] += 1
result_data.append(resampled)
except:
logger.error(f"组 {name} 所有方法都失败")
# 记录统计信息
self._log_metrics()
return pd.concat(result_data, ignore_index=False) if result_data else pd.DataFrame()
def _log_metrics(self):
"""记录处理指标"""
logger.info(f"""
处理完成:
- 总组数: {self.metrics['total_groups']}
- 成功: {self.metrics['successful_groups']}
- 失败: {self.metrics['failed_groups']}
- 总记录数: {self.metrics['total_records']}
""")
# 使用鲁棒重采样器
robust_resampler = RobustResampler(large_data)
robust_result = robust_resampler.resample_with_fallback(freq='W', agg_func='mean')
print("\n鲁棒重采样结果:")
print(robust_result.head())
案例展示了Pandas在数据分组和重采样方面的强大功能:
- 基本分组操作:使用
groupby()进行数据聚合 - 时间序列重采样:使用
resample()进行不同频率的转换 - 分组+重采样:结合两者进行复杂的数据处理
- 高可用方案:并行处理、缓存优化、异常处理
- 实际应用:股票数据、传感器数据处理
- 性能优化:分块处理、并行计算、监控日志
这些技术可以应用于金融数据分析、物联网数据处理、业务报表生成等场景,记住要根据数据规模和业务需求选择合适的方法。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播