### Import der benötigten Bibliotheken # pip3 install pandas ... import pandas as pd # für a) import sys # für b) import numpy as np # für b) import matplotlib.pyplot as plt # für d) import scipy as sp # für e) from scipy import stats # für e) ### a) Einlesen der Quelldaten # Pandas-Methode read_csv() zum Einlesen nutzen, wobei die Spalte namens "id" ausgelassen wird gewuenschteSpalten = ["battery_power", "bluetooth", "dual_sim", "4G", "int_memory", "ram"] df = pd.read_csv('mobile_device_data.csv', usecols=gewuenschteSpalten) # Print inkl. Dataframe-Methode head() aufrufen # Parameter n: Ausgabe der ersten 12 Zeilen (Zeile 0 bis 11 = 12 Zeilen) print(df.head(n=12)) # Ausgabe: # battery_power bluetooth dual_sim 4G int_memory ram # 0 1043 1.0 1 0 5 3476 # ... ... ... ... ... ... ... # 11 1343 0.0 0 1 34 3911 ### b) Bereinigen # Dataframe enthält verschiedene Arten nicht auswertbarer Zellen: # 1. Zellen in denen vorher schon NaN (NotANumber) steht # 2. Zellen, in denen ein leerer String steht (' ') # -> umwandeln von (' ') in "NaN", per DataFrame-Methode replace() df.replace(to_replace=' ', value=np.nan, inplace=True) # 1. und 2. lassen sich jetzt auf die gleiche Weise wie folgt ausgeben, # und es werden 4 Zeilen gefunden, in denen das Bluetooth Feld "NaN" ist, # und insgesamt 6 Zeilen, in denen das 4G, int_memory und ram Feld "NaN" sind: # print(df.isna().sum()) # Ausgabe: # battery_power 0 # bluetooth 4 # dual_sim 0 # 4G 2 # int_memory 2 # ram 2 # Dataframe-Methode "dropna" aufrufen, um solche Einträge zu löschen: # Parameter axis=0 : Zeile wird gelöscht # Parameter how='any' : Zum Löschen genügt eine einzelne leere Zelle # Parameter inplace=True : Die Operation wird direkt auf das DataFrame angewendet df.dropna(axis=0, how='any', inplace=True) # Nach dieser Änderung sind nur noch 200 Zeilen im DataFrame if (len(df.index) != 200): print("Es sind zu viele Zeilen im DataFrame") sys.exit() print("Anzahl der Zeilen:", len(df.index)) # Ausgabe: # 200 ### c) Univariate Analyse # Die Datentypen der gewünschten Merkmale werden nicht von vornherein alle als Ganzzahlen (Integer) # interpretiert (vgl. print(df.info()) ), daher erst in solche umwandeln. # Wenn man das nicht macht, kann .describe() nicht ordentlich mit gemischten Spaltentypen umgehen. # Die Beispielausgabe wäre sonst: "mean 1264.560000 NaN NaN" dfMetrischeMerkmale = df[["battery_power", "int_memory", "ram"]].astype(int) dfUnivariateAnalyse = dfMetrischeMerkmale[["battery_power", "int_memory", "ram"]].describe(include='all', percentiles=[0.2, 0.5, 0.8]) dfUnivariateAnalyse.to_csv('UnivariateAnalyse.csv') # Ausgabe: # battery_power int_memory ram # count 200.000000 200.000000 200.000000 # mean 1264.560000 33.485000 2153.125000 # std 441.550223 17.795595 1140.426372 # min 504.000000 2.000000 263.000000 # 20% 857.600000 16.000000 870.800000 # 50% 1249.500000 33.000000 2172.500000 # 80% 1721.400000 51.000000 3317.600000 # max 1999.000000 64.000000 3976.000000 ### d) Balkendiagramme # Arbeitstabelle erzeugen, die nur die Spalten der nominalen Merkmale enthält: dfNominaleMerkmale = df[["bluetooth", "dual_sim", "4G"]] # Die Merkmalsausprägungen je Merkmal zählen (0=No, 1=Yes) # + benötigte Typenumwandlungen zu Ganzzahlen (0.0-> 0, 1.0-> 1) per .astype(int) srBluetoothAnzahl = df["bluetooth"].astype(int).value_counts() srDualSimAnzahl = df["dual_sim"].astype(int).value_counts() sr4gAnzahl = df["4G"].astype(int).value_counts() dfAnzahlen = pd.concat([srBluetoothAnzahl, srDualSimAnzahl, sr4gAnzahl], axis=1); dfAnzahlen.plot.bar(xlabel="0=No, 1=Yes") plt.show() ### e) Korrellationen nach Pearson und Lineare Regression zweier Merkmale print(dfMetrischeMerkmale.corr(method="pearson")) # Ausgabe: # battery_power int_memory ram # battery_power 1.000000 0.050449 -0.069141 # int_memory 0.050449 1.000000 0.047475 # ram -0.069141 0.047475 1.000000 # -> ram und battery_power korrelieren am Stärksten, wenn auch negativ: # Per Modul SciPy Stats: Methode der kleinsten Quadrate für die Lineare Regression nutzen werteListeX = dfMetrischeMerkmale["ram"] werteListeY = dfMetrischeMerkmale["battery_power"] modell = sp.stats.linregress(werteListeX, werteListeY) steigung = round(modell.slope, 4) yAchsAbschn = round(modell.intercept, 4) arrYpredicted = steigung * werteListeX + yAchsAbschn # using y = m*x + n, calculate every single Y-Value fitting the regression Lines X-Values #print("Regressionsgleichung:", "y =", steigung, "* x +", yAchsAbschn) # Linear Regressions Linie plotten plt.clf() # Letzte Plot Grafik löschen plt.xlabel('ram', color='black') plt.ylabel('battery_power', color='black') plt.scatter(werteListeX, werteListeY) plt.plot(werteListeX, arrYpredicted, label='Lin Regression', color='red', linestyle='solid') # https://scriptverse.academy/tutorials/python-matplotlib-plot-straight-line.html # Show Plot Image plt.show() ### f) Skalierung in [0, 1] # Je metrischem Merkmal eine Zusatzspalte erzeugen, die deren Werte in das Intervall [0,1] skaliert: dfMetrischeMerkmale["battery_power_skaliert"] = dfMetrischeMerkmale["battery_power"] / dfMetrischeMerkmale["battery_power"].max() dfMetrischeMerkmale["int_memory_skaliert"] = dfMetrischeMerkmale["int_memory"] / dfMetrischeMerkmale["int_memory"].max() dfMetrischeMerkmale["ram_skaliert"] = dfMetrischeMerkmale["ram"] / dfMetrischeMerkmale["ram"].max() # print(dfMetrischeMerkmale) # battery_power int_memory ... int_memory_skaliert ram_skaliert # 0 1043 5 ... 0.078125 0.874245 # 1 841 61 ... 0.953125 0.979628 # 2 1807 27 ... 0.421875 0.602616 # ... ### g) Boxplots # Boxplots je metrischem Merkmal mit matplotlib erstellen fig, (ax1 , ax2, ax3) = plt.subplots(1,3, figsize=(10, 5)) # (1,3) = 1 Zeile, 3 Spalten ax1.set_title("Battery") # Subplot 1 Titel ax2.set_title("Ram") ax3.set_title("Memory") dfMetrischeMerkmale["battery_power"].plot(ax=ax1, kind="box", grid=True, showfliers=True, whis=[5, 95]) dfMetrischeMerkmale["ram"].plot(ax=ax2, kind="box", grid=True, showfliers=True, whis=[5, 95]) dfMetrischeMerkmale["int_memory"].plot(ax=ax3, kind="box", grid=True, showfliers=True, whis=[5, 95]) plt.show()