diff --git a/analyse_korrelation.py b/analyse_korrelation.py index a072835..8a7f731 100644 --- a/analyse_korrelation.py +++ b/analyse_korrelation.py @@ -6,6 +6,7 @@ from ci_template.plotly_template import export_figure from config_korrelation import ( theme, export_fig_visual, + export_fig_png, export_fig_clusteranalyse, export_fig_correlation_suchbegriffe_kategorien, export_fig_correlation_fu_kategorien, @@ -61,6 +62,7 @@ def prepare_figure_export(fig, name): def export_and_transfer_figure(fig, function_name, export_flag): export_figure(fig, function_name, export_flag, export_fig_png) + fig.show() # BibTeX-Datei laden bib_path = os.path.join("Research", "Charité - Universitätsmedizin Berlin", "Systematische Literaturrecherche", "Bibliothek", bib_filename) @@ -436,7 +438,6 @@ def visualize_indizes_vs_indizes(export_flag): export_flag ) - #====================================== cluster_colors = { @@ -722,4 +723,8 @@ visualize_forschungsunterfragen_vs_forschungsunterfragen(export_flag=export_fig_ visualize_suchbegriffe_vs_suchbegriffe(export_flag=export_fig_correlation_suchbegriffe_suchbegriffe) visualize_kategorien_vs_kategorien(export_flag=export_fig_correlation_kategorien_kategorien) visualize_indizes_vs_indizes(export_flag=export_fig_correlation_indizes_indizes) -plot_average_correlation_plotly(summary_df) \ No newline at end of file +plot_average_correlation_plotly(summary_df) + +# Visualisierungsoption für Plotly: Immer im Browser öffnen +import plotly.io as pio +pio.renderers.default = 'browser' \ No newline at end of file diff --git a/analyse_netzwerk.py b/analyse_netzwerk.py index 3c8272e..8545976 100644 --- a/analyse_netzwerk.py +++ b/analyse_netzwerk.py @@ -1,7 +1,7 @@ from config_netzwerk import theme, export_fig_visual, bib_filename -from ci_template.plotly_template import export_figure +from ci_template.plotly_template import export_figure as export_figure_ci import os @@ -63,8 +63,10 @@ from config_netzwerk import ( export_fig_visualize_languages, ) -def export_figure(fig, name, flag, bib_filename=None): - export_figure(fig, name, flag, export_fig_png) +from config_netzwerk import export_fig_png + +def export_figure_local(fig, name, flag, bib_filename=None): + export_figure_ci(fig, name, flag, export_fig_png) from ci_template.plotly_template import get_colors, get_plot_styles, get_standard_layout @@ -322,7 +324,7 @@ def visualize_network(bib_database): fig.update_layout(**layout) fig.show(config={"responsive": True}) - export_figure(fig, "visualize_network", export_fig_visualize_network, bib_filename) + export_figure_local(fig, "visualize_network", export_fig_visualize_network, bib_filename) # Einfache Pfadanalyse nach dem Anzeigen der Figur if 'e-learning' in G and 'online:lernen' in G: @@ -429,7 +431,7 @@ def visualize_tags(bib_database): fig.update_layout(**layout) fig.show(config={"responsive": True}) - export_figure(fig, "visualize_tags", export_fig_visualize_tags, bib_filename) + export_figure_local(fig, "visualize_tags", export_fig_visualize_tags, bib_filename) # Visualisierung 3: Häufigkeit Index def visualize_index(bib_database): @@ -477,7 +479,7 @@ def visualize_index(bib_database): fig.update_layout(**layout) fig.update_traces(marker=plot_styles['balken_primaryLine']) fig.show(config={"responsive": True}) - export_figure(fig, "visualize_index", export_fig_visualize_index, bib_filename) + export_figure_local(fig, "visualize_index", export_fig_visualize_index, bib_filename) # Visualisierung 4: Häufigkeit Forschungsunterfragen def visualize_research_questions(bib_database): @@ -526,7 +528,7 @@ def visualize_research_questions(bib_database): fig.update_layout(**layout) fig.update_traces(marker=plot_styles['balken_primaryLine']) fig.show(config={"responsive": True}) - export_figure(fig, "visualize_research_questions", export_fig_visualize_research_questions, bib_filename) + export_figure_local(fig, "visualize_research_questions", export_fig_visualize_research_questions, bib_filename) # Visualisierung 5: Häufigkeit spezifischer Kategorien def visualize_categories(bib_database): @@ -570,7 +572,7 @@ def visualize_categories(bib_database): fig.update_layout(**layout) fig.update_traces(marker=plot_styles['balken_primaryLine']) fig.show(config={"responsive": True}) - export_figure(fig, "visualize_categories", export_fig_visualize_categories, bib_filename) + export_figure_local(fig, "visualize_categories", export_fig_visualize_categories, bib_filename) # Zeitreihenanalyse der Veröffentlichungen def visualize_time_series(bib_database): @@ -617,7 +619,7 @@ def visualize_time_series(bib_database): fig.update_layout(**layout) fig.update_traces(line=plot_styles['linie_primaryLine']) fig.show(config={"responsive": True}) - export_figure(fig, "visualize_time_series", export_fig_visualize_time_series, bib_filename) + export_figure_local(fig, "visualize_time_series", export_fig_visualize_time_series, bib_filename) else: print("Keine gültigen Veröffentlichungsjahre gefunden.") @@ -651,7 +653,7 @@ def visualize_top_authors(bib_database): fig.update_layout(**layout) fig.update_traces(marker=plot_styles['balken_primaryLine']) fig.show(config={"responsive": True}) - export_figure(fig, "visualize_top_authors", export_fig_visualize_top_authors, bib_filename) + export_figure_local(fig, "visualize_top_authors", export_fig_visualize_top_authors, bib_filename) else: print("Keine Autoren gefunden.") @@ -697,7 +699,7 @@ def visualize_top_publications(bib_database): fig.update_layout(**layout) fig.update_traces(marker=plot_styles['balken_primaryLine']) fig.show(config={"responsive": True}) - export_figure(fig, "visualize_top_publications", export_fig_visualize_top_publications, bib_filename) + export_figure_local(fig, "visualize_top_publications", export_fig_visualize_top_publications, bib_filename) ########## @@ -829,7 +831,7 @@ def create_path_diagram(data): layout["autosize"] = True fig.update_layout(**layout) fig.show(config={"responsive": True}) - export_figure(fig, "create_path_diagram", export_fig_create_path_diagram, bib_filename) + export_figure_local(fig, "create_path_diagram", export_fig_create_path_diagram, bib_filename) ############# @@ -962,7 +964,7 @@ def create_sankey_diagram(bib_database): layout["autosize"] = True fig.update_layout(**layout) fig.show(config={"responsive": True}) - export_figure(fig, "create_sankey_diagram", export_fig_create_sankey_diagram, bib_filename) + export_figure_local(fig, "create_sankey_diagram", export_fig_create_sankey_diagram, bib_filename) ########## @@ -1090,7 +1092,7 @@ def visualize_sources_status(bib_database): layout["autosize"] = True fig.update_layout(**layout) fig.show(config={"responsive": True}) - export_figure(fig, "visualize_sources_status", export_fig_visualize_sources_status, bib_filename) + export_figure_local(fig, "visualize_sources_status", export_fig_visualize_sources_status, bib_filename) ############# @@ -1195,7 +1197,7 @@ def visualize_languages(bib_database): fig.show(config={"responsive": True}) # Tabelle ausgeben print(tabulate(df.sort_values("Anzahl", ascending=False), headers="keys", tablefmt="grid", showindex=False)) - export_figure(fig, "visualize_languages", export_fig_visualize_languages, bib_filename) + export_figure_local(fig, "visualize_languages", export_fig_visualize_languages, bib_filename) # Visualisierung der Verteilung von ENTRYTYPE innerhalb jeder Sprache def visualize_language_entrytypes(bib_database): @@ -1297,7 +1299,7 @@ def visualize_language_entrytypes(bib_database): fig.update_layout(**layout) fig.show(config={"responsive": True}) print(tabulate(grouped.sort_values(["Sprache", "Eintragstyp"]), headers=["Sprache", "Eintragstyp", "Anzahl", "Anteil innerhalb Sprache (%)", "Typgruppe"], tablefmt="grid", showindex=False)) - export_figure(fig, "visualize_language_entrytypes", export_fig_visualize_languages, bib_filename) + export_figure_local(fig, "visualize_language_entrytypes", export_fig_visualize_languages, bib_filename) ############# diff --git a/deskriptive-literaturauswahl.py b/deskriptive-literaturauswahl.py index 1b0bda4..8aae102 100644 --- a/deskriptive-literaturauswahl.py +++ b/deskriptive-literaturauswahl.py @@ -9,6 +9,7 @@ import matplotlib.pyplot as plt import plotly.graph_objects as go from datetime import date from scipy.stats.mstats import winsorize +from scipy.stats import iqr # --- CI-Template & Konfiguration --- from ci_template.plotly_template import ( @@ -18,6 +19,7 @@ from ci_template.plotly_template import ( ) from ci_template.plotly_template import export_figure from config_deskriptive_literaturauswahl import theme, export_fig_visual +from config_deskriptive_literaturauswahl import export_fig_png, export_fig_silhouette_plot # --- Initialisierung --- os.system('cls' if os.name == 'nt' else 'clear') @@ -40,65 +42,110 @@ n_values = np.array([ ]) # --- Berechnungen --- -q1 = np.percentile(sc_values, 25) -q2 = np.percentile(sc_values, 50) -q3 = np.percentile(sc_values, 75) +# Berechne IQR und automatische untere/obere Grenzen +sc_iqr = iqr(sc_values) +q1_val = np.percentile(sc_values, 25) +q3_val = np.percentile(sc_values, 75) +lower_bound = q1_val - 1.5 * sc_iqr +upper_bound = q3_val + 1.5 * sc_iqr +sc_winsorized = np.clip(sc_values, lower_bound, upper_bound) +median_winsorized = np.median(sc_winsorized) + +# Quartile +q1 = q1_val +q2 = np.median(sc_values) +q3 = q3_val max_value = np.max(sc_values) min_value = np.min(sc_values) -sc_winsorized = winsorize(sc_values, limits=[0.1, 0.1]) -median_winsorized = np.median(sc_winsorized) - -fatigue_threshold = 0.96 -circadian_optimum = 0.99 +# Schwellenwerte datenbasiert +fatigue_threshold = q1 # oder eine alternative datenbasierte Schwelle +circadian_optimum = q3 # oder np.percentile(sc_values, 90) # --- Visualisierung --- fig = go.Figure() -# SC-Linie -fig.add_trace(go.Scatter(x=years, y=sc_values, name='Silhouette-Scores', - mode='lines+markers', yaxis='y1')) +from ci_template.plotly_template import get_plot_styles +styles = get_plot_styles() -# n-Balken -fig.add_trace(go.Bar(x=years, y=n_values, name='n-Werte (Fallzahlen)', - yaxis='y2', opacity=0.3, marker_color=colors["depthArea"])) +fig.add_trace(go.Scatter( + x=years, + y=n_values, + name='Fallzahlen (n)', + yaxis='y2', + mode='lines+markers', + line=dict(color=colors["secondaryLine"], width=1), + marker=dict(size=16, color=colors["secondaryLine"], symbol="square"), + showlegend=True +)) # Quartile & Bezugslinien -fig.add_trace(go.Scatter(x=years, y=[q1]*len(years), mode='lines', name=f'SC Q1 = {q1:.4f}', - line=dict(dash='dot', color='green'), yaxis='y1')) -fig.add_trace(go.Scatter(x=years, y=[q2]*len(years), mode='lines', name=f'SC Median (Q2) = {q2:.4f}', - line=dict(dash='dot', color='blue'), yaxis='y1')) -fig.add_trace(go.Scatter(x=years, y=[q3]*len(years), mode='lines', name=f'SC Q3 = {q3:.4f}', - line=dict(dash='dot', color='purple'), yaxis='y1')) -fig.add_trace(go.Scatter(x=years, y=[min_value]*len(years), mode='lines', name=f'SC Min = {min_value:.4f}', - line=dict(dash='dash', color='red'), yaxis='y1')) -fig.add_trace(go.Scatter(x=years, y=[max_value]*len(years), mode='lines', name=f'SC Max = {max_value:.4f}', - line=dict(dash='dash', color='orange'), yaxis='y1')) -fig.add_trace(go.Scatter(x=years, y=[fatigue_threshold]*len(years), mode='lines', - name=f'Schwelle: Erschöpfungs-Bias = {fatigue_threshold:.4f}', - line=dict(dash='dashdot', color='firebrick'), yaxis='y1')) -fig.add_trace(go.Scatter(x=years, y=[circadian_optimum]*len(years), mode='lines', - name=f'Idealer Wert (circadian) = {circadian_optimum:.4f}', - line=dict(dash='dashdot', color='darkcyan'), yaxis='y1')) -fig.add_trace(go.Scatter(x=years, y=[median_winsorized]*len(years), mode='lines', - name=f'Winsorisierter Median = {median_winsorized:.4f}', - line=dict(dash='dot', color='black'), yaxis='y1')) +fig.add_trace(go.Scatter(x=years, y=[q1]*len(years), mode='lines', name='SC Q1', + line=dict(dash='dot', color=colors["brightArea"]), yaxis='y1')) +fig.add_trace(go.Scatter(x=years, y=[q2]*len(years), mode='lines', name='SC Median (Q2)', + line=dict(dash='dot', color=colors["depthArea"]), yaxis='y1')) +fig.add_trace(go.Scatter(x=years, y=[q3]*len(years), mode='lines', name='SC Q3', + line=dict(dash='dot', color=colors["accent"]), yaxis='y1')) +fig.add_trace(go.Scatter( + x=years, + y=[min_value]*len(years), + mode='lines', + name='SC Min', + line=dict(dash='dash', color=colors["negativeHighlight"]), + yaxis='y1' +)) +fig.add_trace(go.Scatter( + x=years, + y=[max_value]*len(years), + mode='lines', + name='SC Max', + line=dict(dash='dash', color=colors["positiveHighlight"]), + yaxis='y1' +)) + +fig.add_trace(go.Scatter( + x=years, + y=sc_values, + name='Silhouette-Scores', + yaxis='y1', + mode='lines+markers', + line=dict(color=colors["primaryLine"], width=1), + marker=dict(size=16, color=colors["primaryLine"], symbol="circle"), + showlegend=True +)) # Layout -fig.update_layout( - **get_standard_layout( - title=f"Silhouette-Scores und Fallzahlen (n={sum(n_values)}, Stand: {current_date})", - x_title="Jahr", - y_title="Silhouette-Score", - yaxis2=dict( - title="Fallzahlen (n)", - showgrid=False - ) +layout = get_standard_layout( + title="Silhouette-Scores und Fallzahlen pro Jahr", + x_title='Jahr', + y_title='Silhouette-Score', + yaxis2=dict( + title="Fallzahlen (n)", + showgrid=False, + title_standoff=20 ) ) - -# Anzeige -fig.show(config={"responsive": True}) +layout["font"] = {"size": 14, "color": colors['text']} +layout["title"] = dict(text="Silhouette-Scores und Fallzahlen pro Jahr", font=dict(color=colors["text"])) +layout["margin"] = dict(b=80, t=120, l=60, r=60) +layout["xaxis"] = layout.get("xaxis", {}) +layout["xaxis"]["automargin"] = True +layout["autosize"] = True +layout["legend"] = dict( + x=1.05, + y=1.0, + xanchor="left", + yanchor="top", + orientation="v", + traceorder="normal", + itemclick="toggleothers", + itemdoubleclick="toggle" +) +fig.update_layout(**layout) # --- Export --- export_figure(fig, "silhouette_scores_und_fallzahlen", export_fig_silhouette_plot, export_fig_png) + +# (Hinweis: Balkenfarbe wird direkt im Bar-Trace gesetzt) + +fig.show(config={"responsive": True})