ES 聚合查询 → 数据解析为 DataFrame → 选择可视化工具 → 绘制图表 → 优化细节 → 保存/展示

在 Python 中使用 Elasticsearch(ES)进行数据可视化,核心流程是「ES 数据查询→结果解析为 DataFrame→用可视化库生成图表」。ES 负责高效聚合/筛选数据,Python 借助 Matplotlib/Seaborn(基础可视化)、Plotly(交互式可视化)、Pyecharts(中国式美观图表)等库,将数据转化为「趋势图、柱状图、饼图、热力图」等直观形式。以下是 4 类核心可视化场景 + 完整代码 + 优化技巧,覆盖从基础报表到交互式仪表盘的需求。

一、前置准备

1. 安装核心依赖库

# 基础依赖(ES 交互+数据处理+基础可视化)
pip install elasticsearch pandas matplotlib seaborn
# 可选依赖(交互式/美观图表)
pip install plotly pyecharts openpyxl

2. 基础配置(ES 连接+数据准备)

假设已完成 ES 索引创建(如电商订单索引 orders)和数据预处理,先通过 Python 连接 ES 并获取分析数据(示例:近30天订单数据):

from elasticsearch import Elasticsearch
import pandas as pd
from dotenv import load_dotenv
import os

# 加载环境变量(ES 地址、账号密码)
load_dotenv()

# 连接 ES
es = Elasticsearch(
    os.getenv("ES_URL", "http://localhost:9200"),
    basic_auth=(os.getenv("ES_USER", "elastic"), os.getenv("ES_PWD", "your-password"))
)

# 定义 ES 查询(近30天已支付订单,按城市/日期/分类聚合)
def get_es_analysis_data():
    # 1. 按城市分组(销量排名)
    city_query = {
        "size": 0,
        "query": {"bool": {"filter": [{"term": {"status": "paid"}}, {"range": {"pay_time": {"gte": "now-30d"}}}]}},
        "aggs": {"city_group": {"terms": {"field": "city", "size": 10}, "aggs": {"total_amount": {"sum": {"field": "amount"}}}}}
    }
    city_response = es.search(index="orders", body=city_query)
    city_data = [(b["key"], b["total_amount"]["value"]) for b in city_response["aggregations"]["city_group"]["buckets"]]
    city_df = pd.DataFrame(city_data, columns=["城市", "总金额(元)"])

    # 2. 按天分组(趋势分析)
    trend_query = {
        "size": 0,
        "query": {"bool": {"filter": [{"term": {"status": "paid"}}, {"range": {"pay_time": {"gte": "now-30d"}}}]}},
        "aggs": {"daily_trend": {"date_histogram": {"field": "pay_time", "calendar_interval": "day", "format": "yyyy-MM-dd"}, "aggs": {"order_count": {"count": {}}}}}
    }
    trend_response = es.search(index="orders", body=trend_query)
    trend_data = [(b["key_as_string"], b["order_count"]["value"]) for b in trend_response["aggregations"]["daily_trend"]["buckets"]]
    trend_df = pd.DataFrame(trend_data, columns=["日期", "订单数"])

    # 3. 按商品分类分组(占比分析)
    category_query = {
        "size": 0,
        "query": {"bool": {"filter": [{"term": {"status": "paid"}}, {"range": {"pay_time": {"gte": "now-30d"}}}]}},
        "aggs": {"category_group": {"terms": {"field": "category", "size": 8}, "aggs": {"order_count": {"count": {}}}}}
    }
    category_response = es.search(index="orders", body=category_query)
    category_data = [(b["key"], b["order_count"]["value"]) for b in category_response["aggregations"]["category_group"]["buckets"]]
    category_df = pd.DataFrame(category_data, columns=["商品分类", "订单数"])

    return city_df, trend_df, category_df

