数据分析可视化神器---streamlit框架,各种图表绘制,布局以及生产综合案例剖析

简介: 数据分析可视化神器---streamlit框架,各种图表绘制,布局以及生产综合案例剖析

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

大家好,我是景天,上一篇我们讲到了数据分析可视化框架streamlit的基本介绍,安装,常规用法等等,相信大家对它的使用有了一定的了解,没印象的同学可以翻看下本专栏上一章 数据分析web可视化神器—streamlit框架,无需懂前端也能搭建出精美的web网站页面

本章我们进一步探讨streamlit的一些高阶用法,喜欢的朋友点赞收藏关注不迷路哦

1.图例显示

环境安装:

pip install streamlit-echarts

1.折线图

from pyecharts.charts import Line
from pyecharts import options as opts
from streamlit_echarts import st_pyecharts

# 示例数据
cate = ['Apple', 'Huawei', 'Xiaomi', 'Oppo', 'Vivo', 'Meizu']
data1 = [123, 153, 89, 107, 98, 23]
data2 = [56, 77, 93, 68, 45, 67]
#画图,画折线图
line = (Line()
       .add_xaxis(cate)
       .add_yaxis('电商渠道', data1,
                  #均值标记线
                  markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(type_="average")]))
       .add_yaxis('门店', data2,
                  markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(type_="average")])
                 )
       .set_global_opts(title_opts=opts.TitleOpts(title="Line-基本示例", subtitle="我是副标题"))
      )
#渲染到页面中
st_pyecharts(line)

2.柱状图

from pyecharts import options as opts
from pyecharts.charts import Bar
from streamlit_echarts import st_pyecharts

b = (
    Bar()
        .add_xaxis(["Microsoft", "Amazon", "IBM", "Oracle", "Google", "Alibaba"])
        .add_yaxis(
        "2017-2018 Revenue in (billion $)", [21.2, 20.4, 10.3, 6.08, 4, 2.2]
    ).set_global_opts(
        title_opts=opts.TitleOpts(
            title="Top cloud providers 2018", subtitle="2017-2018 Revenue"
        ),#工具栏,可以切换图表样式--折线图,柱状图....等切换
        toolbox_opts=opts.ToolboxOpts(),
    )
)
st_pyecharts(b)

3.直方图

np.histogram是NumPy库中的一个函数,用于计算给定数据的直方图。

直方图是一种统计图表,用于表示数据的分布情况。它将数据划分为多个离散的区间(称为“bin”),

并计算每个区间中数据点的频率。

直方图的 x 轴表示数据的取值范围,y 轴表示该取值范围内数据点的数量或频率。

from streamlit_echarts import st_pyecharts
from pyecharts.charts import Bar
from pyecharts import options as opts
import numpy as np
import pandas as pd

s = pd.Series(data=np.random.randint(0,10,size=(50)))

#返回值有两个,分别是频率和区间
y,x = np.histogram(s,bins=5)

x = x.tolist()
y = y.tolist()
x,y
c = (
    Bar()
    .add_xaxis(x)
    .add_yaxis("频数", y,
               category_gap=3, # 设置柱子之间的间距为3
               color='#ff8080')
    .set_global_opts(title_opts=opts.TitleOpts(title="Bar-直方图"))
)


st_pyecharts(c)

4.散点图

from streamlit_echarts import st_pyecharts
from pyecharts.charts import Scatter
from pyecharts import options as opts
import numpy as np

# 示例数据
x = np.random.randint(0,50,size=(20,)).tolist()
y = np.random.randint(0,50,size=(20,)).tolist()


#sort_控制排序,默认降序;
#label_opts标签显示位置
scatter = (Scatter()
          .add_xaxis(x)
          .add_yaxis('散点图', y)
          .set_global_opts(title_opts=opts.TitleOpts(title="Scatter-基本示例", subtitle="我是副标题"))
         )


st_pyecharts(scatter)

5.饼状图

