Dataframe multi filter

Hello all,

I’m newbie in streamlit and i have to create an app for my master degree.

I try to have a dataframe with 2 filter : a text input and a list where you can choose multi values.

Here is my code where df is my dataset :

##  Create filters on ship_to and part number
# Create ship to list with all values : 
        ship_to = df['Ship_to'].unique().tolist()  
      
# Create a table to have filters side by side :
        col1, col2 = st.columns([1,1])
        with col2:
            selected_shipto = st.multiselect(
                'Which ship to would like to choose ? ',
                ship_to)
        with col1:
            selected_pn = st.text_input(
                'Which PN are you looking for ? ',
                )
# Create filter_function for df   
        df_filtered = df[
            df['Part_number'].str.contains(selected_pn) & 
            df['Ship_to'].isin(selected_shipto)]
        
# Avoid empty dataframe when no filters selected : 
         def filtered_data(df):
            if df_filtered.empty :
               st.write(df)
            else : st.write(df_filtered)
            return df_filtered

# Write data frame :
        st.write(filtered_data)

But I can only filter the ship_to column and not the part number and I have 2 dataframe on the app…
Could you please please help me ? I first succeed with both filters working but I change some line and I couldn’t find the right code…

Thank you all :wink:

As information, I already try to replace ‘&’ by ‘|’ in my filter function but it did not work…

Hi @Solene_Fritsch ,

Welcome to the Streamlit community forum :partying_face::balloon:

Are you sure you have called your function filtered_data? I don’t see it in your code snippet ( incase I haven’t missed anything ). Would you mind to share your entire code , may be ? It will be easy to understand for others to help you out.

Best
Avra

Dear AvratanuBiswas,

Thank you four your reply ! :slight_smile:

This is my full code :

#__________________________
## Import libraries
#__________________________

import pandas as pd
import numpy as np
import streamlit as st
from PIL import Image
import altair as alt
from datetime import datetime

#__________________________
## Import and clean dataset
#__________________________

# Transform XLSX file to CSV to load data properly
df = pd.read_excel(accessfile_etc.xlsx')

# Split column notification into different column and rename it
df = df.join(df['Notification'].str.split(';', expand= True))
df = df.rename({0: 'Contract', 1: 'Action', 2: 'Part_number', 3: 'Product', 4: 'Ship_to', 5: 'Date'}, axis=1)

# Remove useless column
del df['Notification']
del df['Date de notifification']

#Remove Contract/Contrat N° from Contract column
df['Contract'] = df.Contract.str.replace('Contract N°' , '')
df['Contract'] = df.Contract.str.replace('Contrat N°' , '')

# Check and transform date type
print(type('Date de traitement'))
df['Date de traitement'] = pd.to_datetime(df['Date de traitement'], format='%Y%m%d')
df['Date'] = pd.to_datetime(df['Date'], format='%d/%m/%Y')
print(df.dtypes)

# Count Date
df['Count_date'] = df['Date'].map(df['Date'].value_counts())

# Count Ship_to
df['Count_ship'] = df['Ship_to'].map(df['Ship_to'].value_counts())

## Application creation
#______________________

# Data creation
HOME_MSG = ('Welcome to the app')
APP_TITLE = 'APPLICATIF SUP'
APP_HEADER = 'Tracking tool '
SIDEBAR_TITLE = 'Menu'
MENU_MSG = 'Choose data you want to view'
MENU_CHOICES = ['Home','Sales Administration','Status','Product']
logo_one = Image.open('accessfile_etc')
logo_two = Image.open('accessfile2_etc')
TITLE_SALES = 'What is a Sup?'
SUBTITLE_SALES ='What to do whit it ?'

def load_data(nrows):
    data = df
    return data

@st.cache

#data_load_state.text("Done! (using st.cache)")
    
def home_msg():
    st.write(HOME_MSG)
        

def main():
    
    #Set image 1
    st.sidebar.image(logo_one)
    
    #Set Sidebar title
    st.sidebar.title(SIDEBAR_TITLE)

    #Set Menu
    menu_action =
st.sidebar.selectbox(MENU_MSG,MENU_CHOICES)
    
    if menu_action=='Home':
        
        #Set App title and logo two
        col1, col2 = st.columns([1,7])
        with col2:
            st.title(APP_TITLE)
        with col1:
            st.image(logo_two, width=120)
        
        #Set App header
        st.header(APP_HEADER)

    if menu_action=='Sales Administration':
        
        # EXPLAIN WHAT IS APPLICATIF SUP AND HOW TO DEAL WITH IT
        st.title(TITLE_SALES)
        st.subheader(SUBTITLE_SALES)
        st.markdown("We have to **verify** each action : ")
        texts = ["- Go on website : link.com","- Download docs.","- Check if ok.","- If ok, action1.","- If not, action2"]
        st.write(texts[0])
        st.write(texts[1])
        st.write(texts[2])
        st.write(texts[3])
        st.write(texts[4])
    
    if menu_action=='Status':
        st.write('This is the full dataset. You can find here each notification received, whom traited it and when.')
        
        # DATAFRAME :
        # Create a text element and let the reader know the data is loading.
        data_load_state = st.text('Loading data...')
        # Load 10,000 rows of data into the dataframe.
        df = load_data(1000)
        # Notify the reader that the data was successfully loaded.
        data_load_state.text('Loading data...done!')
        
        st.subheader('Data to analyse :')
        
       ##  Create filters on ship_to and part number
       # Create ship to list with all values : 
        ship_to = df['Ship_to'].unique().tolist()  
      
        # Create a table to have filters side by side :
        col1, col2 = st.columns([1,1])
        with col2:
            selected_shipto = st.multiselect(
                'Which ship to would like to choose ? ',
                ship_to)
        with col1:
            selected_pn = st.text_input(
                'Which PN are you looking for ? ',
                )
            # Create filter_function for df   
        df_filtered = df[
            df['Part_number'].str.contains(selected_pn) & 
            df['Ship_to'].isin(selected_shipto)]
        
        # Avoid empty dataframe when no filters selected : 
        def filtered_data(df):
            if df_filtered.empty :
               st.write(df)
            else : st.write(df_filtered)
            return df_filtered

        # Write data frame :
        st.write(filtered_data)
        
        ## Graph parts
        ##_______
        # Altair chart n.1 :
        #st.subheader('Action done by date :')
        
        # Filtered chart on ship_to / pn

        #c = alt.Chart(df).mark_circle().encode(
         #   x='Date', y='Count_date', size='Action', color ='Action', 
          #  tooltip=["Date", "Count_date", "Action"])

        #st.altair_chart(c, use_container_width=True)

        # Altair chart n.2 :
        #st.subheader('Action done by ship to :')
        
        # Filtered chart on part number
        
        #c = alt.Chart(df).mark_bar().encode(
         #   x='Ship_to', y='Count_ship', tooltip=["Ship_to", "Count_ship", "Action"]).configure_mark(
          #      opacity=0.2,
           #     color='orange').interactive()
        
        #st.altair_chart(c, use_container_width=True)
        


if __name__ == '__main__':
    main()

Thank you for your help. I think (maybe) that I can not filter the dataset on PN if Ship to is not filtered. I tried to create a function if Ship to filter is empty. It works. But then I can not filter only on Ship to. An infinite loop ahha. :frowning: