『玩转Streamlit』--集成Matplotlib

Steamlit虽然也自带了一些绘图组件(比如折线图,柱状图和散点图等等),但是都比较简单,

Python传统的可视化库比起来,功能上差了很多。

本篇介绍如何在Streamlit App中使用Matplotlib库来绘图。

1. st.pyplot函数

st.pyplot函数专门用于在Steamlit应用中显示 Matplotlib 绘制的图形。

这个函数能够直接将Matplotlib Figure对象直接渲染到页面的指定位置上。

st.pyplot的参数不多,主要有:

名称 类型 说明
fig Figure对象 要渲染的 Matplotlib Figure 对象
clear_figure bool 控制图形渲染后是否清除
use_container_width bool 决定是否使用父容器的宽度覆盖图形的原始宽度

最重要的就是fig参数,它是通过 Matplotlib 的常规绘图方式创建图形对象。

也就是说,我们绘制图形时,完全不用考虑Streamlit,正常使用Matplotlib来绘图,

绘制之后直接将Matplotlibfig对象传给st.pyplot函数即可。

2. Matplotlib兼容性问题

在使用 MatplotlibStreamlit 结合时,可能会遇到一些兼容性问题。

Matplotlib 支持多种 Backend,如果在使用过程中出现错误,可以尝试将Backend设置为TkAgg

具体的设置方法如下:

  1. 打开~/.matplotlib/matplotlibrc文件,如果不存在就创建一个
  2. 在上面的文件中添加一行:backend: TkAgg

如果是windows系统,上面的文件路径改为:C:\Users\%username%\.matplotlib\matplotlibrc

此外,Matplotlib 在多线程环境下可能会出现问题,因为它本身对线程的支持并不完善。

当部署和共享应用程序时,由于可能存在并发用户,这个问题可能会更加突出。

为了解决这个问题,建议使用RendererAgg.lock来包裹 Matplotlib 相关代码,如下所示:

from matplotlib.backends.backend_agg import RendererAgg
_lock = RendererAgg.lock

with _lock:
    fig.title('sample figure')
    fig.plot([1,20,3,50])
    st.pyplot(fig)

3. 使用示例

下面通过两个根据实际情况简化的示例来演示两者结合的效果。

3.1. 模拟数据分析项目

这个示例中,我们使用 np.random 函数生成了包含三列不同类型随机数据的 DataFrame

在数据分析与可视化部分,根据选择的列进行不同类型的绘图操作,

  • 当选择 Column1Column2 时绘制柱状图或直方图
  • 当选择 Column3 时可选择绘制 Column1Column2 的散点图

本示例主要展示了 StreamlitMatplotlib 结合在数据探索和分析可视化方面的便利性与交互性。

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

import matplotlib

# 为了显示中文
matplotlib.rcParams["font.sans-serif"] = ["Microsoft YaHei Mono"]
matplotlib.rcParams["axes.unicode_minus"] = False


# 生成随机数据
@st.cache_data
def generate_data():
    # 生成 100 行 3 列的随机数据
    data = {
        "Column1": np.random.randint(1, 100, 100),
        "Column2": np.random.normal(50, 10, 100),
        "Column3": np.random.choice(["A", "B", "C"], 100),
    }
    return pd.DataFrame(data)


data = generate_data()

# 数据探索部分
st.subheader("数据探索")
st.write(data.head())

# 数据分析与可视化
st.subheader("数据分析与可视化")
# 选择分析的列
selected_column = st.selectbox("选择要分析的列", data.columns)

# 使用 Matplotlib 绘制柱状图
if selected_column in ["Column1", "Column2"]:
    fig, ax = plt.subplots()
    if selected_column == "Column1":
        sns.countplot(data=data, x=selected_column, ax=ax)
    else:
        sns.histplot(data=data, x=selected_column, kde=True, ax=ax)
    ax.set_title(f"{selected_column} 分布情况")
    ax.set_xlabel(selected_column)
    ax.set_ylabel("数量")
    st.pyplot(fig)

# 绘制散点图(以 Column1 和 Column2 为例)
elif selected_column == "Column3":
    if st.checkbox("显示散点图"):
        fig2, ax2 = plt.subplots()
        ax2.scatter(data["Column1"], data["Column2"])
        ax2.set_title("Column1 与 Column2 的关系")
        ax2.set_xlabel("Column1")
        ax2.set_ylabel("Column2")
        st.pyplot(fig2)

运行效果:

3.2. 模拟数据监控与报告

在这个数据监控与报告应用示例中,通过get_live_data 函数模拟获取实时数据(实际应用中可替换为真实的数据获取逻辑)。

然后通过一个循环,不断获取新数据并合并到总的数据集中,再使用 Matplotlib 绘制折线图展示数据随时间的变化趋势。

这样就构建了一个简单的实时数据监控应用,在实际业务场景中,例如监控服务器性能指标、生产线上的关键数据等,可以让相关人员实时直观地了解数据的变化情况,及时发现异常并做出决策。

import streamlit as st
import matplotlib.pyplot as plt
import time
import random
import pandas as pd

import matplotlib

# 为了显示中文
matplotlib.rcParams["font.sans-serif"] = ["Microsoft YaHei Mono"]
matplotlib.rcParams["axes.unicode_minus"] = False


# 模拟获取实时数据的函数
def get_live_data():
    # 这里可以替换为真实的获取数据逻辑,比如从数据库或 API 获取
    new_data = pd.DataFrame(
        {
            "time": [time.strftime("%H:%M:%S")],
            "value": [random.randint(-10, 10)],
        }
    )
    return new_data


# 初始化数据
data = pd.DataFrame(columns=["time", "value"])

# 实时数据监控应用标题
st.title("实时数据监控")

# 创建一个占位符用于更新图表
chart_placeholder = st.empty()

while True:
    # 获取新数据
    new_data = get_live_data()
    # 合并新数据到总数据
    data = pd.concat([data, new_data], ignore_index=True)

    # 使用 Matplotlib 绘制折线图
    fig, ax = plt.subplots()
    ax.plot(data["time"], data["value"])
    ax.set_title("实时数据趋势")
    ax.set_xlabel("时间")
    ax.set_ylabel("数值")
    ax.set_xticklabels(data["time"], rotation=45)

    # 在 Streamlit 中更新图表
    chart_placeholder.pyplot(fig)

    # 每隔一段时间更新数据(这里设置为 2 秒)
    time.sleep(2)

运行效果:

4. 总结

StreamlitMatplotlib 结合的关键点在于,Streamlit 提供便捷的应用构建框架,Matplotlib 专注强大的绘图功能,二者通过 st.pyplot 函数紧密相连。

在数据处理流程上,可先在 Matplotlib 中依据数据特性灵活创建各类图形对象,再借助 Streamlit 整合进应用。

它们结合的优势也非常明显,首先,在可视化效率方面,能快速将 Matplotlib 绘制的图形嵌入 Streamlit 应用,减少开发时间与代码量。

其次,在交互性上,Streamlit 的丰富交互组件可与 Matplotlib 图形联动,如通过按钮、滑块等控制图形展示内容或范围,让用户更方便的进行数据探索。

posted @ 2024-12-17 22:03  wang_yb  阅读(128)  评论(0编辑  收藏  举报