前言
在数据驱动的时代,数据看板(Dashboard)已成为企业监控运营、分析业务的核心工具。本文带你用 Python 最快的方式——Streamlit + Pandas + Plotly,从零搭建一个电商销售数据看板,包含数据卡片、柱状图、饼图、折线图、明细表、筛选联动、预警提示等完整功能。
技术栈:
Python 3.13
Streamlit(Web 框架)
Pandas(数据处理)
Plotly(可视化)
PyCharm Community Edition
最终效果:一个可在浏览器访问、支持筛选联动、带动画交互的实时数据看板。
一、环境准备
bash
复制
下载
pip install streamlit pandas plotly openpyxl numpy
💡 国内网络建议加镜像:
pip install ... -i https://pypi.tuna.tsinghua.edu.cn/simple
项目结构:
text
复制
下载
PythonProject/ ├── data/ │ └── sales_data.csv ├── app.py ├── generate_data.py └── requirements.txt
二、数据生成与预处理
使用 NumPy 模拟生成 500 条电商订单数据,包含订单号、日期、品类、单价、数量、金额等字段。
python
复制
下载
import pandas as pd import numpy as np from datetime import datetime, timedelta np.random.seed(42) categories = ['电子产品', '服装', '食品', '家居', '图书'] records = [] start_date = datetime(2024, 1, 1) for i in range(500): date = start_date + timedelta(days=np.random.randint(0, 365)) cat = np.random.choice(categories) price = round(np.random.uniform(20, 2000), 2) qty = np.random.randint(1, 20) records.append({ 'order_id': f'ORD{i+1:04d}', 'date': date.strftime('%Y-%m-%d'), 'category': cat, 'price': price, 'quantity': qty, 'amount': round(price * qty, 2) }) df = pd.DataFrame(records) # 预处理 df.dropna(inplace=True) df = df[df['amount'] > 0] df['month'] = pd.to_datetime(df['date']).dt.strftime('%Y-%m') df.to_csv('data/sales_data.csv', index=False, encoding='utf-8-sig') print(f'✅ 数据生成完成,共 {len(df)} 条记录')关键点:
| 问题 | 原因 | 解决 |
|---|---|---|
| Streamlit 首次运行卡在 Email | 误以为是输入网址 | 直接回车跳过 |
| CSV 中文乱码 | Windows 默认 GBK | 保存时用utf-8-sig |
| 月度排序错乱 | 字符串排序 | 用datetime类型 |
| 修改代码不生效 | 未刷新 | 按R或点击 Rerun |
| 端口被占用 | 8501 已用 | --server.port 8502 |
八、总结与展望
通过本项目,用不到150 行代码就完成了一个功能完整的数据看板,涵盖了数据可视化的大部分核心要素。Streamlit 极大降低了 Web 看板的开发门槛,配合 Plotly 的交互能力,非常适合做数据分析原型、课程作业、甚至小型业务监控系统。
未来可以扩展:
六、进阶功能
1. 筛选联动
侧边栏多选品类,全部图表自动同步更新——只需一行df = df[df['category'].isin(selected_cats)]。
2. 数据预警
python
复制
下载
if growth < 0: st.error(f"⚠️ 环比增长率为负:{growth:.2f}%")3. 数值滚动动画
Streamlit 的st.metric自带数值变化动画,无需额外配置。
4. 图表悬浮提示
Plotly 图表默认支持 hover 悬浮提示,鼠标移到柱状图/折线图上即显示具体数值。
七、踩坑记录
utf-8-sig编码,避免中文乱码剔除空值和金额≤0 的异常数据
派生
month字段,便于月度聚合三、看板主程序
将以下代码保存为
app.py:python
复制
下载
import streamlit as st import pandas as pd import plotly.express as px # 页面配置 st.set_page_config( page_title="电商销售数据看板", page_icon="📊", layout="wide" ) # 自定义样式 st.markdown(""" <style> .main { background-color: #f5f7fa; } h1 { color: #1f77b4; text-align: center; } </style> """, unsafe_allow_html=True) # 加载数据(带缓存) @st.cache_data def load_data(): df = pd.read_csv('data/sales_data.csv') df['date'] = pd.to_datetime(df['date']) return df df = load_data() # 侧边栏筛选 st.sidebar.header("🔍 筛选条件") selected_cats = st.sidebar.multiselect( "选择品类", options=df['category'].unique(), default=df['category'].unique() ) df = df[df['category'].isin(selected_cats)] # 标题 st.markdown("<h1>📊 电商销售数据看板</h1>", unsafe_allow_html=True) st.markdown("---") # 数据概览区 total_amount = df['amount'].sum() total_orders = len(df) avg_price = df['amount'].mean() monthly = df.groupby('month')['amount'].sum().sort_index() growth = 0 if len(monthly) >= 2: growth = (monthly.iloc[-1] - monthly.iloc[-2]) / monthly.iloc[-2] * 100 col1, col2, col3, col4 = st.columns(4) col1.metric("💰 总销售额", f"¥{total_amount:,.0f}") col2.metric("📦 总订单数", f"{total_orders:,}") col3.metric("💵 平均单价", f"¥{avg_price:,.2f}") col4.metric("📈 环比增长率", f"{growth:.2f}%") if growth < 0: st.error(f"⚠️ 警告:环比增长率下降 {growth:.2f}%") else: st.success(f"✅ 环比增长率 {growth:.2f}%,表现良好") st.markdown("---") # 维度统计 + 占比结构 col_left, col_right = st.columns(2) with col_left: st.subheader("📊 各品类销售额对比") cat_data = df.groupby('category')['amount'].sum().reset_index() fig_bar = px.bar( cat_data, x='category', y='amount', color='category', color_discrete_sequence=px.colors.qualitative.Set2, labels={'category': '品类', 'amount': '销售额(元)'} ) fig_bar.update_layout(showlegend=False, height=380) st.plotly_chart(fig_bar, use_container_width=True) with col_right: st.subheader("🥧 各品类销售占比") fig_pie = px.pie( cat_data, names='category', values='amount', hole=0.4, color_discrete_sequence=px.colors.qualitative.Set3 ) fig_pie.update_layout(height=380) st.plotly_chart(fig_pie, use_container_width=True) st.markdown("---") # 趋势分析区 st.subheader("📈 月度销售趋势") monthly_df = df.groupby('month')['amount'].sum().reset_index() fig_line = px.line( monthly_df, x='month', y='amount', markers=True, labels={'month': '月份', 'amount': '销售额(元)'} ) fig_line.update_traces(line_color='#1f77b4', line_width=3) fig_line.update_layout(height=350) st.plotly_chart(fig_line, use_container_width=True) st.markdown("---") # 明细数据区 st.subheader("📋 订单明细数据") st.dataframe( df[['order_id', 'date', 'category', 'price', 'quantity', 'amount']] .sort_values('date', ascending=False) .head(50), use_container_width=True, height=300 )四、启动看板
bash
复制
下载
streamlit run app.py
浏览器自动打开
http://localhost:8501,即可看到完整看板。⚠️ 首次运行会提示输入邮箱,直接按回车跳过即可。
五、效果展示
看板包含:
✅ 一行 4 个数据卡片(总销售额、订单数、平均单价、环比增长率)
✅ 红/绿预警提示条
✅ 左侧柱状图(品类对比) + 右侧环形图(品类占比)
✅ 中部月度折线图
✅ 底部订单明细表(Top50)
✅ 左侧筛选器联动所有图表
对接 MySQL / API 实现实时刷新
加入地图、热力图、雷达图等高级图表
支持暗色主题切换
移动端自适应
一键导出 PDF 报告