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

如何基于分块读取的大型CSV文件计算中位数/百分位数?

这个问题问到点子上了!分块算求和这种能直接累加的统计量确实轻松,但中位数、百分位数这类依赖数据排序分布的指标,处理起来就得换思路了。我给你两种方案,分别对应精确计算和近似计算,你可以根据自己的内存情况来挑:

精确计算中位数/百分位数(内存允许时)

如果你的机器内存能装下所有bytes_alloc列的数据(数百万行的话,假设每个值是8字节的浮点数,总大小也就几十到几百MB,大部分机器都能hold住),那直接收集所有分块的目标列再合并计算是最稳妥的,结果完全精确。

先帮你修正下现有代码里的小bug:你循环里写的for tf in df:是错误的,应该遍历read_csv返回的分块对象,变量名最好区分开,避免混淆:

import pandas as pd

# 初始化列表存储每个分块的bytes_alloc列
data_chunks = []
# 分块读取CSV
chunk_reader = pd.read_csv("../Samples/analytics/trace.csv", chunksize=1024*25)

for chunk in chunk_reader:
    # 只保留需要的列,进一步节省内存
    data_chunks.append(chunk["bytes_alloc"])

# 合并所有分块的数据
all_bytes = pd.concat(data_chunks, ignore_index=True)

# 计算中位数
median_value = all_bytes.median()
# 计算90%百分位数
p90_value = all_bytes.quantile(0.9)
# 计算95%百分位数
p95_value = all_bytes.quantile(0.95)

print(f"中位数: {median_value}")
print(f"90%百分位数: {p90_value}")
print(f"95%百分位数: {p95_value}")
近似计算(内存极度紧张时)

如果数据量实在大到连单列都存不下,那只能用近似方法。这里给你两种实用的思路:

方法1:基于分块分位数的近似估算

先统计每个分块的关键分位数(比如0%、25%、50%、75%、100%),再把这些分位数收集起来,按分块行数加权计算整体近似分位数:

import pandas as pd
import numpy as np

chunk_reader = pd.read_csv("../Samples/analytics/trace.csv", chunksize=1024*25)

# 存储每个分块的分位数和行数
quantile_list = []
row_counts = []

for chunk in chunk_reader:
    col = chunk["bytes_alloc"]
    # 计算当前分块的核心分位点,可根据需求增加更多分位点
    quantiles = col.quantile([0, 0.25, 0.5, 0.75, 1.0]).values
    quantile_list.append(quantiles)
    row_counts.append(len(col))

# 按分块行数加权计算近似中位数
approx_median = np.average([q[2] for q in quantile_list], weights=row_counts)
# 合并所有分块分位数,计算近似95%百分位数
all_quantiles = np.concatenate(quantile_list)
approx_p95 = np.percentile(all_quantiles, 95)

print(f"近似中位数: {approx_median}")
print(f"近似95%百分位数: {approx_p95}")

方法2:使用t-digest算法(更精准的近似)

t-digest是专门为超大规模数据设计的近似分位数算法,误差极小且内存占用极低。你需要先安装tdigest库(pip install tdigest),然后分块更新t-digest再计算结果:

import pandas as pd
from tdigest import TDigest

chunk_reader = pd.read_csv("../Samples/analytics/trace.csv", chunksize=1024*25)

digest = TDigest()

for chunk in chunk_reader:
    # 将当前分块的bytes_alloc数据加入t-digest
    digest.update(chunk["bytes_alloc"].values)

# 计算近似中位数和百分位数
approx_median = digest.percentile(50)
approx_p95 = digest.percentile(95)

print(f"t-digest近似中位数: {approx_median}")
print(f"t-digest近似95%百分位数: {approx_p95}")

如果你的数据分布比较均匀,近似方法的结果会非常接近精确值;如果数据极端倾斜,优先考虑精确方法(只要内存够)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:19:35