from streamlit_echarts import st_pyecharts
from pyecharts.charts import Pie
from pyecharts import options as opts

# 示例数据
cate = ['Apple', 'Huawei', 'Xiaomi', 'Oppo', 'Vivo', 'Meizu']
data = [153, 124, 107, 99, 89, 46]

pie = (Pie()
       .add('i am bobo', [list(z) for z in zip(cate, data)],
            radius=["30%", "75%"], #设置半径(内外圈半径)
            rosetype="radius" #半径形式的玫瑰型样式(经典)
           )
       .set_global_opts(title_opts=opts.TitleOpts(title="Pie-基本示例", subtitle="我是副标题"))
       .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {d}%"))
      )

st_pyecharts(pie)

6.漏斗图

from streamlit_echarts import st_pyecharts
from pyecharts.charts import Funnel
from pyecharts import options as opts

# 示例数据
cate = ['访问', '注册', '加入购物车', '提交订单', '付款成功']
data = [30398, 15230, 10045, 8109, 5698]
#要想显示转化率需要手动计算存储到data列表中

#sort_控制排序,默认降序;
#label_opts标签显示位置
funnel = (Funnel()
          .add("用户数", [list(z) for z in zip(cate, data)],
               sort_='ascending',
               label_opts=opts.LabelOpts(position="inside"),
              )
          .set_global_opts(title_opts=opts.TitleOpts(title="Funnel-基本示例", subtitle="我是副标题"))
         )

st_pyecharts(funnel)

7.地图

import pandas as pd
import streamlit as st
import numpy as np

map_data = pd.DataFrame(
    np.random.randn(1000, 2) / [50,50] + [37.76,-122.4],
    columns=['lat', 'lon']
)
#注意:map的数据集中必须要有lat和lon固定列名的两列数据作为经纬度
st.map(map_data)

2.布局

1.st.sidebar - 在侧边栏增添交互元素

import streamlit as st

# 方式1:使用对象表示法添加选择框
add_selectbox = st.sidebar.selectbox(
    "您希望如何联系您?",
    ("电子邮件", "家庭电话", "移动电话")
)
# 方式2:使用“with”语法添加单选按钮
with st.sidebar:
    add_radio = st.radio(
        "选择一种运输方式",
        ("标准(5-15天)", "快递(2-5天)")
    )

2.st.columns - 并排布局多元素容器

通过调用 st.columns,您可以插入多个多元素容器,并将它们布局为并排的形式。返回的是一个容器对象的列表,每个对象都可以用来添加元素。

您可以选择使用“with”语法(更推荐)或者直接在容器对象上调用方法来添加元素。

import streamlit as st

col1, col2, col3 = st.columns(3)

with col1:
   st.header("一只猫")
   st.image("https://static.streamlit.io/examples/cat.jpg")   #也可以显示视频文件

with col2:
   st.header("一只狗")
   st.image("https://static.streamlit.io/examples/dog.jpg")

with col3:
   st.header("一只猫头鹰")
   st.image("https://static.streamlit.io/examples/owl.jpg")

或者您也可以直接在容器对象上调用方法:

import streamlit as st
import numpy as np

col1, col2 = st.columns([3, 1])
data = np.random.randn(10, 1)

col1.subheader("一个宽容器,含有图表")
col1.line_chart(data)

col2.subheader("一个窄容器,含有数据")
col2.write(data)

3.st.tabs - 以选项卡形式布局多元素容器

通过调用 st.tabs,您可以插入多个多元素容器作为选项卡。每个选项卡都代表一组相关内容。返回的是一个容器对象的列表,每个对象都可以用来添加元素。与之前一样,您可以选择使用“with”语法或者直接在容器对象上调用方法来添加元素。

需要注意的是,每个选项卡的所有内容都会被一次性发送并渲染在前端。

import streamlit as st

tab1, tab2, tab3 = st.tabs(["猫", "狗", "猫头鹰"])

