import streamlit as st import pandas as pd import numpy as np import plotly.express as px st.title("Erweiterter List Data Visualizer & Analyzer") # Seitenleiste für die Dateneingabe st.sidebar.header("Dateneingabe") datenquelle = st.sidebar.radio("Datenquelle auswählen:", ("Manuelle Eingabe", "CSV-Datei hochladen")) if datenquelle == "Manuelle Eingabe": dateneingabe = st.sidebar.text_area("Gib Zahlen ein, getrennt durch Kommas oder Zeilenumbrüche:", value="1,2,3,4,5") try: daten_zeilen = [zeile.strip() for zeile in dateneingabe.strip().split("\n") if zeile.strip()] if len(daten_zeilen) == 1: # Eindimensionale Daten (eine Zeile ohne Zeilenumbrüche) datenliste = [float(x.strip()) for x in daten_zeilen[0].split(",") if x.strip()] df = pd.DataFrame(datenliste, columns=['Werte']) else: # Mehrdimensionale Daten (mehrere Zeilen) datenliste = [list(map(float, zeile.split(','))) for zeile in daten_zeilen] df = pd.DataFrame(datenliste) df.columns = [f"Spalte {i+1}" for i in range(df.shape[1])] except ValueError: st.error("Bitte gib eine gültige Liste von Zahlen ein.") st.stop() elif datenquelle == "CSV-Datei hochladen": hochgeladene_datei = st.sidebar.file_uploader("Wähle eine CSV-Datei aus", type="csv") if hochgeladene_datei is not None: df = pd.read_csv(hochgeladene_datei) # Numerische Spalten identifizieren numerische_spalten = df.select_dtypes(include=[np.number]).columns.tolist() if not numerische_spalten: st.error("Die hochgeladene Datei enthält keine numerischen Spalten.") st.stop() st.sidebar.subheader("Spaltenauswahl") ausgewählte_spalten = st.sidebar.multiselect("Wähle die Spalten für die Analyse aus", numerische_spalten, default=numerische_spalten) if not ausgewählte_spalten: st.error("Bitte wähle mindestens eine Spalte aus.") st.stop() df = df[ausgewählte_spalten] else: st.warning("Bitte lade eine CSV-Datei hoch.") st.stop() else: st.error("Ungültige Datenquelle ausgewählt.") st.stop() # Interaktive Filter st.sidebar.header("Datenfilter") gefilterter_df = df.copy() for spalte in df.columns: # Konvertiere die Spalte in numerische Werte und entferne NaN gefilterter_df[spalte] = pd.to_numeric(gefilterter_df[spalte], errors='coerce') gefilterter_df = gefilterter_df.dropna(subset=[spalte]) min_wert = float(gefilterter_df[spalte].min()) max_wert = float(gefilterter_df[spalte].max()) # Überprüfen, ob min_wert und max_wert unterschiedlich sind if min_wert == max_wert: st.warning(f"Die Spalte '{spalte}' hat konstante Werte. Der Slider wird für diese Spalte deaktiviert.") continue # Überspringe diese Spalte # Slider erstellen filterbereich = st.sidebar.slider( f"Wertebereich für '{spalte}' auswählen:", min_value=min_wert, max_value=max_wert, value=(min_wert, max_wert) ) # Daten filtern gefilterter_df = gefilterter_df[(gefilterter_df[spalte] >= filterbereich[0]) & (gefilterter_df[spalte] <= filterbereich[1])] # Statistische Analyse st.header("Statistische Analyse") def berechne_statistiken(daten): beschreibung = daten.describe().transpose() beschreibung['Median'] = daten.median() beschreibung['Varianz'] = daten.var() return beschreibung[['count', 'mean', 'Median', 'std', 'Varianz', 'min', '25%', '50%', '75%', 'max']] statistiken = berechne_statistiken(gefilterter_df) st.dataframe(statistiken) # Ausreißererkennung st.header("Ausreißererkennung") ausreisser_df = pd.DataFrame() for spalte in gefilterter_df.columns: Q1 = gefilterter_df[spalte].quantile(0.25) Q3 = gefilterter_df[spalte].quantile(0.75) IQR = Q3 - Q1 untere_grenze = Q1 - 1.5 * IQR obere_grenze = Q3 + 1.5 * IQR ausreisser = gefilterter_df[(gefilterter_df[spalte] < untere_grenze) | (gefilterter_df[spalte] > obere_grenze)] ausreisser_df = pd.concat([ausreisser_df, ausreisser]) if not ausreisser_df.empty: st.subheader("Erkannte Ausreißer") st.write(ausreisser_df.drop_duplicates()) else: st.subheader("Keine Ausreißer erkannt") # Visualisierungen st.header("Datenvisualisierungen") st.sidebar.header("Visualisierungseinstellungen") diagramm_typ = st.sidebar.selectbox("Diagrammtyp auswählen", ["Histogramm", "Boxplot", "Streudiagramm", "Liniendiagramm", "Korrelationsmatrix"]) if diagramm_typ == "Histogramm": st.subheader("Histogramm") ausgewählte_spalten = st.multiselect("Wähle die Spalten für das Histogramm aus", gefilterter_df.columns.tolist(), default=gefilterter_df.columns.tolist()) for spalte in ausgewählte_spalten: fig = px.histogram(gefilterter_df, x=spalte, nbins=20, title=f'Histogramm von {spalte}') st.plotly_chart(fig) elif diagramm_typ == "Boxplot": st.subheader("Boxplot") fig = px.box(gefilterter_df, points="all", title='Boxplot') st.plotly_chart(fig) elif diagramm_typ == "Streudiagramm": if len(gefilterter_df.columns) >= 2: x_achse = st.sidebar.selectbox("X-Achse", gefilterter_df.columns) y_achse = st.sidebar.selectbox("Y-Achse", gefilterter_df.columns, index=1) st.subheader("Streudiagramm") fig = px.scatter(gefilterter_df, x=x_achse, y=y_achse, title=f'Streudiagramm {x_achse} vs {y_achse}') st.plotly_chart(fig) else: st.warning("Für ein Streudiagramm sind mindestens zwei numerische Spalten erforderlich.") elif diagramm_typ == "Liniendiagramm": st.subheader("Liniendiagramm") ausgewählte_spalten = st.multiselect("Wähle die Spalten für das Liniendiagramm aus", gefilterter_df.columns.tolist(), default=gefilterter_df.columns.tolist()) fig = px.line(gefilterter_df, y=ausgewählte_spalten, title='Liniendiagramm') st.plotly_chart(fig) elif diagramm_typ == "Korrelationsmatrix": if len(gefilterter_df.columns) >= 2: st.subheader("Korrelationsmatrix") korrelation = gefilterter_df.corr() fig = px.imshow(korrelation, text_auto=True, title='Korrelationsmatrix') st.plotly_chart(fig) else: st.warning("Für eine Korrelationsmatrix sind mindestens zwei numerische Spalten erforderlich.") # Gefilterte Daten anzeigen st.header("Gefilterte Daten") st.write(gefilterter_df)