直方图实战:从 50 万条评论里看”评分是怎么分布的”

老板们拿到一份数据,第一反应不是平均值,而是 “这数据到底长啥样?”

直方图 是回答这些问题的最快方式。

一、什么是直方图?和柱状图啥区别?

老板们最容易混淆的两兄弟:

类型 数据类型 X 轴 Y 轴 适合
柱状图 离散类别 商品名(类别) 销量(数值) 类目对比(哪个卖得多)
直方图 连续数值 区间(0-10, 10-20) 频数(个数) 数据分布(分布形状)

核心区别:柱状图的 X 轴是离散的(苹果/华为/小米),直方图的 X 轴是连续的(0-10 分一档,10-20 分一档)

直方图解决 3 大问题:

  1. 数据分布形状(正态?偏态?双峰?)
  2. 数据集中位置(众数在哪个区间)
  3. 异常点检测(远离主体的孤立柱)

二、最常见的 4 大直方图应用

应用 1:评分分布

1
2
3
4
5
1星: ▍ 200条
2星: ▍▍ 800条
3星: ▍▍▍▍▍▍▍ 5000条
4星: ▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍ 12000条
5星: ▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍ 20000条

老板一眼看出:5 星最多,典型好评偏态分布

应用 2:价格分布(看定价合理性)

1
2
3
4
5
0-50元:  ▍▍▍▍▍ 1000条
50-100元: ▍▍▍▍▍▍▍▍▍▍▍ 2000条
100-200元: ▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍ 5000条
200-500元: ▍▍▍▍▍▍▍▍▍▍ 2000条
500-1000元: ▍▍▍ 500条

老板一眼看出:主销 100-200 元 → 定价/选品都对准中端。

应用 3:用户活跃度分布

1
2
3
4
5
0次:    ▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍ 3000人
1-5次: ▍▍▍▍▍▍▍▍▍▍▍▍ 1500人
5-20次: ▍▍▍▍▍ 600人
20-50次: ▍▍ 200人
50+: ▍ 50人

老板一眼看出:80% 用户只来 1 次 → 留存是大问题。

应用 4:字数分布(文本分析预处理)

1
2
3
4
0-10字:   ▍▍▍▍▍ 100条
10-50字: ▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍ 1000条
50-200字: ▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍ 5000条
200字+: ▍▍▍ 200条

老板一眼看出:大量 50-200 字评论 → 适合做主题分析。

三、Python 5 行核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import pandas as pd
from pyecharts import options as opts
from pyecharts.charts import Bar

# 1) 读数据
df = pd.read_csv('ratings.csv') # 一列:rating (1-5 星)
ratings = df['rating'].dropna().tolist()

# 2) 自动分箱(5 档)
bins = [1, 2, 3, 4, 5, 6] # [1,2) [2,3) [3,4) [4,5) [5,6)
labels = ['1星', '2星', '3星', '4星', '5星']
counts = pd.cut(ratings, bins=bins, labels=labels, right=False).value_counts().sort_index()

# 3) 画图
x_data = labels
y_data = counts.tolist()

Bar(init_opts=opts.InitOpts(width='1000px', height='500px'))
.add_xaxis(x_data)
.add_yaxis('评论数', y_data, color='#00d4ff')
.set_global_opts(
title_opts=opts.TitleOpts(title='评分分布直方图'),
xaxis_opts=opts.AxisOpts(name='评分', type_='category'),
yaxis_opts=opts.AxisOpts(name='评论数'),
)
.render('histogram.html')

四、进阶:自动分箱 + 异常点检测

1. 自动分箱(数据范围未知时)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np

data = df['rating'].dropna().values

# 3 种自动分箱策略
# ① 等宽分箱(默认)
bins_equal_width = np.linspace(data.min(), data.max(), 11) # 10 档

# ② 等频分箱(每档数据量相同)
bins_equal_freq = np.quantile(data, np.linspace(0, 1, 11))

# ③ Sturges 公式(N = log2(n) + 1)
n = len(data)
n_bins = int(np.log2(n)) + 1
bins_sturges = np.histogram_bin_edges(data, bins=n_bins)

# 推荐:等频分箱(可视化效果好)
counts, edges = np.histogram(data, bins=bins_equal_freq)