with tab1:
   st.header("一只猫")
   st.image("https://static.streamlit.io/examples/cat.jpg", width=200)

with tab2:
   st.header("一只狗")
   st.image("https://static.streamlit.io/examples/dog.jpg", width=200)

with tab3:
   st.header("一只猫头鹰")
   st.image("https://static.streamlit.io/examples/owl.jpg", width=200)

或者您也可以直接在容器对象上调用方法:

import streamlit as st
import numpy as np

tab1, tab2 = st.tabs(["📈 图表", "🗃 数据"])
data = np.random.randn(10, 1)

tab1.subheader("一个带有图表的选项卡")
tab1.line_chart(data)

tab2.subheader("一个带有数据的选项卡")
tab2.write(data)

4.st.expander - 可展开/折叠的多元素容器

调用 st.expander,您可以插入一个可展开或折叠的容器,用于包含多个元素。容器的初始状态是折叠的,只显示提供的标签。用户可以点击标签来展开容器,查看其中的内容。

import streamlit as st

st.bar_chart({"data": [1, 5, 2, 6, 2, 1]})

with st.expander("查看说明"):
    st.write("""
        上面的图表展示了我为您选择的一些数字。
        这些数字是通过真实的骰子摇出来的,所以它们*保证*是随机的。
    """)
    st.image("https://static.streamlit.io/examples/dice.jpg")

点击展开

或者您也可以直接在容器对象上调用方法:

import streamlit as st

st.bar_chart({"data": [1, 5, 2, 6, 2, 1]})

expander = st.expander("查看说明")
expander.write("""
    上面的图表展示了我为您选择的一些数字。
    这些数字是通过真实的骰子摇出来的,所以它们*保证*是随机的。
""")
expander.image("https://static.streamlit.io/examples/dice.jpg")

3.实战案例

1.抓取拉勾网招聘岗位数据,并分析展示

注意,运行前需要从网站拿到最新的cookie

完整代码:

import pandas as pd
import streamlit as st
import pandas as pt
import requests
from pyecharts.charts import Line
from pyecharts import options as opts
from streamlit_echarts import st_pyecharts
from pyecharts.charts import Bar
from pyecharts.charts import Pie
from lxml import etree
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0',
    'Cookie':'index_location_city=%E5%85%A8%E5%9B%BD; RECOMMEND_TIP=true; user_trace_token=20231228155703-c428ac53-3dce-4d36-ad4f-f05fefe8ca85; LGUID=20231228155703-bda9a438-ca0b-4cda-b10a-3a0b71bc38d8; _ga=GA1.2.2030589830.1703750224; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1703750224; X_HTTP_TOKEN=1f6c74284fa5532a0363573071dfaca58ed0547982; JSESSIONID=ABAABJAABGBABEB1242F78FD52E6AFAF225BE4AEF12E1D9; WEBTJ-ID=20240313095127-18e3581e05c5b7-005c92cce50259-4c657b58-2073600-18e3581e05d13a9; sensorsdata2015session=%7B%7D; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2218cae00e03e16e3-0cea6da040cc57-26031051-2073600-18cae00e03f24e8%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24os%22%3A%22Windows%22%2C%22%24browser%22%3A%22Chrome%22%2C%22%24browser_version%22%3A%22122.0.0.0%22%7D%2C%22%24device_id%22%3A%2218cae00e03e16e3-0cea6da040cc57-26031051-2073600-18cae00e03f24e8%22%7D'
}
#按钮点击事件-数据爬取+保存
def get_job_msg():
    fp = open('./job_msg.csv', 'a',encoding='utf-8')
    for page in range(2,5):
        url = f'https://www.lagou.com/wn/zhaopin?fromSearch=true&kd=%25E6%2595%25B0%25E6%258D%25AE%25E5%2588%2586%25E6%259E%2590%25E5%25B8%2588&labelWords=sug&suginput=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&pn={page}'
        page_text = requests.get(url, headers=headers).text
        tree = etree.HTML(page_text)
        div_list = tree.xpath('//*[@id="jobList"]/div[1]/div')
        for div in div_list:
            job_title_area = div.xpath('./div[1]/div[1]/div[1]/a//text()')
            salary_degree = div.xpath('./div[1]/div[1]/div[2]//text()')
            #岗位名称
            job_title = job_title_area[0]
            # 地区area
            area = job_title_area[1]
            #薪资
            salary = salary_degree[0]
            #学历degree
            degree = div.xpath('./div[1]/div[1]//div[@class="p-bom__JlNur"]/text()')[0]
            #公司名称company_title
            company_title = div.xpath('./div[1]/div[2]/div[1]/a/text()')[0]
            #公司信息company_msg
            company_msg = div.xpath('./div[1]/div[2]/div[2]/text()')
            if company_msg:
                company_msg = company_msg[0]
            else:
                company_msg = "暂无信息"
            #公司福利company_welfare
            company_welfare =  div.xpath('./div[2]/div[2]/text()')[0]
            #岗位要求job_require
            job_require = div.xpath('./div[2]/div[1]/span/text()')
            if job_require:
                job_require = job_require[0]
            else:
                job_require = "暂无信息"
            fp.write(job_title+'#'+salary+'#'+area+'#'+degree+'#'+company_title+'#'+company_msg+'#'+company_welfare+'#'+job_require+'\n')
    fp.close()
    st.write('数据抓取结束')