# 获取分析数据
city_df, trend_df, category_df = get_es_analysis_data()
print("✅ 数据获取完成")
print("城市销量数据:\n", city_df.head())
print("每日趋势数据:\n", trend_df.head())
print("商品分类数据:\n", category_df.head())

二、核心可视化场景(基础+进阶)

场景 1:基础可视化(Matplotlib/Seaborn)

适合快速生成静态图表(如报表附件、论文图表),风格简洁、易定制。

1.1 柱状图(城市销量排名 TOP10)
import matplotlib.pyplot as plt
import seaborn as sns

# 设置中文显示+图表风格
plt.rcParams['font.sans-serif'] = ['SimHei']  # Windows:SimHei,Mac:Arial Unicode MS
plt.rcParams['axes.unicode_minus'] = False
sns.set_style("whitegrid")  # 白色网格风格

# 创建图表
plt.figure(figsize=(12, 6))
# 绘制柱状图(按总金额降序)
city_df_sorted = city_df.sort_values("总金额(元)", ascending=False)
sns.barplot(x="城市", y="总金额(元)", data=city_df_sorted, palette="viridis")

# 美化图表
plt.title("近30天各城市订单总金额TOP10", fontsize=14, pad=20)
plt.xlabel("城市", fontsize=12)
plt.ylabel("总金额(元)", fontsize=12)
plt.xticks(rotation=45)  # 城市名称旋转45度,避免重叠
plt.grid(axis='y', alpha=0.3)  # 横向网格线(透明度0.3)

# 标注数值(在柱子顶部显示金额)
for i, v in enumerate(city_df_sorted["总金额(元)"]):
    plt.text(i, v + max(city_df_sorted["总金额(元)"]) * 0.01, f"{round(v, 2)}", ha='center', fontsize=10)

# 保存图表(高清无白边)
plt.tight_layout()
plt.savefig("城市销量排名.png", dpi=300, bbox_inches='tight')
plt.show()
1.2 折线图(每日订单趋势)
plt.figure(figsize=(14, 6))
# 绘制折线图(带标记点)
sns.lineplot(x="日期", y="订单数", data=trend_df, color="#2E86AB", linewidth=2, marker="o", markersize=6)

# 美化图表
plt.title("近30天每日订单数趋势", fontsize=14, pad=20)
plt.xlabel("日期", fontsize=12)
plt.ylabel("订单数", fontsize=12)
plt.xticks(rotation=60)  # 日期旋转60度
plt.grid(alpha=0.3)

# 标注峰值(订单数最大的日期)
max_order_day = trend_df.loc[trend_df["订单数"].idxmax()]
plt.annotate(
    f'峰值:{max_order_day["订单数"]}单',
    xy=(max_order_day["日期"], max_order_day["订单数"]),
    xytext=(max_order_day["日期"], max_order_day["订单数"] + 5),
    ha='center',
    arrowprops=dict(arrowstyle='->', color='red')
)

plt.tight_layout()
plt.savefig("每日订单趋势.png", dpi=300, bbox_inches='tight')
plt.show()
1.3 饼图(商品分类占比)
plt.figure(figsize=(10, 10))
# 绘制饼图(带百分比)
colors = sns.color_palette("Set3")  # 配色方案
wedges, texts, autotexts = plt.pie(
    category_df["订单数"],
    labels=category_df["商品分类"],
    autopct='%1.1f%%',  # 百分比保留1位小数
    colors=colors,
    startangle=90,  # 起始角度90度(垂直方向)
    explode=[0.05] * len(category_df)  # 每个扇形向外偏移5%,增强立体感
)

# 美化文字
plt.setp(texts, fontsize=12)
plt.setp(autotexts, fontsize=11, color="white", weight="bold")

plt.title("近30天各商品分类订单占比", fontsize=14, pad=20)
plt.axis('equal')  # 保证饼图为正圆形
plt.tight_layout()
plt.savefig("商品分类占比.png", dpi=300, bbox_inches='tight')
plt.show()

场景 2:交互式可视化(Plotly)