2. 异常点检测(IQR 法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def detect_outliers_iqr(data):
"""基于 IQR 的异常点检测"""
q1 = np.percentile(data, 25)
q3 = np.percentile(data, 75)
iqr = q3 - q1
lower = q1 - 1.5 * iqr
upper = q3 + 1.5 * iqr
outliers = data[(data < lower) | (data > upper)]
return outliers, (lower, upper)

# 应用
ratings_clean = df['rating'].dropna().values
outliers, bounds = detect_outliers_iqr(ratings_clean)
print(f'异常值: {outliers}')
print(f'正常范围: [{bounds[0]:.2f}, {bounds[1]:.2f}]')

案例:50 万条评论评分,发现 0.3% 评分为 0(刷单嫌疑)→ 剔除。

3. 多列对比(2 个商品)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from pyecharts import options as opts
from pyecharts.charts import Bar

# 2 个商品的评分分布
df_a = pd.read_csv('product_a_ratings.csv')['rating']
df_b = pd.read_csv('product_b_ratings.csv')['rating']

# 算百分比(归一化)
def pct_dist(series):
counts = series.value_counts().sort_index()
return (counts / counts.sum() * 100).round(2).tolist()

x_data = ['1星', '2星', '3星', '4星', '5星']
y_a = pct_dist(df_a)
y_b = pct_dist(df_b)

Bar()
.add_xaxis(x_data)
.add_yaxis('商品 A', y_a, color='#00d4ff')
.add_yaxis('商品 B', y_b, color='#ff6b6b')
.set_global_opts(
title_opts=opts.TitleOpts(title='商品 A vs B 评分分布(%)'),
xaxis_opts=opts.AxisOpts(type_='category'),
yaxis_opts=opts.AxisOpts(name='占比(%)'),
)
.render('compare.html')

结果:

1
2
3
       1星  2星  3星  4星  5星
A: 5% 8% 15% 30% 42%
B: 2% 5% 10% 33% 50%

老板一眼看出:B 商品好评率(83%)>A 商品(72%)

五、直方图 + 核密度估计(KDE)

直方图的最大问题:分档方式决定形状。KDE 曲线连续平滑,更准:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import seaborn as sns
import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8))

# 直方图
ax1.hist(ratings, bins=20, color='#00d4ff', edgecolor='black')
ax1.set_title('直方图')
ax1.set_xlabel('评分')
ax1.set_ylabel('频数')

# KDE
sns.kdeplot(ratings, ax=ax2, fill=True, color='#ff6b6b')
ax2.set_title('KDE 密度图')
ax2.set_xlabel('评分')
ax2.set_ylabel('密度')

plt.tight_layout()
plt.savefig('hist_kde.png', dpi=150)

对比:

六、踩坑大全

1. 分档太多/太少

2. 边界值被错分

3. Y 轴量级差太大

4. 多列对比时颜色撞色

5. 数据为空 / NaN

七、软件功能

我们的 数据分析直方图软件 ¥9.80(全店最便宜):

功能 详情
输入 Excel / CSV / TXT,单列或多列
分箱 等宽 / 等频 / Sturges / 自定义边界
对比 2-5 列同图对比(自动归一化 %)
异常检测 IQR / 3σ / 自定义阈值,自动标红
KDE 一键叠加密度曲线
输出 HTML(可交互) + PNG(4K) + 统计表
平台 Windows / Mac(Apple + Intel)

为什么这么便宜(¥9.80)? 因为它是所有分析软件的基础——几乎每个分析报告里都有直方图。老板买回去当工具用,顺手就买了我们词频、LDA、情感。

八、典型用户场景

① 运营分析:评分分布、销量分布、用户活跃度分布
② 数据预处理:发现异常值 / 缺失值,定清洗策略
③ 学术研究:实验数据分布、问卷数据分布
④ 财务分析:工资分布、成本分布、毛利分布
⑤ 文本分析预处理:评论字数分布、关键词频数分布

九、立即试用

软件 售价 适用场景
数据分析直方图软件 ¥9.80 数据分布 + 异常检测
词频统计软件 ¥26.80 文本频数
情感分析软件 ¥29.80 评论情感
一站式文本分析套餐 ¥68.00 入门组合

本文由 小朵科技工作室 原创,专注 Python 数据可视化 6 年。