Third Prompt
parent
4d0472f136
commit
e775103616
134
backend/app.py
134
backend/app.py
|
@ -3,7 +3,7 @@ import pandas as pd
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import plotly.express as px
|
import plotly.express as px
|
||||||
|
|
||||||
st.title("List Data Visualizer & Analyzer")
|
st.title("Erweiterter List Data Visualizer & Analyzer")
|
||||||
|
|
||||||
# Seitenleiste für die Dateneingabe
|
# Seitenleiste für die Dateneingabe
|
||||||
st.sidebar.header("Dateneingabe")
|
st.sidebar.header("Dateneingabe")
|
||||||
|
@ -11,10 +11,13 @@ st.sidebar.header("Dateneingabe")
|
||||||
datenquelle = st.sidebar.radio("Datenquelle auswählen:", ("Manuelle Eingabe", "CSV-Datei hochladen"))
|
datenquelle = st.sidebar.radio("Datenquelle auswählen:", ("Manuelle Eingabe", "CSV-Datei hochladen"))
|
||||||
|
|
||||||
if datenquelle == "Manuelle Eingabe":
|
if datenquelle == "Manuelle Eingabe":
|
||||||
dateneingabe = st.sidebar.text_area("Gib Zahlen ein, getrennt durch Kommas:", value="1,2,3,4,5")
|
dateneingabe = st.sidebar.text_area("Gib Zahlen ein, getrennt durch Kommas oder Zeilenumbrüche:", value="1,2,3,4,5")
|
||||||
try:
|
try:
|
||||||
datenliste = [float(x.strip()) for x in dateneingabe.split(",") if x.strip()]
|
# Unterstützung für mehrere Spalten
|
||||||
df = pd.DataFrame(datenliste, columns=['Werte'])
|
daten_zeilen = [zeile.strip() for zeile in dateneingabe.strip().split("\n") if zeile.strip()]
|
||||||
|
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:
|
except ValueError:
|
||||||
st.error("Bitte gib eine gültige Liste von Zahlen ein.")
|
st.error("Bitte gib eine gültige Liste von Zahlen ein.")
|
||||||
st.stop()
|
st.stop()
|
||||||
|
@ -22,54 +25,121 @@ elif datenquelle == "CSV-Datei hochladen":
|
||||||
hochgeladene_datei = st.sidebar.file_uploader("Wähle eine CSV-Datei aus", type="csv")
|
hochgeladene_datei = st.sidebar.file_uploader("Wähle eine CSV-Datei aus", type="csv")
|
||||||
if hochgeladene_datei is not None:
|
if hochgeladene_datei is not None:
|
||||||
df = pd.read_csv(hochgeladene_datei)
|
df = pd.read_csv(hochgeladene_datei)
|
||||||
# Annahme: Die Daten stehen in der ersten Spalte
|
# Numerische Spalten identifizieren
|
||||||
df = df.iloc[:, [0]]
|
numerische_spalten = df.select_dtypes(include=[np.number]).columns.tolist()
|
||||||
df.columns = ['Werte']
|
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:
|
else:
|
||||||
st.warning("Bitte lade eine CSV-Datei hoch.")
|
st.warning("Bitte lade eine CSV-Datei hoch.")
|
||||||
st.stop()
|
st.stop()
|
||||||
|
else:
|
||||||
|
st.error("Ungültige Datenquelle ausgewählt.")
|
||||||
|
st.stop()
|
||||||
|
|
||||||
# Interaktive Filter
|
# Interaktive Filter
|
||||||
st.sidebar.header("Datenfilter")
|
st.sidebar.header("Datenfilter")
|
||||||
min_wert = float(df['Werte'].min())
|
gefilterter_df = df.copy()
|
||||||
max_wert = float(df['Werte'].max())
|
|
||||||
filterbereich = st.sidebar.slider('Wertebereich auswählen:', min_wert, max_wert, (min_wert, max_wert))
|
for spalte in df.columns:
|
||||||
gefilterter_df = df[(df['Werte'] >= filterbereich[0]) & (df['Werte'] <= filterbereich[1])]
|
# 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
|
# Statistische Analyse
|
||||||
st.header("Statistische Analyse")
|
st.header("Statistische Analyse")
|
||||||
st.write(f"**Anzahl:** {gefilterter_df['Werte'].count()}")
|
|
||||||
st.write(f"**Mittelwert:** {gefilterter_df['Werte'].mean()}")
|
|
||||||
st.write(f"**Median:** {gefilterter_df['Werte'].median()}")
|
|
||||||
st.write(f"**Standardabweichung:** {gefilterter_df['Werte'].std()}")
|
|
||||||
|
|
||||||
# Ausreißererkennung (mithilfe der 1.5*IQR-Regel)
|
def berechne_statistiken(daten):
|
||||||
Q1 = gefilterter_df['Werte'].quantile(0.25)
|
beschreibung = daten.describe().transpose()
|
||||||
Q3 = gefilterter_df['Werte'].quantile(0.75)
|
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
|
IQR = Q3 - Q1
|
||||||
untere_grenze = Q1 - 1.5 * IQR
|
untere_grenze = Q1 - 1.5 * IQR
|
||||||
obere_grenze = Q3 + 1.5 * IQR
|
obere_grenze = Q3 + 1.5 * IQR
|
||||||
ausreisser = gefilterter_df[(gefilterter_df['Werte'] < untere_grenze) | (gefilterter_df['Werte'] > obere_grenze)]
|
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
|
# Visualisierungen
|
||||||
st.header("Datenvisualisierungen")
|
st.header("Datenvisualisierungen")
|
||||||
|
st.sidebar.header("Visualisierungseinstellungen")
|
||||||
|
|
||||||
# Histogramm
|
diagramm_typ = st.sidebar.selectbox("Diagrammtyp auswählen", ["Histogramm", "Boxplot", "Streudiagramm", "Liniendiagramm", "Korrelationsmatrix"])
|
||||||
|
|
||||||
|
if diagramm_typ == "Histogramm":
|
||||||
st.subheader("Histogramm")
|
st.subheader("Histogramm")
|
||||||
fig1 = px.histogram(gefilterter_df, x='Werte', nbins=20, title='Histogramm')
|
ausgewählte_spalten = st.multiselect("Wähle die Spalten für das Histogramm aus", gefilterter_df.columns.tolist(), default=gefilterter_df.columns.tolist())
|
||||||
st.plotly_chart(fig1)
|
for spalte in ausgewählte_spalten:
|
||||||
|
fig = px.histogram(gefilterter_df, x=spalte, nbins=20, title=f'Histogramm von {spalte}')
|
||||||
# Boxplot
|
st.plotly_chart(fig)
|
||||||
|
elif diagramm_typ == "Boxplot":
|
||||||
st.subheader("Boxplot")
|
st.subheader("Boxplot")
|
||||||
fig2 = px.box(gefilterter_df, y='Werte', points="all", title='Boxplot mit Ausreißern')
|
fig = px.box(gefilterter_df, points="all", title='Boxplot')
|
||||||
st.plotly_chart(fig2)
|
st.plotly_chart(fig)
|
||||||
|
elif diagramm_typ == "Streudiagramm":
|
||||||
# Ausreißer anzeigen
|
if len(gefilterter_df.columns) >= 2:
|
||||||
if not ausreisser.empty:
|
x_achse = st.sidebar.selectbox("X-Achse", gefilterter_df.columns)
|
||||||
st.subheader("Erkannte Ausreißer")
|
y_achse = st.sidebar.selectbox("Y-Achse", gefilterter_df.columns, index=1)
|
||||||
st.write(ausreisser)
|
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:
|
else:
|
||||||
st.subheader("Keine Ausreißer erkannt")
|
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
|
# Gefilterte Daten anzeigen
|
||||||
st.header("Gefilterte Daten")
|
st.header("Gefilterte Daten")
|
||||||
|
|
Loading…
Reference in New Issue