#按钮点击事件-数据展示
def load_show():
    df = pd.read_csv('./job_msg.csv',sep='#',
                     names=['岗位名称','薪资','地区','学历/经验要求','公司名称','公司信息','福利','岗位要求'],encoding='utf-8')
    return df

if __name__ == '__main__':
    #侧边栏布局
    st.sidebar.text('数据爬取+存储:')
    #数据爬取+保存
    isClick_btn1 = st.sidebar.button(label='开始吧')
    if isClick_btn1:
        get_job_msg()

    st.sidebar.text('数据加载+展示:')
    #数据加载+展示
    isClick_btn2 = st.sidebar.button(label='一键启动')
    if isClick_btn2:
        df = load_show()
        # 折叠展示数据表格
        with st.expander("岗位信息", expanded=True):
            st.write(df)

    #侧边栏下拉框
    add_selectbox = st.sidebar.selectbox(
        label="数据分析:",
        options=('请选择','不同城市岗位数量&平均薪资','不同经验的岗位占比','不同学历的岗位数量')
    )
    #获取下拉选项
    if add_selectbox == '不同城市岗位数量&平均薪资':
        table = load_show()
        def get_city_name(x):
            return x.split('·')[0].split('[')[1]
        table['city'] = table['地区'].map(get_city_name)
        #不同城市岗位数量
        city_job_count_s = table.groupby(by='city').size().sort_values(ascending=False)

        #不同城市平均薪资
        # 求出salary每个元素表示薪资范围的均值:7k-10k
        ret = table['薪资'].str.extract(r'(\d+)k-(\d+)k')
        # 注意:正则返回结果为字符串类型,将其转成数字类型
        ret = ret.astype('int')
        table['mean_sal'] = ret.apply(lambda s:s.mean(), axis=1)
        table['mean_sal'] = table['mean_sal']
        mean_sal_city = table.groupby(by='city')['mean_sal'].mean().sort_values(ascending=False)
        mean_sal_city = mean_sal_city.map(lambda x:format(x,'.2f'))
        #绘制柱状图
        b = (
            Bar()
                .add_xaxis(city_job_count_s.index.tolist())
                .add_yaxis(
                "岗位数量", city_job_count_s.values.tolist())
                .add_yaxis(
                "平均薪资", mean_sal_city.values.tolist())
                .set_global_opts(
                    title_opts=opts.TitleOpts(
                        title="岗位分析", subtitle="不同城市的岗位数量&平均薪资"
                    ),  # 工具栏
                    toolbox_opts=opts.ToolboxOpts(),
            )
        )
        st_pyecharts(b)

    if add_selectbox == '不同经验的岗位占比':
        table = load_show()
        #学历
        table["degree"] = table['学历/经验要求'].str.extract('(.*)/(.*)')[0]
        ret = table.groupby(by='degree').size()
        #饼图
        cate = ret.index.tolist()
        data = ret.values.tolist()
        pie = (Pie()
               .add('i am bobo', [list(z) for z in zip(cate, data)],
                    radius=["30%", "75%"],  # 设置半径(内外圈半径)
                    rosetype="radius"  # 半径形式的玫瑰型样式(经典)
                    )
               .set_global_opts(title_opts=opts.TitleOpts(title="数据分析", subtitle="经验占比"))
               .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {d}%"))
               )

        st_pyecharts(pie)

    if add_selectbox == '不同学历的岗位数量':
        st.write('兄弟们,自己玩起来吧!')