适合生成可交互图表(如网页仪表盘),支持缩放、悬停显示详情、下载图片,体验更优。

2.1 交互式柱状图(城市销量)
import plotly.express as px

# 绘制交互式柱状图
fig = px.bar(
    city_df_sorted,
    x="城市",
    y="总金额(元)",
    title="近30天各城市订单总金额TOP10",
    color="总金额(元)",  # 按金额着色(渐变)
    color_continuous_scale="viridis",  # 渐变配色
    text="总金额(元)"  # 柱子顶部显示金额
)

# 美化配置
fig.update_layout(
    xaxis_title="城市",
    yaxis_title="总金额(元)",
    xaxis_tickangle=-45,  # 城市名称旋转-45度
    template="plotly_white",  # 白色模板
    coloraxis_showscale=False  # 隐藏颜色条(无需重复显示)
)

# 优化数值显示(保留2位小数)
fig.update_traces(
    texttemplate='%{text:.2f}',
    textposition='outside'  # 数值显示在柱子外部
)

# 显示图表(自动打开浏览器)
fig.show()
# 保存为HTML文件(可嵌入网页)
fig.write_html("交互式城市销量排名.html")
2.2 交互式折线图(每日趋势)
fig = px.line(
    trend_df,
    x="日期",
    y="订单数",
    title="近30天每日订单数趋势",
    markers=True,  # 显示标记点
    color_discrete_sequence=["#2E86AB"]  # 线条颜色
)

# 美化配置
fig.update_layout(
    xaxis_title="日期",
    yaxis_title="订单数",
    xaxis_tickangle=-60,
    template="plotly_white",
    hovermode="x unified"  # 悬停时显示同一日期的所有数据
)

# 显示峰值标注
max_order_day = trend_df.loc[trend_df["订单数"].idxmax()]
fig.add_annotation(
    x=max_order_day["日期"],
    y=max_order_day["订单数"],
    text=f'峰值:{max_order_day["订单数"]}单',
    showarrow=True,
    arrowhead=1,
    arrowcolor="red"
)

fig.show()
fig.write_html("交互式每日订单趋势.html")

场景 3:中国式美观图表(Pyecharts)

适合生成符合国内审美习惯的图表(如政务报表、企业汇报),支持动态效果和丰富组件。

3.1 柱状图(城市销量排名)
from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.globals import ThemeType

# 准备数据(Pyecharts 要求格式:[(城市1, 金额1), (城市2, 金额2)])
city_data_pye = list(zip(city_df_sorted["城市"], city_df_sorted["总金额(元)"].round(2)))

# 创建柱状图(指定主题:明亮风格)
bar = (
    Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT, width="1200px", height="600px"))
    .add_xaxis([x[0] for x in city_data_pye])
    .add_yaxis("总金额(元)", [x[1] for x in city_data_pye], itemstyle_opts=opts.ItemStyleOpts(color="#4CAF50"))
    .set_global_opts(
        title_opts=opts.TitleOpts(title="近30天各城市订单总金额TOP10", subtitle="数据来源:Elasticsearch", pos_left="center"),
        xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-45)),
        yaxis_opts=opts.AxisOpts(name="总金额(元)"),
        legend_opts=opts.LegendOpts(pos_bottom="5%"),
    )
    .set_series_opts(
        label_opts=opts.LabelOpts(is_show=True, position="top", formatter="{c}"),  # 顶部显示数值
        markpoint_opts=opts.MarkPointOpts(
            data=[opts.MarkPointItem(type_="max", name="最大值"), opts.MarkPointItem(type_="min", name="最小值")]
        )
    )
)

# 保存为HTML文件
bar.render("Pyecharts城市销量排名.html")
print("✅ Pyecharts图表已保存为 HTML 文件")
3.2 饼图(商品分类占比)
from pyecharts.charts import Pie

# 准备数据
category_data_pye = list(zip(category_df["商品分类"], category_df["订单数"]))

