python-streamlit|生成多種圖表

記錄用生產多種形式圖表格式,併發送到streamlit

注意:pyecahrts發送到streamlit需要用到streamlit_echarts

1.一般pyecharts可以直接發送到streamlit,  

    比如:ste.st_pyecharts(pie1)

2.靜態html發送到streamlit需要用到streamlit.components.v1

  比如:fin_barHtml=fin_bar.render_embed()

            components.html(fin_barHtml,height=500,width=1000)

公共數據和參數 

# -*- coding: utf-8 -*-
"""
https://blog.csdn.net/ai_ljh/article/details/130371579
https://github.com/PablocFonseca/streamlit-aggrid/issues/13
BP meeting scorecard+volume
設置sheet_name=None,會得到一個字典變量,
    key=sheet.name
    value=sheet.data
"""
import os
import pandas as pd

import streamlit as st
import streamlit_echarts as ste   #用以將pyecharts發送到strealit html頁面
import streamlit.components.v1 as components               #展示成html
from st_aggrid import AgGrid, GridOptionsBuilder           #streamlit-aggrid

from pyecharts.charts import Bar,Pie                       #pyechart圖
from pyecharts import options as opts
from pyecharts.globals import ThemeType
from pyecharts.commons.utils import JsCode

#========================main variable===============================
st.title("xxxxxxxxxxxxx")
path=r'xxxxxxxxxxxxxx'
finFile='wusi-scorecard.xlsx'
srcFIN=os.path.join(path,finFile)               #volume data source
fin_datas=load_bp_data(srcFIN)                  #dfs
fin_df1=fin_datas['wusi']                       #scorecard data
fin_df1.fillna(0,inplace=True)                  #fill missing data

volumeFile='ttttttttt.xlsx'
srcVOLUME=os.path.join(path,volumeFile)        #volume data source
volumes=load_bp_data(srcVOLUME)                #dfs
df1=volumes['wusi']
df2=volumes['premix']
df3=volumes['country']

多顏色柱狀圖

需要用到JsCode

#generate colorful bar chart
@st.cache(allow_output_mutation=True)
def df_sc_bar_chart(df):
    COLOR = """function (params) {
                 let colorList=[
                     '#37A2DA',
                     '#ca8622',
                     '#4BABDE',
                     '#d48265',
                     '#749f83',
                     '#c23531',
                     ];
                     return colorList[params.dataIndex];
                }"""
    bar=Bar(init_opts=opts.InitOpts(
        # width=600,
        # height=800,
        theme=ThemeType.LIGHT))                           #創建bar
    xData=list(df.columns)                                #x軸
    bar.add_xaxis(xData)                                  #添加x
    for i in range(len(df)):                              #循環數據列
        data=df.iloc[i,]                                  #篩選當前行數據
        yData=list(round(v,2) for v in data)              #y軸爲數值
        serName=df.index[i]                               #y軸名稱
        #添加y系列值
        bar.add_yaxis(
            series_name='Wusi '+serName+' m$',            #名稱
            y_axis=yData,stack="stack1",                  #數據
            itemstyle_opts=opts.ItemStyleOpts(color=JsCode(COLOR)),
            label_opts=opts.LabelOpts(is_show='True',
                                      position='top',     #標籤位置
                                      color='black',      #數字標籤
                                      font_size='15'      #字體大小
                                      ),
                    )
    return bar

fin_sc=fin_df1.loc[['Scorecard'],:]             #keep df format
fin_bar=df_sc_bar_chart(fin_sc)                   # bar chart
fin_barHtml=fin_bar.render_embed()                    #bar發送到變量
components.html(fin_barHtml,height=500,width=1000)   #keep the parameter

streamlit的metric

st.subheader('Wusi 2023F06 Scorecard vs Plan')
r1,r2,r3,r4,r5=st.columns(5)
with r1:
    st.metric(label="EXPENSE",value="9.55",delta="-0.77",delta_color="inverse")
with r2:
    st.metric(label="ABS",value="6.58",delta="0.47",delta_color="inverse")
with r3:
    st.metric(label="LOSS",value="0.03",delta="-0.09",delta_color="inverse")
