jeudi 2 mars 2023

streamlit plot Python

I have a code that reads data and produces 4 plots, using the sidebar, the user can select which plot to display, up to 4, if none is selected, the page is clear, each plot has its own position, 4 corners, here is part of the plot that shows the case with the data needed:

import pandas as pd
import streamlit as st
import plotly.express as px
import streamlit as st

data = [['No','Time','Source','Destination','Protocol','Length'],
        ['1','26-02-23 12:17','192.168.0.105','192.168.0.1','TCP','66'],
        ['2','26-02-23 12:17','52.98.228.210','192.168.0.105','TLSv1.2','1151'],
        ['3','26-02-23 12:17','52.98.228.210','192.168.0.105','TCP','1514'],
        ['4','26-02-23 12:17','52.98.228.210','192.168.0.105','TLSv1.2','72'],
        ['5','26-02-23 12:17','192.168.0.105','52.98.228.210','TCP','54'],
        ['6','26-02-23 12:17','52.98.228.210','192.168.0.105','TLSv1.2','88'],
        ['7','26-02-23 12:17','192.168.0.105','52.98.228.210','TCP','54'],
        ['8','26-02-23 12:17','192.168.0.105','52.98.228.210','TCP','54'],
        ['9','26-02-23 12:17','192.168.0.105','239.255.255.250','UDP','698'],
        ['10','26-02-23 12:17','192.168.0.104','239.255.255.250','UDP','698'],
        ['11','26-02-23 12:17','192.168.0.105','192.168.0.1','TCP','66'],
        ['12','26-02-23 12:17','192.168.0.1','224.0.0.251','IGMPv2','60'],
        ['13','26-02-23 12:17','192.168.0.105','224.0.0.22','IGMPv3','54'],
        ['14','26-02-23 12:17','192.168.0.104','224.0.0.22','IGMPv3','60'],
        ['15','26-02-23 12:17','192.168.0.100','224.0.0.251','IGMPv2','60'],
        ['16','26-02-23 12:17','192.168.0.101','224.0.0.251','IGMPv2','60'],
        ['17','26-02-23 12:17','192.168.0.105','128.75.237.113','TCP','66'],
        ['18','26-02-23 12:17','128.75.237.113','192.168.0.105','TCP','66'],
        ['19','26-02-23 12:17','192.168.0.105','128.75.237.113','TCP','54'],
        ['20','26-02-23 12:17','192.168.0.105','128.75.237.113','HTTP','178']]


df = pd.DataFrame(data[1:],columns=data[0])

 #Setting page header
st.header('Network Monitoring Charts')

# Ploting top 10 Inbound traffic IP addresses
#st.header('Top 10 Inbound traffic IP addresses')
inbound_ip_count = df.groupby('Source').size().nlargest(n=10)
top_in_IP = px.bar(df['Source'],
                   x=inbound_ip_count.index, y= inbound_ip_count.values,
                   title='Top 10 incoming traffic IP addresses')

# Ploting top 10 Outbound traffic IP addresses
#st.header('Top 10 Onbound traffic IP addresses')
outbound_ip_count = df.groupby('Destination').size().nlargest(n=10)
top_out_IP = px.bar(df['Destination'],
                   x=outbound_ip_count.index, y=outbound_ip_count.values,
                   title='Top 10 Outbound traffic IP addresses')

# Ploting top 10 traffic ports
#st.header('Top 10 traffic ports')
port_count = df.groupby('Protocol').size().nlargest(n=10)
top_ports = px.bar(df['Protocol'],
                   x=port_count.index, y=port_count.values,
                   title='Top 10 Active Ports')

# Ploting top 5 inbound IP addresses and their top active ports
# Group by Source and Protocol, count the occurrences, and sort by count in descending order
sources_grp = df.groupby(['Source', 'Protocol'], as_index=False)['Destination']\
    .count().sort_values('Destination', ascending=False)

# Get the top 5 occurrences of Source
top_sources = df['Source'].value_counts()[:5].index.tolist()

# Filter the dataframe to only include the top 5 occurrences of Source
top_sources_df = sources_grp[sources_grp['Source'].isin(top_sources)]\
    .reset_index(drop=True)

# Rename the count column to 'Protocol Count'
top_sources_df = top_sources_df.rename(columns={'Destination': 'Protocol Count'})

# Get the top 5 occurrences of Protocol within the top sources
top_protocols = top_sources_df['Protocol'].value_counts()[:5].index.tolist()

# Filter the dataframe to only include the top 5 occurrences of Protocol
top_protocols_df = top_sources_df[top_sources_df['Protocol']\
                   .isin(top_protocols)].reset_index(drop=True)

# plot the long (tidy) dataframe
combo = px.bar(top_protocols_df, x="Source", y="Protocol Count",
               color="Protocol",\
               title="Top 5 inbound IP addresses and their top active Ports",\
               barmode='group')
combo.update_layout(xaxis_title='IP Addresses', yaxis=dict(tickformat=\
               "Protocol Count",))

#reports = ['Top Inbound IP Addresses', 'Top Outbound IP Addresses',\
#'Top Active Ports', 'Top Active IP-Ports']

st.sidebar.header('Please select your report to display')
# Diagrams selection - Sidebar
check1 = st.sidebar.checkbox('Top Inbound IP Addresses')
check2 = st.sidebar.checkbox('Top Outbound IP Addresses')
check3 = st.sidebar.checkbox('Top Active Ports')
check4 = st.sidebar.checkbox('Top Active IP-Ports')

left_column1, right_column1 = st.columns(2)
left_column2, right_column2 = st.columns(2)

if check1:
    left_column1.plotly_chart(top_in_IP, use_container_width=True)
if check2:
    right_column1.plotly_chart(top_out_IP, use_container_width=True)
if check3:
    left_column2.plotly_chart(top_ports, use_container_width=True)
if check4:
    right_column2.plotly_chart(combo, use_container_width=True)

I want to have the plots displayed according to the selection sequence, not pre-defined as per this code

Currently this code position each plot in a specific location, so if I pick the first and forth plots, they show diagonally, but I want them next to each other, and if the second one from the list is selected 3rd, then it will appear in the second row, as each row has two plots

  • Streamlit version: 1.19.0
  • Python version: 3.9.13



Aucun commentaire:

Enregistrer un commentaire