249 lines
11 KiB
Python
249 lines
11 KiB
Python
import pandas as pd
|
|
import matplotlib.pyplot as plt
|
|
import numpy as np
|
|
from datetime import datetime
|
|
import os
|
|
|
|
# Manuelle Zuordnung der Monatsnamen von Deutsch auf Englisch
|
|
# month_translation = {
|
|
# 'Jan': 'Jan', 'Feb': 'Feb', 'Mär': 'Mar', 'Apr': 'Apr', 'Mai': 'May', 'Jun': 'Jun',
|
|
# 'Jul': 'Jul', 'Aug': 'Aug', 'Sep': 'Sep', 'Okt': 'Oct', 'Nov': 'Nov', 'Dez': 'Dec', 'Mrz': 'Mar'
|
|
# }
|
|
|
|
|
|
# Funktion, um 'Okt 10-16' in eine Kalenderwoche zu konvertieren und das Startdatum zurückzugeben
|
|
# def convert_to_week_number_and_start_date(date_range_str):
|
|
# # Splitte den Datumsbereich in Monat und Tage
|
|
# start_part, end_part = date_range_str.split(" - ")
|
|
# start_month_str, start_day = start_part.split(" ")
|
|
# start_day = int(start_day) # Nimm den Starttag
|
|
#
|
|
# # Konvertiere den deutschen Monatsnamen in den englischen
|
|
# if start_month_str in month_translation:
|
|
# start_month_str = month_translation[start_month_str]
|
|
#
|
|
# # Erstelle das Datum basierend auf dem Starttag und dem aktuellen Jahr
|
|
# current_year = datetime.now().year
|
|
# date_str = f"{start_month_str} {start_day} {current_year}"
|
|
#
|
|
# try:
|
|
# start_date = datetime.strptime(date_str, "%b %d %Y") # Konvertiere in ein Datum
|
|
# except ValueError:
|
|
# raise ValueError(f"Ungültiges Datum: {date_str}")
|
|
#
|
|
# week_number = start_date.isocalendar()[1] # Kalenderwoche ermitteln
|
|
#
|
|
# return week_number, start_date.strftime('%Y-%m-%d') # Gib KW und das Startdatum zurück
|
|
# Funktion, um 'Okt 10-16' oder 'Okt 10 - 16' in eine Kalenderwoche zu konvertieren und das Startdatum zurückzugeben
|
|
# def convert_to_week_number_and_start_date(date_range_str):
|
|
# # Entferne zusätzliche Leerzeichen um den Bindestrich herum
|
|
# date_range_str = date_range_str.replace(" - ", "-")
|
|
#
|
|
# # Splitte den Datumsbereich in Start- und Endbereich
|
|
# start_part, end_part = date_range_str.split("-")
|
|
# start_month_str, start_day = start_part.split(" ")
|
|
# start_day = int(start_day.strip()) # Nimm den Starttag und entferne etwaige Leerzeichen
|
|
#
|
|
# # Konvertiere den deutschen Monatsnamen in den englischen
|
|
# if start_month_str in month_translation:
|
|
# start_month_str = month_translation[start_month_str]
|
|
#
|
|
# # Erstelle das Datum basierend auf dem Starttag und dem aktuellen Jahr
|
|
# current_year = datetime.now().year
|
|
# date_str = f"{start_month_str} {start_day} {current_year}"
|
|
#
|
|
# try:
|
|
# start_date = datetime.strptime(date_str, "%b %d %Y") # Konvertiere in ein Datum
|
|
# except ValueError:
|
|
# raise ValueError(f"Ungültiges Datum: {date_str}")
|
|
#
|
|
# week_number = start_date.isocalendar()[1] # Kalenderwoche ermitteln
|
|
#
|
|
# return week_number, start_date.strftime('%Y-%m-%d') # Gib KW und das Startdatum zurück
|
|
|
|
# Funktion, um Datumsbereiche wie 'Mrz 29-Apr 4' oder 'Okt 10-16' in die Kalenderwoche zu konvertieren
|
|
# und das Startdatum zurückzugeben
|
|
# Funktion, um Datumsbereiche wie 'Mrz 29-Apr 4' oder 'Okt 10-16' in die Kalenderwoche zu konvertieren
|
|
# und das Startdatum zurückzugeben
|
|
# def convert_to_week_number_and_start_date(date_range_str):
|
|
# # Entferne zusätzliche Leerzeichen um den Bindestrich herum
|
|
# date_range_str = date_range_str.replace(" - ", "-")
|
|
#
|
|
# # Splitte den Datumsbereich in Start- und Endteil
|
|
# start_part, end_part = date_range_str.split("-")
|
|
#
|
|
# # Verarbeite den Startteil
|
|
# start_month_str, start_day = start_part.split(" ")
|
|
# start_day = int(start_day.strip()) # Nimm den Starttag und entferne etwaige Leerzeichen
|
|
#
|
|
# # Wenn der Endteil einen Monat enthält, verarbeite ihn ebenfalls
|
|
# if " " in end_part:
|
|
# end_month_str, end_day = end_part.split(" ")
|
|
# end_day = int(end_day.strip()) # Nimm den Endtag
|
|
# else:
|
|
# # Wenn der Endteil keinen Monat enthält, verwenden wir denselben Monat wie im Startteil
|
|
# end_month_str = start_month_str
|
|
# end_day = int(end_part.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]
|
|
#
|
|
# # Erstelle das Datum basierend auf dem Starttag und dem aktuellen Jahr
|
|
# current_year = datetime.now().year
|
|
# start_date_str = f"{start_month_str} {start_day} {current_year}"
|
|
#
|
|
# try:
|
|
# # Konvertiere in ein Datum
|
|
# start_date = datetime.strptime(start_date_str, "%b %d %Y")
|
|
# except ValueError:
|
|
# raise ValueError(f"Ungültiges Startdatum: {start_date_str}")
|
|
#
|
|
# # Berechne die Kalenderwoche basierend auf dem Startdatum
|
|
# week_number = start_date.isocalendar()[1]
|
|
#
|
|
# return week_number, start_date.strftime('%Y-%m-%d') # Gib KW und das Startdatum zurück
|
|
# Manuelle Zuordnung der Monatsnamen von Deutsch auf Englisch
|
|
month_translation = {
|
|
'Jan': 'Jan', 'Feb': 'Feb', 'Mär': 'Mar', 'Mrz': 'Mar', 'Apr': 'Apr', 'Mai': 'May', 'Jun': 'Jun',
|
|
'Jul': 'Jul', 'Aug': 'Aug', 'Sep': 'Sep', 'Okt': 'Oct', 'Nov': 'Nov', 'Dez': 'Dec'
|
|
}
|
|
|
|
|
|
# Funktion, um Datumsbereiche wie 'Mrz 29-Apr 4' oder 'Dez 29, 2023-Jan 4, 2024' in die Kalenderwoche und das Startdatum zu konvertieren
|
|
def convert_to_week_number_and_start_date(date_range_str):
|
|
# Entferne zusätzliche Leerzeichen um den Bindestrich herum
|
|
date_range_str = date_range_str.replace(" - ", "-").replace(",", "")
|
|
|
|
# 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(" ")
|
|
|
|
if len(end_parts) == 2:
|
|
end_month_str = end_parts[0]
|
|
end_day = int(end_parts[1].strip()) # Nimm den Endtag
|
|
else:
|
|
end_month_str = start_month_str # Falls kein Monat angegeben, setze den Startmonat
|
|
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]
|
|
|
|
# Wenn der Startteil ein Jahr enthält, nutze dieses
|
|
if len(start_parts) == 3:
|
|
current_year = int(start_parts[2])
|
|
else:
|
|
current_year = datetime.now().year
|
|
|
|
# Wenn der Datumsbereich über den Dezember hinausgeht, endet das Enddatum im nächsten Jahr
|
|
if start_month_str == 'Dec' and end_month_str == 'Jan':
|
|
end_year = current_year + 1
|
|
else:
|
|
end_year = current_year
|
|
|
|
try:
|
|
# Konvertiere das Startdatum in ein Datum
|
|
start_date = datetime.strptime(f"{start_month_str} {start_day} {current_year}", "%b %d %Y")
|
|
except ValueError:
|
|
raise ValueError(f"Ungültiges Startdatum: {start_month_str} {start_day} {current_year}")
|
|
|
|
try:
|
|
# Konvertiere das Enddatum in ein Datum
|
|
end_date = datetime.strptime(f"{end_month_str} {end_day} {end_year}", "%b %d %Y")
|
|
except ValueError:
|
|
raise ValueError(f"Ungültiges Enddatum: {end_month_str} {end_day} {end_year}")
|
|
|
|
# Berechne die Kalenderwoche basierend auf dem Startdatum
|
|
week_number = start_date.isocalendar()[1]
|
|
|
|
return week_number, start_date.strftime('%Y-%m-%d') # Gib KW und das Startdatum zurück
|
|
|
|
|
|
# Funktion zum Bereinigen und Zwischenspeichern der Daten
|
|
def clean_and_save_data(hr_data, sleep_data, output_dir='sandbox'):
|
|
# 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)
|
|
|
|
# Konvertiere die Spalte 'Datum' in Kalenderwoche (KW) und Startdatum
|
|
hr_data[['week', 'start_date']] = hr_data['Datum'].apply(
|
|
lambda x: pd.Series(convert_to_week_number_and_start_date(x)))
|
|
|
|
# Berechne den Durchschnitt der Herzfrequenzdaten (In Ruhe und Hoch)
|
|
hr_data['avg_hr'] = hr_data[['In Ruhe', 'Hoch']].mean(axis=1)
|
|
|
|
# Konvertiere auch das 'Datum' der Schlafdaten in Kalenderwoche (KW) und Startdatum
|
|
sleep_data[['week', 'start_date']] = sleep_data['Datum'].apply(
|
|
lambda x: pd.Series(convert_to_week_number_and_start_date(x)))
|
|
|
|
# Speichere die bereinigten Daten in 'sandbox'
|
|
if not os.path.exists(output_dir):
|
|
os.makedirs(output_dir)
|
|
|
|
hr_data_clean_path = os.path.join(output_dir, 'hr_data_clean.csv')
|
|
sleep_data_clean_path = os.path.join(output_dir, 'sleep_data_clean.csv')
|
|
|
|
hr_data.to_csv(hr_data_clean_path, sep=';', index=False)
|
|
sleep_data.to_csv(sleep_data_clean_path, sep=',', index=False)
|
|
|
|
print(f"HR-Daten wurden bereinigt und in {hr_data_clean_path} gespeichert.")
|
|
print(f"Schlafdaten wurden bereinigt und in {sleep_data_clean_path} gespeichert.")
|
|
|
|
return hr_data, sleep_data
|
|
|
|
|
|
# Schritt 1: Lade die HR- und Schlafdaten
|
|
hr_data = pd.read_csv('/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/raw/hr_gramic.csv',
|
|
sep=';')
|
|
sleep_data = pd.read_csv('/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/raw/sleep_gramic.csv',
|
|
sep=',')
|
|
|
|
# Bereinige und speichere die Daten
|
|
hr_data, sleep_data = clean_and_save_data(hr_data, sleep_data)
|
|
|
|
# Schritt 2: Sortiere beide Datensätze nach 'week' und 'start_date'
|
|
hr_data = hr_data.sort_values(by=['week', 'start_date'])
|
|
sleep_data = sleep_data.sort_values(by=['week', 'start_date'])
|
|
|
|
# Schritt 3: Kombiniere die beiden Datensätze anhand der 'week' und 'start_date' Spalten mit einem äußeren Join
|
|
combined_data = pd.merge(hr_data, sleep_data, on=['week', 'start_date'], how='outer')
|
|
|
|
# Zeige die kombinierten Daten
|
|
print("\nKombinierte Daten:")
|
|
print(combined_data)
|
|
|
|
# Schritt 4: Entferne alle Zeilen mit fehlenden Daten
|
|
combined_data = combined_data.dropna()
|
|
|
|
# Schritt 5: Berechne die Korrelation zwischen 'avg_hr' und 'Durchschnittliche Dauer'
|
|
correlation = combined_data['avg_hr'].corr(combined_data['Durchschnittliche Dauer'])
|
|
print(f"\nDie Korrelation zwischen der durchschnittlichen Herzfrequenz und der Schlafdauer ist: {correlation}")
|
|
|
|
# Schritt 6: Visualisiere den Zusammenhang zwischen Herzfrequenz und Schlafdauer
|
|
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()
|
|
plt.show()
|