# 创建饼图
pie = (
    Pie(init_opts=opts.InitOpts(theme=ThemeType.LIGHT, width="1000px", height="800px"))
    .add(
        series_name="订单数",
        data_pair=category_data_pye,
        radius=["30%", "75%"],  # 内半径30%,外半径75%(环形饼图)
        center=["50%", "50%"],  # 居中显示
        rosetype="radius"  # 玫瑰图样式(扇形大小随数值变化)
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="近30天商品分类订单占比", pos_left="center"),
        legend_opts=opts.LegendOpts(orient="vertical", pos_top="15%", pos_left="2%")  # 图例垂直显示在左侧
    )
    .set_series_opts(
        label_opts=opts.LabelOpts(formatter="{b}: {c} ({d}%)")  # 显示:分类名+数量+百分比
    )
)

pie.render("Pyecharts商品分类占比.html")

场景 4:多图表仪表盘(子图组合)

将多个图表组合为一个仪表盘,适合综合展示分析结果(如业务监控大屏)。

4.1 Matplotlib 子图组合
plt.figure(figsize=(20, 12))

# 子图1:城市销量柱状图(左上)
plt.subplot(2, 2, 1)
city_df_sorted_top5 = city_df_sorted.head(5)  # 仅显示TOP5
sns.barplot(x="城市", y="总金额(元)", data=city_df_sorted_top5, palette="viridis")
plt.title("城市销量TOP5", fontsize=12)
plt.xlabel("")
plt.xticks(rotation=45)
for i, v in enumerate(city_df_sorted_top5["总金额(元)"]):
    plt.text(i, v + max(city_df_sorted_top5["总金额(元)"]) * 0.01, f"{round(v, 2)}", ha='center', fontsize=9)

# 子图2:每日订单趋势折线图(右上)
plt.subplot(2, 2, 2)
sns.lineplot(x="日期", y="订单数", data=trend_df, color="#2E86AB", linewidth=2)
plt.title("每日订单趋势", fontsize=12)
plt.xlabel("")
plt.xticks(rotation=60)

# 子图3:商品分类饼图(左下)
plt.subplot(2, 2, 3)
plt.pie(category_df["订单数"], labels=category_df["商品分类"], autopct='%1.1f%%', colors=sns.color_palette("Set3"))
plt.title("商品分类占比", fontsize=12)
plt.axis('equal')

# 子图4:订单数分布直方图(右下)
plt.subplot(2, 2, 4)
sns.histplot(trend_df["订单数"], bins=10, kde=True, color="#A23B72")  # kde:密度曲线
plt.title("订单数分布", fontsize=12)
plt.xlabel("订单数")
plt.ylabel("天数")

# 总标题
plt.suptitle("近30天电商订单数据分析仪表盘", fontsize=16, y=0.98)
plt.tight_layout()
plt.savefig("数据分析仪表盘.png", dpi=300, bbox_inches='tight')
plt.show()
4.2 Plotly 交互式仪表盘
import plotly.subplots as sp

# 创建2x2子图
fig = sp.make_subplots(
    rows=2, cols=2,
    subplot_titles=("城市销量TOP5", "每日订单趋势", "商品分类占比", "订单数分布"),
    specs=[
        [{"type": "bar"}, {"type": "scatter"}],  # 第一行:柱状图+折线图
        [{"type": "pie"}, {"type": "histogram"}]  # 第二行:饼图+直方图
    ]
)

# 子图1:城市销量TOP5
city_top5 = city_df_sorted.head(5)
fig.add_trace(px.bar(city_top5, x="城市", y="总金额(元)").data[0], row=1, col=1)

# 子图2:每日订单趋势
fig.add_trace(px.line(trend_df, x="日期", y="订单数").data[0], row=1, col=2)

# 子图3:商品分类占比
fig.add_trace(px.pie(category_df, values="订单数", names="商品分类").data[0], row=2, col=1)