展示效果:

点开始吧,开始抓取数据,并保存到本地csv文件

点击一键启动,就会展示抓取的表格数据

点击下拉框选择展示不同数据

2. 从本地表格读取数据,并进行可视化展示

先看下原数据表

实战代码:

import pandas as pd

import streamlit as st
from pyecharts.charts import Pie,Scatter,Funnel,Page,Line,Bar
from pyecharts import options as opts
from streamlit_echarts import st_pyecharts

# st.set_page_config(layout='wide')

#装饰器,做数据缓存的,如果数据量比较大,不用每次都要重新加载,而是在数据第一次加载时,将数据保存到缓存中,下次直接使用
@st.cache_data
def load_data():
    data = pd.read_excel('Phone.xlsx')
    #缺失值处理
    data['年'] = data['订单日期'].dt.year
    data['月'] = data['订单日期'].dt.month
    #数据分箱:
    data['年龄段'] = pd.cut(data['年龄'],bins=[16,30,40,50],labels=['16-30','30-40','40-50'],right=False)
    #手机号脱敏处理
    def func(x):
        return str(x).replace(str(x)[3:7],'****')
    data['手机号'] = data['手机号'].map(func)
    return data


data = load_data() #加载数据
#侧边栏布局年份选择
with st.sidebar:
    # 不同年份
    years = data['年'].unique().tolist()
    #下拉选中的年份值
    select_value = st.selectbox(label='请选择年份',options=years)
    #计算对应年份的总销量和总销售额
    year_data = data.loc[data['年']==select_value]
    #总销售额
    year_total_amount = year_data['销售额'].sum()
    st.markdown('### 总销售额 : '+str(year_total_amount))
    #总销量
    year_total_product = year_data['数量'].sum()
    st.markdown('### 总共销量 : ' + str(year_total_product))
    #总订单数
    year_total_count = year_data.shape[0]
    st.markdown('### 总订单量 : ' + str(year_total_count))

st.subheader('销量相关数据展示')
#月份和销售额
month_data = year_data.groupby(by='月')['数量'].sum()
indexs = month_data.index.tolist()
values = month_data.values.tolist()
#画图
line = (Line()
       .add_xaxis(indexs)
       .add_yaxis('不同月份销量', values)
       .set_global_opts(title_opts=opts.TitleOpts('不同月份销量'))
      )
#渲染到页面中
st_pyecharts(line,height=400)


#不同品牌与销量
good_data = year_data.groupby(by='品牌')['数量'].sum()
indexs = good_data.index.tolist()
values = good_data.values.tolist()
b = (
    Bar()
        .add_xaxis(indexs)
        .add_yaxis(
        "销量:", values
    ).set_global_opts(
        title_opts=opts.TitleOpts(
            title="不同品牌的销量"
        )
    )
)
st_pyecharts(b)

