You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于含出现频率的字典/DataFrame绘制boxplot?

解决方案

结论:完全不需要展开成列表

大数据集下展开会直接导致内存溢出,完全没必要。我们可以通过计算加权分位数的方式,直接基于压缩的频率数据生成符合要求的箱线图。


步骤1:处理DataFrame格式的频率数据

假设你的DataFrame包含len(长度)、num_occurrence(出现次数)、dt(日期)字段,具体实现如下:

1.1 定义加权分位数计算函数

这个函数会根据出现次数作为权重,计算箱线图所需的核心统计量,支持异常值过滤(符合1.5*IQR规则):

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

def weighted_percentile(data, weights, percents):
    data = np.asarray(data)
    weights = np.asarray(weights)
    # 按长度排序
    sorted_idx = np.argsort(data)
    sorted_data = data[sorted_idx]
    sorted_weights = weights[sorted_idx]
    # 计算累计权重
    cum_weights = np.cumsum(sorted_weights)
    total_weight = cum_weights[-1]
    # 定位分位数对应的权重位置并插值得到结果
    percentile_points = [p * total_weight for p in percents]
    return np.interp(percentile_points, cum_weights, sorted_data)

def weighted_boxplot_stats(data, weights):
    # 计算四分位数
    q25, q50, q75 = weighted_percentile(data, weights, [0.25, 0.5, 0.75])
    iqr = q75 - q25
    lower_bound = q25 - 1.5 * iqr
    upper_bound = q75 + 1.5 * iqr
    
    # 过滤异常值
    mask = (data >= lower_bound) & (data <= upper_bound)
    filtered_data = data[mask]
    filtered_weights = weights[mask]
    
    # 处理过滤后无数据的极端情况
    if len(filtered_data) == 0:
        min_val = data.min()
        max_val = data.max()
    else:
        min_val = weighted_percentile(filtered_data, filtered_weights, [0.0])[0]
        max_val = weighted_percentile(filtered_data, filtered_weights, [1.0])[0]
    
    return pd.Series([min_val, q25, q50, q75, max_val], index=['min', '25%', '50%', '75%', 'max'])

1.2 按日期分组计算加权统计量

# 假设你的DataFrame名为df
grouped_stats = df.groupby('dt').apply(
    lambda x: weighted_boxplot_stats(x['len'], x['num_occurrence'])
).reset_index()

1.3 绘制加权箱线图

基于计算好的统计量绘图,可套用seaborn样式美化:

plt.figure(figsize=(12, 6))
# 整理箱线图所需数据:每个日期对应一组[min, 25%, 50%, 75%, max]
box_data = grouped_stats[['min', '25%', '50%', '75%', 'max']].values.T
# 绘制箱线图
box = plt.boxplot(box_data, labels=grouped_stats['dt'], patch_artist=True)

# 套用seaborn样式
sns.set_style("whitegrid")
for patch in box['boxes']:
    patch.set_facecolor('#88c999')

plt.title('加权长度分布箱线图(按日期分组)')
plt.xlabel('日期')
plt.ylabel('长度')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

步骤2:处理defaultdict格式的频率数据

先将字典转换为带日期字段的DataFrame(若字典对应多个日期,需补充日期匹配逻辑),再按上述DataFlow流程处理:

from collections import defaultdict

# 假设你的defaultdict为len_counts,键是长度,值是出现次数
len_counts = defaultdict(int)
# 数据填充示例
len_counts[5] = 100
len_counts[6] = 200
len_counts[7] = 150

# 转换为DataFrame(需补充对应日期)
df_from_dict = pd.DataFrame([
    {'len': length, 'num_occurrence': count, 'dt': '2023-01-01'} 
    for length, count in len_counts.items()
])

# 后续步骤同DataFrame处理流程

内容的提问来源于stack exchange,提问作者rgowtham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 19:10:30