# 子图4:订单数分布
fig.add_trace(px.histogram(trend_df, x="订单数").data[0], row=2, col=2)

# 全局配置
fig.update_layout(
    height=800, width=1200,
    title_text="近30天电商订单数据分析仪表盘",
    title_x=0.5,
    template="plotly_white"
)

fig.show()
fig.write_html("交互式数据分析仪表盘.html")

三、可视化优化技巧(提升图表质感)

1. 配色方案选择

  • 专业配色:seabornviridis(蓝绿渐变)、plasma(紫橙渐变),适合数据对比;
  • 和谐配色:Set2/Set3(多分类场景),避免颜色冲突;
  • 品牌配色:根据企业品牌色自定义(如 color="#1E40AF" 深蓝色)。

2. 图表细节优化

  • 标题:简洁明了(含时间范围+核心指标),字体大小14-16;
  • 坐标轴:标签清晰,避免重叠(旋转角度45-60度),添加单位(如「元」「单」);
  • 数值标注:重要图表添加数值标签,避免读者猜测;
  • 网格线:仅保留横向网格线,透明度0.3-0.5(不干扰数据展示)。

3. 性能优化(大数据量场景)

  • 数据采样:当 ES 返回数据量达10万+时,先采样(如取前1000条)再可视化;
  • 分桶聚合:在 ES 中完成分桶(如按天/按城市),避免 Python 处理海量原始数据;
  • 异步加载:Plotly/Pyecharts 生成的 HTML 图表,支持异步加载数据,提升打开速度。

4. 交互体验优化(交互式图表)

  • 悬停效果:显示详细信息(如日期+订单数+总金额);
  • 缩放/平移:支持鼠标缩放图表,查看局部细节;
  • 下载功能:Plotly/Pyecharts 自带图片下载按钮,方便导出;
  • 筛选功能:Plotly 支持添加下拉框/滑块,动态筛选数据(如按月份筛选)。

四、常见问题与避坑指南

  1. 中文乱码

    • 原因:Matplotlib 默认不支持中文字体;
    • 解决:设置 plt.rcParams['font.sans-serif'] = ['SimHei'](Windows)或 ['Arial Unicode MS'](Mac)。
  2. 图表保存后白边过多

    • 解决:使用 plt.tight_layout() 自动调整布局,保存时添加 bbox_inches='tight'(去除白边)。
  3. Plotly 图表无法显示

    • 原因:Jupyter 环境未启用 Plotly 渲染器;
    • 解决:在代码开头添加 import plotly.io as pio; pio.renderers.default='browser'(自动打开浏览器显示)。
  4. 数据量过大导致图表卡顿

    • 解决:在 ES 中通过 size/from 分页,或按时间/维度分桶,减少 Python 处理的数据量。

五、总结:可视化工具选择指南

工具优势适用场景
Matplotlib/Seaborn轻量、灵活、定制性强静态报表、论文图表、快速原型
Plotly交互式强、支持网页嵌入、体验好网页仪表盘、动态数据分析、分享展示
Pyecharts中国式审美、动态效果丰富、文档友好企业汇报、政务报表、国内业务场景

核心流程总结:

ES 聚合查询 → 数据解析为 DataFrame → 选择可视化工具 → 绘制图表 → 优化细节 → 保存/展示

关键建议:

  1. 优先在 ES 中完成数据筛选和聚合,减少 Python 数据处理压力;
  2. 静态图表用 Matplotlib/Seaborn,交互式图表用 Plotly,国内场景用 Pyecharts;
  3. 图表需「数据准确+逻辑清晰+美观易读」,避免过度装饰;
  4. 复杂仪表盘可结合 Flask/FastAPI 搭建网页服务,集成 Plotly/Pyecharts 图表实现实时刷新。

按以上场景和技巧,可覆盖 Python 中 90% 以上的 ES 数据可视化需求,从快速分析到企业级汇报均适用。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值