2024-10-16 20:48:05 +02:00
|
|
|
import pandas as pd
|
2024-10-16 21:15:23 +02:00
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
import numpy as np
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
# Manuelle Zuordnung der Monatsnamen von Deutsch auf Englisch
|
|
|
|
month_translation = {
|
2024-10-17 20:42:54 +02:00
|
|
|
'Jan': 'Jan', 'Feb': 'Feb', 'Mär': 'Mar', 'Mrz': 'Mar', 'Apr': 'Apr', 'Mai': 'May', 'Jun': 'Jun',
|
2024-10-16 21:15:23 +02:00
|
|
|
'Jul': 'Jul', 'Aug': 'Aug', 'Sep': 'Sep', 'Okt': 'Oct', 'Nov': 'Nov', 'Dez': 'Dec'
|
|
|
|
}
|
|
|
|
|
2024-10-18 10:40:27 +02:00
|
|
|
# Funktion zur Umwandlung von '6h 11min' in numerische Stundenwerte
|
|
|
|
def convert_sleep_duration(sleep_duration_str):
|
|
|
|
print(sleep_duration_str)
|
|
|
|
hours = 0
|
|
|
|
minutes = 0
|
|
|
|
if 'h' in sleep_duration_str:
|
|
|
|
hours_part = sleep_duration_str.split('h')[0].strip()
|
|
|
|
hours = int(hours_part)
|
|
|
|
if 'min' in sleep_duration_str:
|
|
|
|
minutes_part = sleep_duration_str.split('h')[-1].replace('min', '').strip()
|
|
|
|
minutes = int(minutes_part)
|
|
|
|
return hours + (minutes / 60)
|
2024-10-16 21:15:23 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Funktion, um Datumsbereiche wie 'Mrz 29-Apr 4', 'Dez 22-28 2023' oder 'Dez 28' in Kalenderwoche und Jahr zu konvertieren
|
|
|
|
def convert_to_week_and_year(date_range_str):
|
2024-10-17 20:47:31 +02:00
|
|
|
# Entferne zusätzliche Leerzeichen um den Bindestrich herum und entferne Kommas
|
2024-10-17 20:42:54 +02:00
|
|
|
date_range_str = date_range_str.replace(" - ", "-").replace(",", "")
|
|
|
|
|
2024-10-17 20:52:26 +02:00
|
|
|
# Prüfen, ob das Format nur einen Tag und Monat enthält (z.B. 'Dez 28')
|
|
|
|
if "-" not in date_range_str and len(date_range_str.split(" ")) == 2:
|
|
|
|
# Nur ein Datum (Monat und Tag)
|
|
|
|
month_str, day_str = date_range_str.split(" ")
|
|
|
|
day = int(day_str.strip())
|
|
|
|
year_str = str(datetime.now().year) # Verwende das aktuelle Jahr
|
|
|
|
|
|
|
|
# Konvertiere den deutschen Monatsnamen in den englischen
|
|
|
|
if month_str in month_translation:
|
|
|
|
month_str = month_translation[month_str]
|
|
|
|
|
|
|
|
# Konvertiere das Datum
|
|
|
|
start_date = datetime.strptime(f"{month_str} {day} {year_str}", "%b %d %Y")
|
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Berechne die Kalenderwoche und das Jahr
|
2024-10-17 20:52:26 +02:00
|
|
|
week_number = start_date.isocalendar()[1]
|
2024-10-18 09:59:08 +02:00
|
|
|
year = start_date.year
|
2024-10-17 20:52:26 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
return f"W{week_number}-{year}"
|
2024-10-17 20:52:26 +02:00
|
|
|
|
2024-10-17 20:50:23 +02:00
|
|
|
# Prüfen, ob das Jahr am Ende steht (z.B. 'Dez 22-28 2023')
|
|
|
|
if date_range_str[-4:].isdigit():
|
|
|
|
# Jahr am Ende des Datums
|
|
|
|
year_str = date_range_str[-4:]
|
|
|
|
date_range_str = date_range_str[:-5] # Entferne das Jahr aus der Datumsangabe
|
|
|
|
else:
|
|
|
|
# Kein Jahr am Ende -> nutze das aktuelle Jahr
|
|
|
|
year_str = str(datetime.now().year)
|
|
|
|
|
2024-10-17 20:42:54 +02:00
|
|
|
# Splitte den Datumsbereich in Start- und Endteil
|
|
|
|
start_part, end_part = date_range_str.split("-")
|
|
|
|
|
|
|
|
# Verarbeite den Startteil
|
|
|
|
start_parts = start_part.split(" ")
|
|
|
|
start_month_str = start_parts[0]
|
|
|
|
start_day = int(start_parts[1].strip()) # Nimm den Starttag und entferne etwaige Leerzeichen
|
|
|
|
|
|
|
|
# Verarbeite den Endteil
|
|
|
|
end_parts = end_part.split(" ")
|
|
|
|
|
2024-10-17 20:50:23 +02:00
|
|
|
# Verarbeite das Enddatum, basierend darauf, ob der Endteil das Jahr enthält
|
|
|
|
if len(end_parts) == 2: # Fall: 'Apr 4'
|
2024-10-17 20:47:31 +02:00
|
|
|
end_month_str = end_parts[0]
|
|
|
|
end_day = int(end_parts[1].strip())
|
2024-10-17 20:42:54 +02:00
|
|
|
else:
|
2024-10-17 20:50:23 +02:00
|
|
|
# Fall: kein Monat -> nur Tag (z.B. '28' im Format 'Dez 22-28 2023')
|
2024-10-17 20:47:31 +02:00
|
|
|
end_month_str = start_month_str
|
2024-10-17 20:42:54 +02:00
|
|
|
end_day = int(end_parts[0].strip())
|
|
|
|
|
|
|
|
# Konvertiere den deutschen Monatsnamen in den englischen für beide Monate
|
|
|
|
if start_month_str in month_translation:
|
|
|
|
start_month_str = month_translation[start_month_str]
|
|
|
|
if end_month_str in month_translation:
|
|
|
|
end_month_str = month_translation[end_month_str]
|
|
|
|
|
|
|
|
try:
|
|
|
|
# Konvertiere das Startdatum in ein Datum
|
2024-10-17 20:50:23 +02:00
|
|
|
start_date = datetime.strptime(f"{start_month_str} {start_day} {year_str}", "%b %d %Y")
|
2024-10-17 20:42:54 +02:00
|
|
|
except ValueError:
|
2024-10-17 20:50:23 +02:00
|
|
|
raise ValueError(f"Ungültiges Startdatum: {start_month_str} {start_day} {year_str}")
|
2024-10-16 20:48:05 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Berechne die Kalenderwoche und das Jahr basierend auf dem Startdatum
|
2024-10-17 20:42:54 +02:00
|
|
|
week_number = start_date.isocalendar()[1]
|
2024-10-18 09:59:08 +02:00
|
|
|
year = start_date.year
|
2024-10-16 20:58:01 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
return f"W{week_number}-{year}" # Gib Kalenderwoche und Jahr im Format W-YYYY zurück
|
2024-10-16 20:48:05 +02:00
|
|
|
|
2024-10-16 21:15:23 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Datei Pfade
|
|
|
|
hr_data_path = '/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/raw/hr_gramic.csv'
|
2024-10-18 10:40:27 +02:00
|
|
|
sleep_data_path = '/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/sandbox/sleep_gramic.csv'
|
2024-10-18 09:59:08 +02:00
|
|
|
hr_clean_path = '/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/sandbox/hr_data_clean.csv'
|
|
|
|
sleep_clean_path = '/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/sandbox/sleep_data_clean.csv'
|
|
|
|
combined_data_path = '/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/sandbox/combined_data.csv'
|
2024-10-18 10:40:27 +02:00
|
|
|
graphic_corr_path = '/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/final/gramic_sleep_hr_correlation.png'
|
|
|
|
graphic_weekly_path = '/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/final/weekly_hr_sleep.png'
|
|
|
|
|
2024-10-16 20:48:05 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Schritt 1: Lade die HR-Daten (mit Semikolon separiert) und entferne 'bpm'
|
|
|
|
hr_data = pd.read_csv(hr_data_path, sep=';')
|
2024-10-17 20:42:54 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Entferne 'bpm' und konvertiere die Werte in numerische Daten
|
|
|
|
hr_data['In Ruhe'] = hr_data['In Ruhe'].str.replace(' bpm', '').astype(float)
|
|
|
|
hr_data['Hoch'] = hr_data['Hoch'].str.replace(' bpm', '').astype(float)
|
2024-10-17 20:42:54 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Konvertiere die Spalte 'Datum' in Kalenderwoche (KW und Jahr)
|
|
|
|
hr_data['Woche'] = hr_data['Datum'].apply(convert_to_week_and_year)
|
2024-10-17 20:42:54 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Berechne den Durchschnitt der Herzfrequenzdaten (In Ruhe und Hoch)
|
|
|
|
hr_data['avg_hr'] = hr_data[['In Ruhe', 'Hoch']].mean(axis=1)
|
2024-10-17 20:42:54 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Speichere nur die Spalten 'Woche' und 'avg_hr' in einer neuen CSV-Datei
|
|
|
|
hr_data_clean = hr_data[['Woche', 'avg_hr']]
|
|
|
|
hr_data_clean.to_csv(hr_clean_path, index=False)
|
2024-10-17 20:42:54 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Schritt 2: Lade die Schlafdaten (mit Komma separiert)
|
2024-10-18 10:40:27 +02:00
|
|
|
sleep_data = pd.read_csv(sleep_data_path, sep=';')
|
2024-10-17 20:42:54 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Konvertiere die Spalte 'Datum' in Kalenderwoche (KW und Jahr)
|
|
|
|
sleep_data['Woche'] = sleep_data['Datum'].apply(convert_to_week_and_year)
|
2024-10-17 20:42:54 +02:00
|
|
|
|
2024-10-18 10:40:27 +02:00
|
|
|
# Konvertiere die Spalte 'Durchschnittliche Dauer' in numerische Stunden
|
|
|
|
sleep_data['Durchschnittliche Dauer'] = sleep_data['Durchschnittliche Dauer'].apply(convert_sleep_duration)
|
|
|
|
|
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Speichere nur die Spalten 'Woche' und 'Durchschnittliche Dauer' in einer neuen CSV-Datei
|
|
|
|
sleep_data_clean = sleep_data[['Woche', 'Durchschnittliche Dauer']]
|
|
|
|
sleep_data_clean.to_csv(sleep_clean_path, index=False)
|
2024-10-16 20:48:05 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Schritt 3: Kombiniere die HR- und Schlafdaten basierend auf der 'Woche'
|
|
|
|
combined_data = pd.merge(hr_data_clean, sleep_data_clean, on='Woche', how='inner')
|
2024-10-16 21:15:23 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Speichere das kombinierte Dataset in einer neuen CSV-Datei
|
|
|
|
combined_data.to_csv(combined_data_path, index=False)
|
2024-10-16 20:48:05 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Schritt 4: Berechne die Korrelation zwischen avg_hr und der Schlafdauer
|
2024-10-16 20:48:05 +02:00
|
|
|
correlation = combined_data['avg_hr'].corr(combined_data['Durchschnittliche Dauer'])
|
2024-10-18 09:59:08 +02:00
|
|
|
print(f"Die Korrelation zwischen der durchschnittlichen Herzfrequenz und der Schlafdauer ist: {correlation}")
|
2024-10-16 21:15:23 +02:00
|
|
|
|
2024-10-18 09:59:08 +02:00
|
|
|
# Schritt 5: Visualisiere den Zusammenhang zwischen Herzfrequenz und Schlafdauer
|
2024-10-16 21:15:23 +02:00
|
|
|
plt.figure(figsize=(10, 6))
|
|
|
|
plt.scatter(combined_data['avg_hr'], combined_data['Durchschnittliche Dauer'], color='blue', label='Datenpunkte')
|
|
|
|
plt.title('Zusammenhang zwischen Herzfrequenz (Durchschnitt) und Schlafdauer')
|
|
|
|
plt.xlabel('Durchschnittliche Herzfrequenz (bpm)')
|
|
|
|
plt.ylabel('Schlafdauer (Stunden)')
|
|
|
|
plt.grid(True)
|
|
|
|
|
|
|
|
# Linie zur Visualisierung des Trends hinzufügen
|
|
|
|
m, b = np.polyfit(combined_data['avg_hr'], combined_data['Durchschnittliche Dauer'], 1)
|
|
|
|
plt.plot(combined_data['avg_hr'], m * combined_data['avg_hr'] + b, color='red',
|
|
|
|
label=f'Trendlinie (Kor = {correlation:.2f})')
|
|
|
|
|
|
|
|
plt.legend()
|
2024-10-18 10:40:27 +02:00
|
|
|
# Speichern der Grafik
|
|
|
|
plt.savefig(graphic_corr_path)
|
|
|
|
plt.show()
|
|
|
|
|
|
|
|
# Schritt 6: Erstelle eine Grafik pro Kalenderwoche (Herzfrequenz und Schlafdaten)
|
|
|
|
plt.figure(figsize=(12, 6))
|
|
|
|
|
|
|
|
# Plot für die Herzfrequenz
|
|
|
|
plt.bar(combined_data['Woche'], combined_data['avg_hr'], width=0.4, label='Durchschnittliche Herzfrequenz', align='center')
|
|
|
|
|
|
|
|
# Plot für die Schlafdauer (mit Verschiebung, um Überlappung zu vermeiden)
|
|
|
|
plt.bar(combined_data['Woche'], combined_data['Durchschnittliche Dauer'], width=0.4, label='Schlafdauer', align='edge')
|
|
|
|
|
|
|
|
# Diagrammtitel und Achsenbeschriftungen
|
|
|
|
plt.title('Durchschnittliche Herzfrequenz und Schlafdauer pro Kalenderwoche')
|
|
|
|
plt.xlabel('Kalenderwoche')
|
|
|
|
plt.ylabel('Wert')
|
|
|
|
|
|
|
|
# Legende und Rotation der x-Achse
|
|
|
|
plt.legend()
|
|
|
|
plt.xticks(rotation=45, ha='right')
|
|
|
|
|
|
|
|
# Speichern der zweiten Grafik
|
|
|
|
plt.savefig(graphic_weekly_path)
|
2024-10-16 21:15:23 +02:00
|
|
|
plt.show()
|