Dateien lesen und schreiben
All die starken Daten-Strukturen wie Series und DataFrames würden fast nichts nützen, wenn das Pandas-Modul keine Funktionalitäten unterstützen würde, um Daten einzulesen und rauszuschreiben. Dabei geht es nicht um die einfache Möglichkeit mit Dateien umzugehen. Damit der Nutzen für Data-Scientists sichtbar wird, müssen die wichtigsten Daten-Formate unterstützt werden, wie z.B.:
- Trenner-Separierte Dateien, z.B. csv
- Microsoft Excel Dateien
- HTML
- XML
- JSON
Trennerseparierte Werte
Die meisten Menschen verwenden den Namen "CSV-Datei" als Synonym für eine trennerseparierte-Datei. Sie beachten nicht die Tatsache, das CSV ein Akronym ist für "comma separated values" (also in Deutsch "kommaseparierte-Liste"), was in den meisten Situationen nicht der Fall ist. Pandas verwendet "csv" ebenfalls in Zusammenhängen, in denen "dsv" die passendere Bezeichnung wäre.
Trennerseparierte Werte (Delimiter-separated values - DSV) sind definiert und abgelegt in zweidimensionalen Arrays, bei denen die Werte mit zweckmäßig definierten Trennzeichen in jeder Zeile getrennt sind. Diese Arte und Weise wird oft in Kombination mit Tabellenprogrammen eingesetzt, die Daten als DSV ein- und auslesen können. Auch wird die Implementierung in allgemeinen Datenaustauschformaten verwendet.
Bei der Datei dollar_euro.txt handelt es sich um eine DSV-Datei, die Tabulatoren (\t) als Trennzeichen benutzt.
CSV- und DSV-Dateien lesen
Pandas bietet zwei Wege, um CSV/DSV Dateien zu lesen. Das bedeutet konkret:
- DataFrame.from_csv
- read_csv
Es gibt zwischen beiden Methoden keinen großen Unterschied, d.h. es gibt in manchen Fällen verschiedene Default-Werte, und read_csv
hat mehr Parameter.
Wir konzentrieren uns auf read_csv
, weil DataFrame.from_csv
nur wegen Auf- und Abwärtskompatibilität innerhalb von Pandas gehalten wird.
import pandas as pd exchange_rates = pd.read_csv("data1/dollar_euro.txt", sep="\t") print(exchange_rates)
Year Average Min USD/EUR Max USD/EUR Working days 0 2016 0.901696 0.864379 0.959785 247 1 2015 0.901896 0.830358 0.947688 256 2 2014 0.753941 0.716692 0.823655 255 3 2013 0.753234 0.723903 0.783208 255 4 2012 0.778848 0.743273 0.827198 256 5 2011 0.719219 0.671953 0.775855 257 6 2010 0.755883 0.686672 0.837381 258 7 2009 0.718968 0.661376 0.796495 256 8 2008 0.683499 0.625391 0.802568 256 9 2007 0.730754 0.672314 0.775615 255 10 2006 0.797153 0.750131 0.845594 255 11 2005 0.805097 0.740357 0.857118 257 12 2004 0.804828 0.733514 0.847314 259 13 2003 0.885766 0.791766 0.963670 255 14 2002 1.060945 0.953562 1.165773 255 15 2001 1.117587 1.047669 1.192748 255 16 2000 1.085899 0.962649 1.211827 255 17 1999 0.939475 0.848176 0.998502 261
Wie wir gesehen haben, benutzt read_csv
automatisch die erste Zeile als Überschriften bzw. Spaltennamen für die Spalten.
Wir können den Spalten auch beliebige andere Namen geben. Dazu muss die erste Zeile übersprungen werden, was wir dadurch erreichen, dass wir den Parameter header
auf 0
setzen, und eine Liste mit Spalten-Namen an den Parameter names
zuweisen:
import pandas as pd exchange_rates = pd.read_csv("data1/dollar_euro.txt", sep="\t", header=0, names=["year", "min", "max", "days"]) print(exchange_rates.head())
year min max days 2016 0.901696 0.864379 0.959785 247 2015 0.901896 0.830358 0.947688 256 2014 0.753941 0.716692 0.823655 255 2013 0.753234 0.723903 0.783208 255 2012 0.778848 0.743273 0.827198 256
Schreiben von CSV-Dateien
CSV-Dateien können wir mit der Methode to_csv
schreiben. Wir werden dies an einem Beispiel demonstrieren. Zuerst erzeugen wir jedoch Daten, die wir dann rausschreiben werden. Im Verzeichnis data1
liegen die beiden Dateien countries_male_population.csv und countries_female_population.csv, die entsprechend die Zahlen der männlichen und weiblichen Bevölkerungs von Ländern enthalten.
column_names = ["Country"] + list(range(2003, 2013)) male_pop = pd.read_csv("data1/countries_male_population.csv", header=None, index_col=0, names=column_names) female_pop = pd.read_csv("data1/countries_female_population.csv", header=None, index_col=0, names=column_names) population = male_pop + female_pop population.head()Wir erhalten die folgende Ausgabe:
2003 | 2004 | ... | 2011 | 2012 | |
---|---|---|---|---|---|
Country | |||||
Australia | 19872646 | 20091504 | ... | 22620554 | 22683573 |
Austria | 8067289 | 8140122 | ... | 8404252 | 8443018 |
Belgium | 10355844 | 10396421 | ... | 10366843 | 11035958 |
Canada | 31361611 | 31372587 | ... | 33927935 | 34492645 |
Czech Republic | 10203269 | 10211455 | ... | 10532770 | 10505445 |
5 rows × 10 columns
In der Datei countries_total_population.csv
im Verzeichnis data1
speichern wir die eben erzeugte DataFrame population
:
population.to_csv("data1/countries_total_population.csv")
Wir möchten nun ein DataFrame bzw. eine Datei erzeugen, die alle Informationen enthalten soll, also sowohl die weibliche und die männliche Bevölkerung als auch die Gesamtbevölkerung. Dazu konkatenieren wir die drei DataFrames:
pop_complete = pd.concat([population, male_pop, female_pop], keys=["total", "male", "female"])
Um das Ergebnis der vorigen Konkatenation besser zu verstehen, geben wir im Folgenden nur die interessanten Indizes aus:
pop_complete.iloc[[0, 1, 2, 29, 30, 31, 32, 59, 60, 61, 62]]Wir erhalten die folgende Ergebnisse:
2003 | 2004 | ... | 2011 | 2012 | ||
---|---|---|---|---|---|---|
Country | ||||||
total | Australia | 19872646 | 20091504 | ... | 22620554 | 22683573 |
Austria | 8067289 | 8140122 | ... | 8404252 | 8443018 | |
Belgium | 10355844 | 10396421 | ... | 10366843 | 11035958 | |
United States | 288774226 | 290810719 | ... | 309989078 | 312232049 | |
male | Australia | 9873447 | 9990513 | ... | 11260747 | 11280804 |
Austria | 3909120 | 3949825 | ... | 4095337 | 4118035 | |
Belgium | 5066885 | 5087176 | ... | 5370234 | 5413801 | |
United States | 141957038 | 143037260 | ... | 152449134 | 153596908 | |
female | Australia | 9999199 | 10100991 | ... | 11359807 | 11402769 |
Austria | 4158169 | 4190297 | ... | 4308915 | 4324983 | |
Belgium | 5288959 | 5309245 | ... | 4996609 | 5622157 |
11 rows × 10 columns
Wir wollen nun den hierarchischen Index umdrehen, sodass man für jedes Land direkt alle Bevölkerungsinformationen im Blick hat:
df = pop_complete.swaplevel() df.sort_index(inplace=True) df.head(12)Der obige Python-Code liefert Folgendes:
2003 | 2004 | ... | 2011 | 2012 | ||
---|---|---|---|---|---|---|
Country | ||||||
Australia | female | 9999199 | 10100991 | ... | 11359807 | 11402769 |
male | 9873447 | 9990513 | ... | 11260747 | 11280804 | |
total | 19872646 | 20091504 | ... | 22620554 | 22683573 | |
Austria | female | 4158169 | 4190297 | ... | 4308915 | 4324983 |
male | 3909120 | 3949825 | ... | 4095337 | 4118035 | |
total | 8067289 | 8140122 | ... | 8404252 | 8443018 | |
Belgium | female | 5288959 | 5309245 | ... | 4996609 | 5622157 |
male | 5066885 | 5087176 | ... | 5370234 | 5413801 | |
total | 10355844 | 10396421 | ... | 10366843 | 11035958 | |
Canada | female | 15829173 | 15834015 | ... | 17101813 | 17379104 |
male | 15532438 | 15538572 | ... | 16826122 | 17113541 | |
total | 31361611 | 31372587 | ... | 33927935 | 34492645 |
12 rows × 10 columns
df.to_csv("data1/countries_total_population.csv")
Lesen und Schreiben von Excel-Dateien
Es ist auch möglich, Microsoft-Excel-Dateien zu lesen und zu schreiben. Um diese Funktionalitäten bereitzustellen, benutzt Pandas die Module xlrd
und openpyxl
. Diese Module werden automatisch von Pandas installiert, sodass man sie nicht extra installieren muss.
Wir werden ein einfaches Excel-Dokument benutzen, um Lesemöglichkeiten von Pandas zu demonstrieren. Das Dokument sales.xls enthält zwei Blätter (englisch "sheet"), das eine mit dem Namen 'week1' und das andere 'week2'.
Eine Excel-Datei lässt sich mit der Funktion "read_excel" einlesen. Wir zeigen dies mit dem folgenden Python-Programm:
excel_file = pd.ExcelFile("data1/sales.xls") sheet = pd.read_excel(excel_file) sheetWir erhalten die folgende Ausgabe:
Weekday | Sales | |
---|---|---|
0 | Monday | 123432.980000 |
1 | Tuesday | 122198.650200 |
2 | Wednesday | 134418.515220 |
3 | Thursday | 131730.144916 |
4 | Friday | 128173.431003 |
Von den beiden Blättern der Datei "sales.xls" haben wir nur eine mit read_excel
eingelesen. Eine Excel-Datei, die aus zahlreichen Blättern bestehen kann, kann mit allen Blättern wie folgt eingelesen werden:
document = {} excel_file = pd.ExcelFile("data1/sales.xls") for sheet_name in excel_file.sheet_names: document[sheet_name] = excel_file.parse(sheet_name) for sheet_name in document: print("\n" + sheet_name + ":\n", document[sheet_name])
week1: Weekday Sales 0 Monday 123432.980000 1 Tuesday 122198.650200 2 Wednesday 134418.515220 3 Thursday 131730.144916 4 Friday 128173.431003 week2: Weekday Sales 0 Monday 223277.980000 1 Tuesday 234441.879000 2 Wednesday 246163.972950 3 Thursday 241240.693491 4 Friday 230143.621590