Daten laden, kombinieren und prüfen#
Mit pandas können Daten aus verschiedenen Dateiformaten eingelesen und kombiniert werden. Zusätzlich wollen wir uns ansehen, wie eine erste Qualitätsprüfung der Daten durchgeführt werden kann.
Wir nutzen für die folgenden Übungen Teile eines Datensatzes mit Nachrichtenartikeln, veröffentlicht von:
Misra, Rishabh. “News Category Dataset.” arXiv preprint arXiv:2209.11429 (2022).
Misra, Rishabh and Jigyasa Grover. “Sculpting Data for ML: The first act of Machine Learning.” ISBN 9798585463570 (2021).
Lizenz: CC-BY 4.0
Kaggle: https://www.kaggle.com/datasets/rmisra/news-category-dataset
# pandas importieren
import pandas as pd
# Import und Initialisierung von bia-bob
from bia_bob import bob
# API Key wird aus condas Umgebungsvariable gelesen
bob.initialize(endpoint='blablador', model='alias-fast')
Daten aus einer Datei laden#
Schauen wir uns zunächst an, wie Daten aus einer JSON-Datei geladen werden. Hierfür nutzen wir read_json()
. Der damit erstellte DataFrame wird in der Variable df1
gespeichert.
df1 = pd.read_json('../data/news_category_data_2020.json', lines=True)
Wir können unseren KI-Assistenten nutzen, um zunächst einen kurzen Überblick über die Daten zu bekommen.
%%bob
Beschreibe mir kurz den Inhalt und die Spalten des DataFrame df1 mit {df1.columns} und {df1.index}.
KEIN Code, antworte in Deutsch
Die Daten enthalten Bemeldungen aus verschiedenen Kategorien. Jede Zeile des Datensatzes stellt eine einzelne Meldung dar, die durch einen Link auf eine Webseite referenziert wird. Hier sind die Spalten und deren Inhalte im Detail:
headline
: Diese Spalte enthält den Titel der Meldung.category
: Diese Spalte gibt die Kategorie der Meldung an, z.B. POLITIK, COMEDY, ENTERTAINMENT, WORLD NEWS, U.S. NEWS, WELLNESS.short_description
: Diese Spalte gibt eine kurze Beschreibung der Meldung.authors
: Diese Spalte gibt die Autoren der Meldung an.date
: Diese Spalte gibt das Datum der Meldung an.
Die Spalten sind alle als string
oder datetime
definiert.
Lass dir mit den aus der vorhergehenden Übung bekannten Methoden des DataFrame weitere detaillierte Infos zum Datensatz anzeigen
# Ausgabe der Metadaten
# Ausgabe der ersten n Zeilen
# Ausgabe beschreibender Statistiken für alle Spalten mit Datentyp "object"
# Ausgabe der vorhandenen Kategorien in der Spalte "category"
Zusammenführen von DataFrames#
Oft müssen Daten für eine Analyse aus verschiedenen Datenquellen zusammengeführt werden. pandas unterstützt das Zusammenführen von DataFrames durch verschiedene Methoden. Siehe dazu auch den entsprechenden User Guide: Merge, Join, Concatenate.
Wir wollen uns das am Beispiel zwei weiterer Datensätze in teils unterschiedlichen Formaten ansehen, die wir hierzu laden.
Beginnen wir mit dem Datensatz /data/news_category_data_2021.json
.
df2 = pd.read_json('../data/news_category_data_2021.json', lines=True)
# Ausgabe der Metadaten
df2.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2066 entries, 0 to 2065
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 link 2066 non-null object
1 headline 2066 non-null object
2 category 2066 non-null object
3 short_description 2066 non-null object
4 authors 2066 non-null object
5 date 2066 non-null datetime64[ns]
dtypes: datetime64[ns](1), object(5)
memory usage: 97.0+ KB
Der Datensatz für 2021 scheint das gleiche Format (Spaltennamen, Datentypen) zu haben, wie der vorhergehende.
Hier bietet sich concat()
für ein einfaches Aneinanderfügen an.
df12 = pd.concat([df1, df2])
# Ausgabe der Metadaten
df12.info()
<class 'pandas.core.frame.DataFrame'>
Index: 4120 entries, 0 to 2065
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 link 4120 non-null object
1 headline 4120 non-null object
2 category 4120 non-null object
3 short_description 4120 non-null object
4 authors 4120 non-null object
5 date 4120 non-null datetime64[ns]
dtypes: datetime64[ns](1), object(5)
memory usage: 225.3+ KB
# Überprüfen des Index auf Duplikate (soll keine Duplikate enthalten)
df12.index.duplicated().any()
True
Sehen wir uns jetzt den dritten Datensatz an: /data/news_category_data_2022.csv
. Dieser liegt im Dateiformat CSV vor und kann mit read_csv()
eingelesen werden.
df3 = pd.read_csv('../data/news_category_data_2022.csv', sep='|')
# Ausgabe der Metadaten
df3.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1398 entries, 0 to 1397
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 link 1398 non-null object
1 headline 1398 non-null object
2 category 1398 non-null object
3 description 1398 non-null object
4 authors 1258 non-null object
5 date 1398 non-null object
dtypes: object(6)
memory usage: 65.7+ KB
Hier zeigen sich folgende Unterschiede / Problempunkte:
Eine Spalte ist anders bezeichnet
Der Datentyp in
date
ist ein andererEs scheinen einige Einträge bei
authors
zu fehlen (dazu später mehr)
pd.concat([df12, df3]).info()
<class 'pandas.core.frame.DataFrame'>
Index: 5518 entries, 0 to 1397
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 link 5518 non-null object
1 headline 5518 non-null object
2 category 5518 non-null object
3 short_description 4120 non-null object
4 authors 5378 non-null object
5 date 5518 non-null object
6 description 1398 non-null object
dtypes: object(7)
memory usage: 344.9+ KB
Bei einem einfachen concat()
werden beide Spalten mit unterschiedlichem Namen behalten, diese beinhalten dann entsprechend viele Fehlwerte. Zudem wurde der Datentyp in date
jetzt zu dem allgemeinen Typ object
zusammengefasst.
Es bietet sich daher vor den Zusammenfügen an in df3
…die Spalte
description
inshort_description
umzunennen…den Datentyp der Spalte
date
indatetime64
umzuwandeln
Lass dir hier vom KI-Assistenten helfen
%%bob
Mit dem angepassten dritten Datensatz können jetzt alle Daten zusammengeführt werden. Überprüfe das Ergebnis.
# df_all = pd.concat(...)
Speichere den aktuellen DataFrame als Zwischenergebnis als CSV unter ../data/news_category_data_all.csv
# df_all.to_csv(...)
Prüfen und Bereinigen#
Daten haben oftmals nicht die für eine Analyse notwendige Qualität. Dies betrifft in unserem Fall fehlende Werte in den Daten. Bei numerischen Daten kommen häufig noch Ausreißer dazu.
Wir wollen uns für diesen Datensatz einmal den Punkt Fehlwerte anschauen - also Einträge, die entweder Null oder ein leerer String sind. pandas bietet umfassende Möglichkeiten, Fehlwerte zu erkennen und mit ihnen umzugehen, siehe dazu auch User Guide: Working with missing data
Wir laden uns zunächst das Zwischenergebnis aus /data/news_category_data_all.csv
und sehen uns die Metadaten sowie die Zeilen 20 bis 30 an.
df_all = pd.read_csv('../data/news_category_data_all.csv', sep='|', parse_dates=[5])
df_all.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5518 entries, 0 to 5517
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 link 5518 non-null object
1 headline 5518 non-null object
2 category 5518 non-null object
3 short_description 5518 non-null object
4 authors 5061 non-null object
5 date 5518 non-null datetime64[ns]
dtypes: datetime64[ns](1), object(5)
memory usage: 258.8+ KB
df_all.iloc[20:31]
link | headline | category | short_description | authors | date | |
---|---|---|---|---|---|---|
20 | https://www.huffpost.com/entry/trump-dc-hotel-... | Trump's D.C. Hotel Appears To Concede Election... | POLITICS | The Trump International Hotel in Washington, D... | David Moye | 2020-12-28 |
21 | https://www.huffpost.com/entry/best-buys-from-... | The 20 Finds That Helped Our Shopping Editors ... | HOME & LIVING | Including a meal kit for lunch during the work... | Ambar Pardilla | 2020-12-28 |
22 | https://www.huffpost.com/entry/anthony-quinn-w... | Nashville Bombing Suspect Told Neighbor: The W... | CRIME | Anthony Quinn Werner reportedly made the chill... | Kimberlee Kruesi, Michael Balsamo and Michael ... | 2020-12-28 |
23 | https://www.huffpost.com/entry/tony-rice-blueg... | Tony Rice, Master Bluegrass Guitarist, Dies At 69 | ENTERTAINMENT | His last live guitar performance was in 2013, ... | NaN | 2020-12-28 |
24 | https://www.huffpost.com/entry/european-union-... | European Union Kicks Off COVID-19 Vaccine Camp... | WORLD NEWS | The 27-nation bloc began administering the fir... | Nicole Winfield and Vanessa Gera, AP | 2020-12-27 |
25 | https://www.huffpost.com/entry/the-best-books-... | The Best Books Of 2020 | CULTURE & ARTS | The 10 reads -- from Emily St. John Mandel, Ra... | Claire Fallon | 2020-12-27 |
26 | https://www.huffpost.com/entry/dan-rather-dona... | Dan Rather Rips 'Abject Cruelty' Of Trump's 'M... | POLITICS | The president, relaxing at Mar-a-Lago, left "d... | Mary Papenfuss | 2020-12-27 |
27 | https://www.huffpost.com/entry/rockford-illino... | Illinois Bowling Alley Shooting Leaves 3 Dead,... | CRIME | A 37-year-old male suspect was in custody afte... | NaN | 2020-12-27 |
28 | https://www.huffpost.com/entry/nashville-polic... | Nashville Police Believe Man Responsible For C... | CRIME | Investigators linked Anthony Quinn Warner, 63,... | Sanjana Karanth | 2020-12-27 |
29 | https://www.huffpost.com/entry/bernie-sanders-... | Bernie Sanders: Trump Needs To Stop 'Diddling ... | POLITICS | "We may be looking at a government shutdown in... | Jeremy Blum | 2020-12-27 |
30 | https://www.huffpost.com/entry/andrew-kacynski... | CNN's Andrew Kaczynski Mourns Death Of Baby Da... | U.S. NEWS | “We’re heartbroken to have to announce our bea... | Mary Papenfuss | 2020-12-26 |
Wie wir sehen, gibt es Zeilen, die NaNs enthalten - die von pandas genutzte Representation von Fehlwerten. Eine Überprüfung, ob irgendwo in einem DataFrame NaNs enthalten sind, ist eine wichtige erste Qualitätsprüfung vor jeder Datenanalyse. Pandas’ isna()
bietet hierfür eine boolesche Maskierung des DataFrame mit True / False Werten, wobei True ein NaN anzeigt.
df_all.isna().iloc[20:31]
link | headline | category | short_description | authors | date | |
---|---|---|---|---|---|---|
20 | False | False | False | False | False | False |
21 | False | False | False | False | False | False |
22 | False | False | False | False | False | False |
23 | False | False | False | False | True | False |
24 | False | False | False | False | False | False |
25 | False | False | False | False | False | False |
26 | False | False | False | False | False | False |
27 | False | False | False | False | True | False |
28 | False | False | False | False | False | False |
29 | False | False | False | False | False | False |
30 | False | False | False | False | False | False |
Mit dieser booleschen Maskierung können wir weitere Analysen zu Fehlwerten durchführen. Und da True / False auch als 1 / 0 interpretiert wird, können wir damit auch rechnen.
# Ausgeben, ob Fehlwerte enthalten sind
df_all.isna().values.any()
True
# Spaltenweises Zählen der NaN
df_all.isna().sum()
link 0
headline 0
category 0
short_description 0
authors 457
date 0
dtype: int64
Nutze den KI-Assistenten, um dir eine Liste der Indizes aller Zeilen mit NaN zu erstellen
%%bob
Es gibt mehrere Wege, mit Fehlwerten umzugehen. Diese können insbesondere bei numerischen Daten z.b. durch Interpolation oder Einsetzen eines Mittelwertes aufgefüllt werden. Bei diesen Ansätzen sollte aber immer beachtet werden, dass ein Auffüllen fehlender Werte den Datensatz und seine statistischen Eingenschaften verzerren kann. Im Gegensatz dazu können Einträge mit Fehlwerten auch einfach aus dem Datensatz entfernt werden, insofern dieser dann für die weitere Analyse nicht zu stark augedünnt wird.
In unseren Fall lassen wir pandas mittels dropna()
einfach alle Zeilen aus dem Datensatz entfernen, welche ein NaN enthalten, und speichern das Ergebnis als CSV unter /data/news_category_data_prep.csv
.
# df_all.dropna(...)
# ...