with r4:
    st.metric(label="UYV",value="0.26",delta="0.26",delta_color="inverse")
with r5:
    st.metric(label="PPV",value="0.09",delta="-0.09",delta_color="inverse")

#--------------------absorption data information--------------------
st.subheader('Wusi 2023F06 Absorption vs Plan')
r1,r2,r3,r4=st.columns(4)
with r1:
    st.metric(label="COATING",value="4.48",delta="3%",delta_color="normal")
with r2:
    st.metric(label="AGITA",value="0.81",delta="-12%",delta_color="normal")
with r3:
    st.metric(label="PREMIX",value="1.29",delta="-27%",delta_color="normal")
with r4:
    st.metric(label="WUSI",value="6.58",delta="-7%",delta_color="normal")

一般柱狀圖和aggrid表格

#aggrid table,用以創建更靈活streamlit表格
# @st.cache(allow_output_mutation=True)
def aggrid_interactive_table(df: pd.DataFrame):
    options = GridOptionsBuilder.from_dataframe(
        df, 
        # enableRowGroup=True,
        enableValue=True,
        autoHeight=True,
        # enablePivot=True,
        wrapText=True,
        editable=True,
        )
    ag = AgGrid(
        df,
        # height=300,
        # width=900,
        enable_enterprise_modules=True,
        gridOptions=options.build(),
        fit_columns_on_grid_load=True,
        # theme="light",
        # update_mode=GridUpdateMode.MODEL_CHANGED,
        allow_unsafe_jscode=True,
    )
    return ag                                       #返回aggrid

#generate bar chart with dataframe
@st.cache(allow_output_mutation=True)
def df_generate_bar_chart(df):
    bar=Bar(init_opts=opts.InitOpts(
        # width=600,
        # height=800,
        theme=ThemeType.LIGHT))                           #創建bar
    xData=list(df.columns)                                #x軸
    bar.add_xaxis(xData)                                  #添加x
    for i in range(len(df)):                              #循環數據列
        data=df.iloc[i,]                                  #篩選當前行數據
        yData=list(data)                                  #y軸爲數值
        serName=df.index[i]                               #y軸名稱
        #添加y系列值
        bar.add_yaxis(
            series_name=serName,                           #名稱
            y_axis=yData,stack="stack1",                   #數據
            label_opts=opts.LabelOpts(is_show='True',
                                      position='inside',   #標籤位置
                                      color='black'),      #數字標籤
                    )
    return bar

st.subheader('Wusi volume(mt) by production line')
df1=df1.round(0)                                #keep as integer
#create pyecharts
bar1=df_generate_bar_chart(df1)                #chart by production.line
# ste.st_pyecharts(bar1)                        #將pycharts發送streamlit
bar1Html=bar1.render_embed()                    #bar發送到變量
components.html(bar1Html,height=500,width=1000)   #keep the parameter
#create table
df1a=df1.copy(deep=True)                            #deep copy
df1a.loc['total']=df1a.apply(lambda x:x.sum(),axis=0)    #新行,按列彙總
df1a=df1a.reset_index()          #aggrid are displayed w/o df index
# st.dataframe(df1a)                                     #show as table
agTB=aggrid_interactive_table(df=df1a)              #use aggrid table

批量生成餅圖pie

#generate pie chart
@st.cache(allow_output_mutation=True)
def my_pie_chart(sName,df):
    df1=df.loc[sName]                         #filter data
    b1=df1['COUNTRY']
    v1=df1['2023F06']
    c=(
       Pie().add(
               sName,                             #title
               [list(z) for z in zip(b1,v1)])     #data
       .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}mt ({d}%)"))
       #不顯示主圖例
       .set_global_opts(
           legend_opts = opts.LegendOpts(is_show = False),
           title_opts=opts.TitleOpts(title=sName,pos_left='center'))
           )
    return c

st.subheader('Wusi volume(mt) by destination')
pie1=my_pie_chart('COATING',df3)                  #pyecharts
pie2=my_pie_chart('AGITA',df3)
pie3=my_pie_chart('PREMIX',df3)
ste.st_pyecharts(pie1)                            #send to streamlit
ste.st_pyecharts(pie2)
ste.st_pyecharts(pie3)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章