本文目录导读:

我来详细讲解如何使用Pandas进行数据分组和密度分析,这主要用于分析数据在不同分组中的分布情况。
基础数据准备和分组
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# 创建示例数据
np.random.seed(42)
data = {
'group': np.random.choice(['A', 'B', 'C'], 1000),
'value': np.random.normal(50, 15, 1000),
'category': np.random.choice(['X', 'Y', 'Z'], 1000)
}
df = pd.DataFrame(data)
print("原始数据:")
print(df.head())
print(f"数据形状: {df.shape}")
使用groupby进行分组密度计算
# 基础分组密度计算
grouped_density = df.groupby('group')['value'].agg(['mean', 'std', 'count'])
print("\n分组统计:")
print(grouped_density)
# 计算每个分组的数据密度估计
def density_estimate(group_data):
"""计算密度估计"""
return stats.gaussian_kde(group_data)
# 为每个分组创建密度估计对象
density_objects = {}
for group in df['group'].unique():
group_data = df[df['group'] == group]['value']
density_objects[group] = stats.gaussian_kde(group_data)
print("\n密度估计对象已创建:", list(density_objects.keys()))
多列分组密度分析
# 多列分组统计
multi_group_density = df.groupby(['group', 'category']).agg({
'value': ['count', 'mean', 'std', lambda x: x.quantile(0.25), lambda x: x.quantile(0.75)]
})
print("\n多列分组统计:")
print(multi_group_density)
# 计算多组数据的密度
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
for idx, (name, group_data) in enumerate(df.groupby('category')['value']):
if idx < 3:
# 计算密度
density = stats.gaussian_kde(group_data)
x_range = np.linspace(group_data.min(), group_data.max(), 200)
axes[idx].hist(group_data, bins=30, density=True, alpha=0.7, label=f'Histogram {name}')
axes[idx].plot(x_range, density(x_range), 'r-', lw=2, label='KDE')
axes[idx].set_title(f'Category {name} Density')
axes[idx].legend()
plt.tight_layout()
plt.show()
高级密度分组分析
# 创建更复杂的密度分析
def density_profile(df, group_col, value_col):
"""创建密度分布档案"""
profiles = {}
for group_name, group_df in df.groupby(group_col):
data = group_df[value_col].values
# 基本统计
profiles[group_name] = {
'count': len(data),
'mean': np.mean(data),
'std': np.std(data),
'skewness': stats.skew(data),
'kurtosis': stats.kurtosis(data),
'percentiles': np.percentile(data, [25, 50, 75, 90, 95])
}
return pd.DataFrame(profiles).T
# 执行密度档案分析
density_profiles = density_profile(df, 'category', 'value')
print("\n密度分布档案:")
print(density_profiles)
# 概率密度函数比较
from scipy.integrate import quad
def compare_density_distributions(df, group1, group2, value_col):
"""比较两个组的密度分布"""
data1 = df[df['group'] == group1][value_col].values
data2 = df[df['group'] == group2][value_col].values
# 创建密度函数
kde1 = stats.gaussian_kde(data1)
kde2 = stats.gaussian_kde(data2)
# 计算KL散度
def kl_divergence(x):
return kde1(x) * np.log(kde1(x) / kde2(x))
# Kolmogorov-Smirnov测试
ks_statistic, p_value = stats.ks_2samp(data1, data2)
return {
'KS_statistic': ks_statistic,
'KS_p_value': p_value,
'mean_difference': np.mean(data1) - np.mean(data2)
}
# 比较不同组
results = compare_density_distributions(df, 'A', 'B', 'value')
print("\n组A和组B的密度分布比较:")
for key, value in results.items():
print(f"{key}: {value:.4f}")
可视化密度分组
# 创建综合密度可视化
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 1. 重叠密度图
ax1 = axes[0, 0]
for group, group_data in df.groupby('group')['value']:
density = stats.gaussian_kde(group_data)
x_range = np.linspace(df['value'].min(), df['value'].max(), 200)
ax1.plot(x_range, density(x_range), label=f'Group {group}', lw=2)
ax1.set_title('密度分布比较')
ax1.set_xlabel('Value')
ax1.set_ylabel('Density')
ax1.legend()
# 2. 箱线图+密度
ax2 = axes[0, 1]
grouped_data = [group['value'].values for name, group in df.groupby('group')]
ax2.boxplot(grouped_data, labels=df['group'].unique())
ax2.set_title('分组箱线图')
ax2.set_ylabel('Value')
# 3. 小提琴图(类似密度图)
ax3 = axes[1, 0]
colors = ['lightblue', 'lightgreen', 'lightcoral']
for idx, (name, group) in enumerate(df.groupby('group')):
# 创建密度图
density = stats.gaussian_kde(group['value'])
x_range = np.linspace(group['value'].min(), group['value'].max(), 200)
y_density = density(x_range)
# 绘制密度
ax3.plot(y_density, x_range, label=f'Group {name}', color=colors[idx], lw=2)
ax3.fill_between(y_density, x_range, alpha=0.3, color=colors[idx])
ax3.set_title('密度曲线(旋转)')
ax3.set_xlabel('Density')
ax3.set_ylabel('Value')
ax3.legend()
# 4. 累积密度分布
ax4 = axes[1, 1]
for group, group_data in df.groupby('group')['value']:
sorted_data = np.sort(group_data)
cdf = np.arange(1, len(sorted_data) + 1) / len(sorted_data)
ax4.plot(sorted_data, cdf, label=f'Group {group}', lw=2)
ax4.set_title('累积分布函数')
ax4.set_xlabel('Value')
ax4.set_ylabel('Cumulative Probability')
ax4.legend()
plt.tight_layout()
plt.show()
实际应用案例:销售数据分析
# 创建更实际的销售数据
np.random.seed(42)
sales_data = pd.DataFrame({
'product': np.random.choice(['电子产品', '服装', '食品', '家居'], 500),
'price': np.random.uniform(10, 1000, 500) * np.random.choice([1, 1.5, 2], 500),
'quantity': np.random.poisson(5, 500),
'region': np.random.choice(['北区', '南区', '东区', '西区'], 500)
})
# 计算销售额
sales_data['revenue'] = sales_data['price'] * sales_data['quantity']
print("\n销售数据前5行:")
print(sales_data.head())
# 按产品分组分析销售密度
product_density = sales_data.groupby('product')['revenue'].agg([
('count', 'count'),
('total', 'sum'),
('mean', 'mean'),
('std', 'std'),
('CV', lambda x: x.std() / x.mean()) # 变异系数
])
print("\n产品分组销售密度分析:")
print(product_density)
# 分析价格密度分布
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 按产品分组的价格密度
ax1 = axes[0, 0]
for product, group in sales_data.groupby('product'):
density = stats.gaussian_kde(group['price'])
x_range = np.linspace(group['price'].min(), group['price'].max(), 200)
ax1.plot(x_range, density(x_range), label=product, lw=2)
ax1.set_title('各产品价格密度分布')
ax1.set_xlabel('Price')
ax1.set_ylabel('Density')
ax1.legend()
# 按区域分组的销量密度
ax2 = axes[0, 1]
for region, group in sales_data.groupby('region'):
density = stats.gaussian_kde(group['quantity'])
x_range = np.linspace(group['quantity'].min(), group['quantity'].max(), 200)
ax2.plot(x_range, density(x_range), label=region, lw=2)
ax2.set_title('各区域销量密度分布')
ax2.set_xlabel('Quantity')
ax2.set_ylabel('Density')
ax2.legend()
# 热力图:产品-区域密度
ax3 = axes[1, 0]
pivot_table = sales_data.pivot_table(values='revenue',
index='product',
columns='region',
aggfunc='mean')
im = ax3.imshow(pivot_table, cmap='YlOrRd')
ax3.set_xticks(range(len(pivot_table.columns)))
ax3.set_yticks(range(len(pivot_table.index)))
ax3.set_xticklabels(pivot_table.columns)
ax3.set_yticklabels(pivot_table.index)
ax3.set_title('产品-区域平均销售额热力图')
plt.colorbar(im, ax=ax3)
# 销售额分布
ax4 = axes[1, 1]
for product, group in sales_data.groupby('product')['revenue']:
ax4.hist(group, bins=20, alpha=0.5, label=product)
ax4.set_title('各产品销售额分布')
ax4.set_xlabel('Revenue')
ax4.set_ylabel('Frequency')
ax4.legend()
plt.tight_layout()
plt.show()
高级密度分组技术
def create_density_matrix(df, group_cols, value_col, n_bins=50):
"""创建密度矩阵"""
groups = [df[col].unique() for col in group_cols]
density_matrix = {}
for idx, group_values in enumerate(zip(*groups)):
mask = True
for j, col in enumerate(group_cols):
mask &= (df[col] == group_values[j])
subset = df[mask][value_col].values
if len(subset) > 1:
density = stats.gaussian_kde(subset)
x = np.linspace(subset.min(), subset.max(), n_bins)
density_matrix[group_values] = {
'x': x,
'density': density(x),
'count': len(subset)
}
return density_matrix
# 执行高级密度分析
density_matrix = create_density_matrix(df, ['group', 'category'], 'value')
print("密度矩阵包含的组合:")
for key in density_matrix.keys():
print(f"{key}: {density_matrix[key]['count']} 个样本")
# 条件密度分析
def conditional_density(df, condition_col, condition_value, target_col):
"""条件密度分析"""
# 条件子集
conditioned = df[df[condition_col] == condition_value]
# 创建密度估计
density = stats.gaussian_kde(conditioned[target_col])
# 计算密度值
x_range = np.linspace(conditioned[target_col].min(),
conditioned[target_col].max(), 100)
y_density = density(x_range)
return x_range, y_density, conditioned[target_col].values
# 条件密度可视化
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
for idx, group in enumerate(['A', 'B', 'C']):
x, y, data = conditional_density(df, 'group', group, 'value')
axes[idx].plot(x, y, 'r-', lw=2)
axes[idx].hist(data, bins=20, density=True, alpha=0.3)
axes[idx].set_title(f'Group {group} 条件密度')
axes[idx].set_xlabel('Value')
axes[idx].set_ylabel('Density')
plt.tight_layout()
plt.show()
这些示例涵盖了Pandas数据分组密度分析的主要技术,核心步骤是:
- 使用groupby进行分组
- 计算分组统计量
- 利用scipy.stats进行密度估计
- 可视化密度分布
- 比较不同组的密度特征
根据你的具体数据分析需求,可以选择相应的技术进行深入分析。