Mini-Hackathon-Data-Viz/app.py

152 lines
6.3 KiB
Python
Raw Permalink Normal View History

2024-10-03 11:40:50 +02:00
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
2024-10-03 11:45:57 +02:00
st.title("Erweiterter List Data Visualizer & Analyzer")
2024-10-03 11:40:50 +02:00
# 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":
2024-10-03 11:45:57 +02:00
dateneingabe = st.sidebar.text_area("Gib Zahlen ein, getrennt durch Kommas oder Zeilenumbrüche:", value="1,2,3,4,5")
2024-10-03 11:40:50 +02:00
try:
2024-10-03 11:45:57 +02:00
daten_zeilen = [zeile.strip() for zeile in dateneingabe.strip().split("\n") if zeile.strip()]
2024-10-03 11:49:21 +02:00
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])]
2024-10-03 11:40:50 +02:00
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)
2024-10-03 11:45:57 +02:00
# 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]
2024-10-03 11:40:50 +02:00
else:
st.warning("Bitte lade eine CSV-Datei hoch.")
st.stop()
2024-10-03 11:45:57 +02:00
else:
st.error("Ungültige Datenquelle ausgewählt.")
st.stop()
2024-10-03 11:40:50 +02:00
# Interaktive Filter
st.sidebar.header("Datenfilter")
2024-10-03 11:45:57 +02:00
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])]
2024-10-03 11:40:50 +02:00
# Statistische Analyse
st.header("Statistische Analyse")
2024-10-03 11:45:57 +02:00
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']]
2024-10-03 11:40:50 +02:00
2024-10-03 11:45:57 +02:00
statistiken = berechne_statistiken(gefilterter_df)
st.dataframe(statistiken)
2024-10-03 11:40:50 +02:00
2024-10-03 11:45:57 +02:00
# Ausreißererkennung
st.header("Ausreißererkennung")
ausreisser_df = pd.DataFrame()
2024-10-03 11:40:50 +02:00
2024-10-03 11:45:57 +02:00
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:
2024-10-03 11:40:50 +02:00
st.subheader("Erkannte Ausreißer")
2024-10-03 11:45:57 +02:00
st.write(ausreisser_df.drop_duplicates())
2024-10-03 11:40:50 +02:00
else:
st.subheader("Keine Ausreißer erkannt")
2024-10-03 11:45:57 +02:00
# 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.")
2024-10-03 11:40:50 +02:00
# Gefilterte Daten anzeigen
st.header("Gefilterte Daten")
st.write(gefilterter_df)