#年龄段和销售额
age_data = year_data.groupby(by='年龄段')['数量'].sum()
indexs = age_data.index.tolist()
values = age_data.values.tolist()
pie = (Pie()
       .add('销量', [list(item) for item in zip(indexs,values)],
            radius=["40%", "60%"], #设置半径(内外圈半径)
            rosetype="radius", #半径形式的玫瑰型样式(经典)
            label_opts=opts.LabelOpts(is_show=False, position="center")
           )
       .set_global_opts(title_opts=opts.TitleOpts(title="不同年龄段销量"))
       .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {d}%"))

      )
st_pyecharts(pie)

可以选取不同年份展示


相关文章
|
14天前
|
数据采集 编解码 数据可视化
空间单细胞|10x Visium数据分析、可视化与整合(1)
空间单细胞|10x Visium数据分析、可视化与整合(1)
35 1
|
8天前
|
编解码 数据可视化 算法
空间单细胞|10x Visium数据分析、可视化与整合(2)
空间单细胞|10x Visium数据分析、可视化与整合(2)
8 0
|
15天前
|
数据采集 机器学习/深度学习 数据可视化
了解数据科学面试中的Python数据分析重点,包括Pandas(DataFrame)、NumPy(ndarray)和Matplotlib(图表绘制)。
【7月更文挑战第5天】了解数据科学面试中的Python数据分析重点,包括Pandas(DataFrame)、NumPy(ndarray)和Matplotlib(图表绘制)。数据预处理涉及缺失值(dropna(), fillna())和异常值处理。使用describe()进行统计分析,通过Matplotlib和Seaborn绘图。回归和分类分析用到Scikit-learn,如LinearRegression和RandomForestClassifier。
31 3
|
15天前
|
数据采集 机器学习/深度学习 数据可视化
关于Python数据分析项目的简要概述:从CSV加载数据,执行数据预处理,进行数据探索,选择线性回归模型进行训练,评估模型性能并优化,最后结果解释与可视化。
【7月更文挑战第5天】这是一个关于Python数据分析项目的简要概述:从CSV加载数据,执行数据预处理(填充缺失值,处理异常值),进行数据探索(可视化和统计分析),选择线性回归模型进行训练,评估模型性能并优化,最后结果解释与可视化。此案例展示了数据科学的典型流程。
34 2
|
15天前
|
数据采集 机器学习/深度学习 数据可视化
完整的Python数据分析流程案例解析-数据科学项目实战
【7月更文挑战第5天】这是一个Python数据分析项目的概览,涵盖了从CSV数据加载到模型评估的步骤:获取数据、预处理(处理缺失值和异常值、转换数据)、数据探索(可视化和统计分析)、模型选择(线性回归)、训练与评估、优化,以及结果的可视化和解释。此流程展示了理论与实践的结合在解决实际问题中的应用。
35 1
|
20天前
|
存储 数据可视化 Java
使用Java实现可视化数据分析平台
使用Java实现可视化数据分析平台
|
15天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的豆瓣电影数据分析可视化系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的豆瓣电影数据分析可视化系统附带文章源码部署视频讲解等
13 0
|
25天前
|
数据采集 Web App开发 数据可视化
程序员必知:对厦门二手房的数据分析与可视化分析
程序员必知:对厦门二手房的数据分析与可视化分析
26 0
|
1天前
|
数据采集 机器学习/深度学习 数据挖掘
转换数据,扭转乾坤!Python转换技巧,让你的数据分析如虎添翼!
【7月更文挑战第19天】Python在数据转换中扮演关键角色,借助Pandas库进行数据清洗,如填充缺失值、处理异常值和转换数据类型。数据重塑通过pivot、melt和groupby提供多维度视图。文本数据通过独热编码或标签编码转化为数值。自定义函数解决复杂转换问题,提升数据分析的深度和准确性。掌握这些技巧,能有效挖掘数据价值,助力决策。
16 4
|
11天前
|
机器学习/深度学习 监控 算法
Python数据分析与机器学习在金融风控中的应用
Python数据分析与机器学习在金融风控中的应用
39 12