Ja, hallo liebe Hörerinnen und Hörer. Willkommen beim Python-Podcast in der mittlerweile sechsten Episode.
Heute geht es um Pandas. Ja, was machen wir eigentlich? Wir sind, wie fast immer, in Jochens Hintergarten.
Ich bin der Dominik, dabei ist wie immer der Jochen und unser Gast, der Simon.
Ja, hallo Simon. Vielleicht kannst du dich einfach mal kurz vorstellen, bevor wir über das Thema reden.
Klar. Ja, ich bin Simon. Ich bin von Haus aus Biologe, immer mit Interesse für Informatik und Spieleentwicklung gesegnet gewesen
und habe das dann irgendwie auch zu meinem Beruf gemacht. Also ich habe nach meinem Biostudium ein bisschen geforscht in der Bioinformatik.
Da ging es dann viel um Datenanalyse von DNA-Sequenzen und so Dingen.
Game of Life. Game of Life, ja, quasi. Nur in echt echt.
Ja, genau. Und zusammen mit dem Wissen, was ich daraus getragen habe und meinem Interesse an Informatik und Spieleentwicklung
mache ich heute als selbstständiger IT-Trainer Trainings für Game Engines und Trainings für Softwareentwicklung
und parallel noch ein paar Softwareprojekte.
Das Gaming haben wir uns ja schon ein bisschen unterhalten. Das machen wir auch nach der Folge ein bisschen intensiver.
Aber heute soll es ja um Pandas gehen. Genau, heute...
Deswegen, ja, super, dass du das auch ganz viel mit deinem zu tun hattest in deinem Fach.
In deiner Wissenschaft.
Bevor wir aber jetzt auf das Pandas-Thema eingehen, würde ich gerne noch so ein bisschen wieder Formalkrams abarbeiten.
Wenn ihr Fragen, Anmerkungen habt, Lobkommentare, Hass, dann schreibt uns doch an hallo-podcast.de.
Ihr findet natürlich die Links und alle zusätzlichen Informationen wie in den Shownotes.
Es gab noch ein bisschen User-Feedback und zwar sollten wir irgendwann mal eine Folge machen über Do's und Don'ts im Programmieren.
Also seid doch bitte so nett und schickt uns einfach per E-Mail eure Do's und Don'ts.
Das wäre super. Dann schneiden wir das ein bisschen zusammen und fragen euch in einer der nächsten Folgen bestimmt irgendwann mal danach.
Ja, doch, es gab noch ein anderes eben zu der Datenbank-Folge, dass das gar nicht so schlimm gewesen wäre mit der Länge.
Und das ist übrigens vielleicht ganz interessant.
Also wenn man sich anguckt, welche Folgen komplett runtergeladen wurden, dann hat die beste Quote tatsächlich die Datenbank-Folge zurzeit.
Was ich ein bisschen überraschend finde.
Ich hätte jetzt auch erwartet, dass es eher ein bisschen runtergeht.
Vielleicht müssen wir noch mehr so Buzzword-Bingo-Sachen machen.
Nein, wir machen das natürlich für alle unsere Hörer.
Vor allen Dingen für die, die sich dafür wirklich interessieren.
Und natürlich auch für die Leute, die was lernen wollen und für alle Leute, die einfach so reinhören oder denen langweilig ist.
Oder ihr wisst ja, morgens, abends, nachts, beim Aufstehen im Flugzeug könnt ihr immer hören.
Ja, bevor wir in das Thema gehen, ist weiterhin noch ein paar News aus der Szene.
Und zwar gab es so ein bisschen was Neues.
Daubig.
Python 3.8, zweite Alpha.
Ja.
Ja, da gab es so ein paar coole neue Sachen mit Shared Memory for Multiprocessing.
Jochen, was ist das denn?
Ja, das ist eine gute Frage.
Das ist eine gute Frage.
Wann habe ich denn das da reingeschrieben?
Oh, ja, das ist auch schon ein bisschen her.
Ah doch, ja, alles klar.
Das war ja immer so ein Problem.
Also man muss ja, wenn man jetzt über mehrere Prozessoren Berechnungen verteilen will in Python, das auf mehreren Prozessen machen.
Weil man ja irgendwie so ein Global Interpreter-Log hat, das halt verhindert, dass man das innerhalb von einem Prozess irgendwie mehrere Prozessoren benutzen kann.
Und ja, früher hat man halt dann immer so das, oder hat man jetzt immer noch in der stabilen Version, aber vielleicht hat man das mit 3.8 dann nicht mehr so das Problem, dass man, wenn man jetzt eine Funktion aufrufen möchte und, sagen wir mal so, man startet halt ein Pool von fünf Prozessen oder sowas oder zehn.
Und eben so viele üblicherweise, wie man Prozessoren hat und ruft jetzt eine Funktion auf jedem Prozessor sozusagen auf.
Also man hat jetzt eine Liste von Dingen, die man irgendwie abarbeiten möchte.
Man hat eine Funktion, die das dann halt tut.
Dann sagt man, okay, starte mit diesem.
Job irgendwie diese Funktion.
Und das geht dann halt irgendwie auf die, auf den, auf jeden Prozess, der halt in diesem Pool ist, wird dann halt das irgendwie gestartet.
Also wie man im Supermarkt ganz viele verschiedene Kassen aufmacht und macht ein paar Kassen auf einmal auf.
Ja, ja, ja.
Das Problem ist jetzt, dass man, wenn man da irgendwie auch Daten hat, auf denen da gearbeitet wird, dann muss man die Daten irgendwie zu diesen Prozessen bringen.
Das ist jetzt ein anderer Prozess.
Das heißt, man kann nicht einfach das in, also.
In Code ist es schon so, dass man einfach einen Funktionsaufruf macht.
Aber was dann im Hintergrund passieren muss, ist ja irgendwie, dass die Daten serialisiert werden.
Dann müssen sie irgendwie durch die Gegend geschoben werden.
Und dann auf der anderen Seite wird der deserialisiert werden.
In so kleine Häppchen.
Und dass alle, die ganze große Bestellung an verschiedenen Kassen abgearbeitet wird, um danach wieder in der richtigen Reihenfolge im Einkaufskorb zu landen.
So ungefähr?
Ja, man kann.
15 Fehler wieder.
Nein, ich glaube, ich weiß nicht, ob die Analogie da an der Stelle so gut passt.
Ich weiß auch nicht genau.
Ja, man muss es.
Ja, man kann sich vielleicht vorstellen, dass man, wenn man jetzt einen riesen Einkaufswagen voll Zeug hat und möchte jetzt das an fünf Kassen aber bezahlen, dann muss man halt auch fünf Einkaufswagen haben, indem man das jetzt aufteilt.
Und mit jedem Einkaufswagen einzeln zu einer Kasse.
Und.
Muss die irgendwer umpacken.
Dann muss man die umpacken.
Und das ist halt alles halbwegs aufwendig und kann halt auch zu Problemen führen, wenn die Daten sehr groß werden.
Zum Beispiel kann es sein, dass irgendwelche Dinge dazwischen halt aussteigen und das ist alles nicht so schön.
Und es ist halt unter Umständen auch etwas, was Dinge langsam macht.
Und jetzt geht es aber transparent mit Chat Memory sozusagen.
Das heißt, man hat halt die Daten.
Genau, das ist ja auch so ein Problem.
Wenn man jetzt Daten serialisiert und deserialisieren muss, dann kopiert man sie damit natürlich auch.
Das heißt, wenn man große Daten hat, die jetzt vielleicht insgesamt nur einmal in den Hauptspeicher passen, aber nicht zweimal.
Wenn man sie kopiert, dann hat man sie halt zweimal drin und dann hat man zu wenig Hauptspeicher.
Ist ja auch blöd.
Und was halt schon immer viel, viel cooler war, ist, wenn man halt einfach Shared Memory reservieren kann
und sagt dann den einzelnen Prozessen, gibt denen nur einen Pointer auf diese Shared Memory und sagt so,
da sind deine Datenstrukturen drin.
Also das heißt, jemand nimmt sich einfach so einen Unterkorb aus dem Einkaufswagen raus, der schon fertig ist
und der Einkaufskorb, der fährt dann automatisch auf das richtige Förderband.
Ja, nee, aber das ist, ja, mal überlegen, ob man diese Analogie da noch irgendwie...
Ja, Shared Memory, ein eigener Teil der Einkaufswagen.
Das wäre der eine Einkaufswagen, der an allen fünf Kassen steht.
Jede Kasse greift nur auf einen Teil von dem Korb selber zu.
Stimmt, wir haben eine Ruhre von Kassen.
Die Kasse ist oben, unten, rechts und links.
Man kann einfach eingreifen.
Das ist schön, ja.
Genau, so könnte man sich das vorstellen, ja.
Und das heißt, man hat halt, wenn man jetzt Daten hat, die so gerade in den Hauptspeicher vielleicht passen,
dann kann man die trotzdem auf mehreren Prozessen verarbeiten.
Und das macht natürlich Multiprocessing auf Python deutlich attraktiver.
Und das ist irgendwie eine ziemlich coole Geschichte, wenn die jetzt in drei abkommen,
und...
Dann wird Python ja schneller.
Ja, also, oder es wird einfacher damit.
Also, man kann ja auch, das konnte man auch sowieso schon immer machen.
Man kann ja auch einfach Shared Memory reservieren, da Dinge reinpacken.
Da gibt es übrigens auch ein schönes Modul in der Standardbibliothek, das heißt Struct.
Struct.
Genau, damit kann man zum Beispiel Daten halt so binär irgendwie in den Hauptspeicher schreiben.
Und das zum Beispiel so tun,
dass das halt C-Structs sind.
Ah.
Und dann kann man das halt, also das ist halt so etwas, so haben wir das früher halt gemacht,
wenn wir Daten nicht so groß waren, dass man da nicht einfach irgendwas mit tun konnte.
Das heißt, man hat halt irgendwie einen Shared Memory Bereich,
und den schreibt man halt irgendwie per Struct irgendwie, sozusagen C-Struct Daten irgendwie rein,
und hat dann Python-Prozesse, die wiederum einen Pointer auf diese Shared Memory kriegen,
und die dann halt wieder ein C-Modul haben, das dann halt irgendwas mit den Daten macht und so.
Und dann geht das auch schon, aber das ist halt viel Handarbeit.
Und jetzt kriegt man das quasi so geschenkt, und das passiert dann dann automatisch, und das ist halt schon sehr nett.
Cool.
Ja.
Ich hörte ja auch gerade diese Hintergrundmusik, das ist so ein bisschen wie in Battlestar Galactica, ne, diese
Ah, super.
Keine Opelide.
Ja, also die nächsten News aus der Szene.
Doppelte Keys, gab ein Post von Guido irgendwo, der hat irgendwas geshared.
Es gibt ein neues Python-Enhancement-Proposal, das ist eine ganz interessante,
äh, äh, äh, Geschichte vorschlägt, und zwar geht's darum, dass man halt, äh, für Dicts vielleicht auch die, äh,
äh, also Plus und Minus als Operatoren, äh, haben möchte, sodass man halt sagen kann, irgendwie Dict A plus Dict B,
und dann, äh, werden sozusagen die Keys hinzugefügt, oder halt, äh, wird das eine, äh, werden halt die Keys, die in dem einen Ding drin sind, entfernt,
wenn man das halt abzieht, und das ist natürlich auch eine ganz, also ist eigentlich relativ naheliegend,
es wundert mich, dass da bisher noch niemand draufgekommen ist, dass man das irgendwie mal machen könnte, aber
das ist auf jeden Fall eine ganz interessante Idee.
Und, ähm, Kido hat da einen Artikel zugeschrieben.
Ja, genau, irgendwie, der hat zweimal den Key irgendwie draus zugewiesen, und dann quasi einen Dictionary mit zwei identischen Keys erzeugt,
wo dann nur einer von überlebt hat.
Äh, ja.
Irgendwie so, also, wenn man halt, ich glaub, welcher Post war das, ähm, wo er A einmal die Nullen, A einmal die Eins zugewiesen hat,
und dann war Eins übrig, weil das die letzte Zuweisung war.
Weil ich das richtig verstanden habe.
Genau, das war das Verhalten.
Das war das Verhalten, was mich irgendwie gewundert hat, aber das ist, das ist, äh, das ist generell, äh, so, das war schon immer so, offenbar,
wenn man halt, ähm, also insofern ist es halt kompatibel mit diesem Verhalten, ähm, äh, dass wenn man jetzt irgendwie einen Key mehrfach entdeckt hat,
dass dann halt immer das letzte genommen wird.
Und, ähm, das war mir auch gar nicht klar, dass das so ist, aber, äh...
Also kein, ähm, Duplicate Value oder Key Error oder sowas.
Nee, es wird einfach das letzte genommen.
Und da hat er halt dazu, oder von mir nehmen wir es so geschrieben, dass, äh, ja, er hat damals lange drüber nachgedacht, äh, dass das,
weil irgendjemand die Frage gestellt hat, ob das Absicht wäre oder nicht.
Dann hat er so, ich hab damals noch lange drüber nachgedacht und das ist Absicht.
Ja.
Und damit...
Ich erinnere mich an irgendein Programm, wo ich das dachte, wo ich irgendwie komischen Fehler hatte und das, glaube ich, genau daran gelegen hat.
Weil, ja, irgendwelche Duplikate dann zwar drin waren, ich das aber nicht gemerkt habe, erst irgendwann später, als mir um die Ohren flog.
Ja, äh, aber, ähm, Guido hatte auch noch, ähm, ähm, einen Blogpost, äh, dazu geschrieben, wo er, äh, überlegt hat, ob das mit diesen Operatoren...
halt eine gute Idee ist oder nicht.
Wie heißt das wieder? Code Active State?
Ähm.
Python Ideas.
Ja, nee, in seinem Blog war das Ding drin.
Ja.
Und, äh, ja, da macht er tatsächlich den Punkt, dass das halt schon eine gute Idee ist und, äh, ähm, hat er so das als Beispiel quasi, wenn man jetzt mathematische, also arithmetische Geschichten halt nicht als, äh, Operatoren hätte, sondern wenn man da Funktionen, das mit Funktionen ausschreiben würde,
dann würde es halt sehr viel unklarer, was eigentlich gemeint ist, jedenfalls wenn das irgendwie komplizierter wird, weil man dann halt immer erst die, äh, Operatoren, äh, immer erst die Funktion mit den Klammern auflösen muss, äh, bevor man sieht, was passiert und während man quasi, wenn man das als Operatoren hinschreibt, hat man so eine Art visuelles Pattern-Matching direkt schon, das einem sagt, was da, was da passiert und daher sind für so arithmetische Geschichten, um zu sehen, was da passiert ist, ist es halt, äh, viel sinnvoller, das mit Operatoren-Schreibweise hinzuschreiben als mit Funktionen, was man ja auch tun könnte.
Also, äh, für Dicts ist halt die Frage, ob das Sinn macht, aber, also immer dann, wenn, wenn einem das dabei beim Verständnis hilft, äh, wenn man das anders hinschreiben kann, dann kann es natürlich schon gut sein, dass das irgendwie sinnvoll ist und, ähm, ja, das ist auf jeden Fall, glaube ich, hier ein, äh, starkes Argument dafür und, äh, mal sehen. Ich, ich bin mir nicht sicher, ob wir das in Python 3.8 dann schon direkt sehen werden, aber es wäre auf jeden Fall, es ist irgendwie eine interessante Idee und, ähm, ja, ich bin mal gespannt, wie das sich so weiterentwickelt.
Neue News hatten wir, glaube ich, und das war der Django-Chat-Podcast.
Äh, releases machen und so. Ja, und, äh, das war schon, die ersten beiden Episoden sind erschienen, die erste war irgendwie relativ interessant. Ich fand, das war auch so, dass da irgendwie eine ganze Menge Überschneidung war zu dem, was wir in unserer Django-Folge irgendwie erzählt haben, so von dem, äh, so Rundtenor, äh.
Ja, ja, ja, ja, ja, ja, ja, ja, ja, ja, ja, ja, ja.
Ja, wir können eigentlich mal, Pandas, genau.
Ja, Pandas, was ist das denn überhaupt? Also, ähm, beim Eishockey, ich bin ja Eishockey-Fan, da haben die Schiedsrichter jetzt so ein Pandasymbol, äh, gehabt auf den Trikots, weil die eine Kooperation mit dem, äh, WWF haben und dann waren sie am Ende ein bisschen enttäuscht, dass der WWF da so eine Spendenaffäre hatte, aber, ähm, ja, das ist manchmal so, aber Pandas und Spendenaffäre hat wahrscheinlich jetzt bei uns jetzt so viel nicht miteinander zu tun.
Ne, aber das, äh, der Name bietet natürlich schon so ein bisschen, äh, äh, Verwechslungspotenzial. Wir hatten da auch genau darüber gesprochen, haben, ob wir nicht irgendwie mal zusammen irgendwie eine Podcast-Episode machen wollen, hatte.
Da sieht man auch irgendwie zuerst was anderes verstanden, glaube ich.
Ja, genau, also es gibt nicht nur, ähm, Python-Pandas, das Data-Frame-Framework, sondern auch, ähm, Python-Pandas-3D, die Game-Engine.
Ah!
Und, äh, weil ich ja irgendwie beide Themen abdecke, war das, was ich gerade zuletzt gemacht hatte, das erste, was im Kopf wieder aufgetaucht ist, und das war die Game-Engine, und dann haben wir, weiß nicht, fünf Minuten aneinander vorbeigeredet.
Wir können doch jetzt gerne nochmal fünf Minuten über die Game-Engine-Pandas-3D reden, wenn du magst.
Ist die in Python?
Also, äh, ich...
Ich glaube, Game-Entwicklung in Python ist vielleicht eine Folge, zu der ich nochmal wiederkommen sollte.
Oh, ja!
Ja, ja, einfach, weil das sehr, sehr umfangreich ist.
Und das geht?
Also, da gibt's im Wesentlichen irgendwie, äh, Pygame und Pandas als die beiden großen etablierten, dann gibt's noch so ein paar kleinere.
Und damit kann man wirklich auch Spiele machen, die auch gehen und die auch aussehen, oder sowas? Oder braucht man dafür noch Qt, oder sowas?
Ich sag's mal vorsichtig, ja, damit kann man Spiele machen, ähm, mit Pygame 2D-Spiele, mit Pandas 3D sogar 3D-Spiele, was man damit sehr gut machen kann, ist...
...ist zu lernen, wie so eine Game-Engine wirklich funktioniert.
Mhm.
Ich glaube aber nicht, dass man Triple-A-Titel darin machen möchte, weil es dann doch irgendwann umständlicher ist, als eine von den großen 3D-Game-Engines, die so am Markt sind, äh, die vielleicht auch ein bisschen mehr klickbar sind, zu verwenden.
Ich muss überlegen, welche das waren. Das war, ähm, Unreal...
Unreal, Unity 3D und...
...Unity 3D und CryEngine.
Ja, okay, dann CryEngine ist ja nicht frei. It 7 oder so 8.
Weiß ich gerade gar nicht.
Ich glaub, wir sind gerade völlig off-topic, ähm, wir wollten über Pandas sprechen.
Genau, also Pandas 3D ist die Game-Engine, darüber sprechen wir heute dann nicht, und, ähm, Pandas, äh, ist im Wesentlichen eins der Python-Tools, an denen man nicht vorbeikommt, wenn man Datenanalyse betreibt.
Okay, wir sind wieder mal bei der Datenanalyse.
Genau.
Datenbanken hatten wir übrigens in der letzten Folge, für alle, die sich das noch nicht angehört haben, eine ziemliche Mammut-Folge mit, wie lange, drei Stunden haben wir gebraucht?
Ja, ein bisschen mehr, aber genau um den Dreh.
Wenn ihr mal wieder die Wohnung richtig putzen wollt, dann...
Ja, an der Stelle würde ich ganz gerne noch kurz, äh, meinen Hintergrund in der Datenanalyse erwähnen, damit man so ein bisschen einordnen kann, aus welcher Richtung meine Kommentare kommen.
Ähm, als Biologe war damals, äh, Perl das große, die große Programmiersprache, um alles zu lösen, und, äh, erst zum Ende meiner Forschungszeit hat sich dann irgendwann Python durchgesetzt.
Das heißt, ich hab noch sehr viel in Perl gemacht, und was man in Perl gar nicht gut konnte, zumindest ich konnte das nicht, ist...
...das Daten, äh, nachher analysieren und visualisieren, aber die Aufbereitung war da sehr gut.
Das heißt, für die Analyse und, und die Visualisierung sind wir dann immer zu R rüber gewechselt.
R ist, äh, auch eine Programmiersprache, ähm, ist eine eher mathematische Annotation, ähm, zur Datenanalyse.
Und wenn ich so die Branche, sag ich mal, richtig überblicke, dann wird am meisten, ähm, R und Python benutzt, und vielleicht dann noch Mathe.
Ähm, als, als dritte Alternative, wenn Leute heute Daten, Datenanalyse machen.
Was meinst du denn mit Datenbereinigung?
Ähm, in der Biologie ist das so, dass die Daten immer unheimlich, äh, fuzzy sind, also man, man hat nie ganz konkrete Messwerte, sondern man hat immer super viele Abweichungen, mal, mal Fehlmessungen, mal Werte, die man gar nicht erheben konnte, und, äh...
Du musst dich dann entscheiden, ob du eine Rundung anwendest oder nicht.
Ähm, führt dann erstmal dazu, dass die Daten nicht mehr so strukturiert sind, wie man das eigentlich dachte in der Tabelle.
Ähm, das kommt auf, auf die Messinstrumente im Wesentlichen an.
Ähm, das heißt, die erste Aufbereitung ist erstmal, die Daten in ein maschinenlesbares Format zu bringen.
Und da ist es, äh, von unfassbarem Wert, wenn man programmieren kann.
Ähm...
Dann muss man jede einzelne Zeile oder Zelle durchgehen und die manuell korrigieren.
Mhm.
Genau, also ich, äh, ich hab auch, äh, tatsächlich schon...
Ich hab auch Kollegen damals gesehen, die, äh, von Programmierung gar keine Ahnung hatten, die dann angefangen haben, in Excel sich das händisch zusammenzustellen.
Und, äh, dann haben wir uns kurz zusammengesetzt, ein Makro geschrieben und dann ging das irgendwie doch schneller.
Mhm.
Ähm, und fehlerfreier an der Stelle auch.
So, und, ähm, dieser erste Schritt, überhaupt die Daten erstmal maschinenlesbar zu kriegen, der, der ist im Wesentlichen unabhängig von der Analyse, aber notwendig.
Nochmal für unsere ganz Anfänger, nochmal bitte, was denn überhaupt maschinenlesbar bedeutet.
Mhm.
Ähm, ich hab da mal irgendwann ein Beispiel vorbereitet, äh, für, ähm, für Mediziner, die von Excel zu R wechseln wollten.
Und, äh, das Beispiel war eine Tabelle, eine Excel-Tabelle aus meinem Laboralltag, wo dann in einem Tabellenblatt an mehreren verschiedenen Stellen so kleine Subtabellen zu sehen waren, wo die Messdaten drin standen.
Da gab's dann quasi einmal Experiment A, war so ein, äh, fünfmal...
Fünfmal vier Raster.
Experiment B war so ein fünfmal vier Raster, was irgendwie rechts daneben stand.
Und dann gab's noch ein Experiment C, was dann mittig darunter stand, auch fünfmal vier Raster.
Das ist für einen Menschen super lesbar, weil man kann sofort die Blöcke identifizieren und sich die Messdaten angucken.
Ähm, für eine Maschine ist das aber nicht mehr strukturiert lesbar.
Weil die Koordinaten nicht klar sind.
Weil die Koordinaten nicht klar sind, genau.
Und, ähm, was häufig passiert ist, wenn Menschen...
...Tabellen ausfüllen, um die visuell ansprechend zu machen, verletzen die ein wichtiges Kriterium, dass in jeder Zeile oder Spalte, je nachdem, woran man sich orientieren möchte, nur ein Datensatz wirklich drinsteht.
Oder stehen sollte, weil da unterschiedliche Informationen sind, die nicht voneinander getrennt sind.
Dann stehen zum Beispiel sowas wie eine Spalte, wo zwei verschiedene Datensachen auf einmal drinstehen.
Genau.
Einmal Temperatur in Celsius, einmal in Fahrenheit oder sowas.
Oder ist das legitim?
Ja, das könnte ja noch...
...zusammenpassen, aber, ähm, einmal die Temperaturen, ähm, in Celsius und Fahrenheit für das eine Experiment und dann, ähm, das Ganze nochmal für das andere Experiment irgendwo weiter hinten in der gleichen Zeile, aber nicht klar strukturiert abgrenzbar.
Mhm.
Ja, also das ist halt quasi bei Datenmarken, das ist halt die erste Normalform, dass halt man in der Spalte immer nur einen Wert stehen hat und nicht, äh, irgendwie mehrere zum Beispiel, was halt dann manche Leute...
Aber, äh, Fahrenheit und Celsius wäre okay, wenn man...
...die...
...wenn die Spalte...
...wenn das unterschiedliche Spalten wäre...
...wenn die Information enthalten wäre in der Zelle, ob es Celsius-Erfahrenheit wäre.
Äh...
Weil das wäre sonst problematisch, wenn man...
Ja, also wir kommen da sicherlich gleich nochmal zu, so gut das geht, in einem Podcast Tabellen zu beschreiben.
Ja, wir passieren, weil wir das so kritisieren.
Ähm, äh, grundsätzlich, wenn man so eine Tabelle hat, wo man Zeilenbeschriftungen hat und Spaltenbeschriftungen hat und die ganze Tabelle ist rechteckig, dann kriegt man die auch sinnvoll maschinenlesbar ausgewertet.
Mhm.
Also Probleme höre ich, fangen dann an, wenn man keine zweidimensionalen Tabellen mehr hat, keine, die man mal eben so auf seinen Whiteboard malen kann.
Welche, die man bauen müsste oder, äh, wo man irgendwelche Dimensionen verbraucht, die wir uns jetzt nicht so räumlich vorstellen können.
Genau.
Oder wo, wo tatsächlich Lücken drin sind und die Muster für Menschen zwar noch erkennbar bleiben, aber für eine Maschine die Koordinaten dann zum Beispiel nicht mehr zusammenpassen.
Okay.
Ja.
Ja, okay, das haben wir so ungefähr verstanden, was so maschinenlesbar dann bedeutet für die einzelnen Daten.
Und wo kommt jetzt Pandas dann ins Spiel, wenn du jetzt diese...
Für die Darstellung von Vektoren NumPy und für einfache statistische Analysen SciPy und für Visualisierung Matplotlib.
Und dann war der Kreis eins weiter draußen so ein bisschen das, was darauf aufbaut.
Das war dann Pandas, das war, ähm, Studs Models war das, glaube ich.
Mhm, das so für Zeitreihen und so.
Genau, und, ähm, Seaborn.
Und das waren dann die Pendants, also, äh, Seaborn auch wieder zur Visualisierung und Studs Models.
Äh, im Prinzip zur statistischen Auswertung und Pandas eben zum, äh, zum Data Handling, ähm, aber jenseits von einfachen Vektoren.
Mhm, okay.
So, und da kommen wir im Prinzip auch schon wieder in den Bereich, wo man immer den Vergleich zwischen Excel normalerweise führt, ähm, wenn man das mit, mit Leuten bespricht, mit denen man zusammenarbeitet, ähm, weil Excel kennt irgendwie jeder.
Ja.
Also, Tabellenkalkulation ist...
Also, Tabellenkalkulation ist jedem sofort ein Begriff und alle wissen auch sofort, okay, es gibt Zeilen und Spalten.
Das ist so, dass das, äh, wäre ein Minimum, was man wissen muss, um mit Pandas was anfangen zu können.
Das hat man wahrscheinlich in der Schule schon mal aufgemacht oder so, oder aufmachen müssen.
In der Regel schon, ja.
Ja, genau, ähm, das heißt, bei Pandas sind wir jetzt in dem Bereich von, ähm, Data Handling.
Also, wie kann ich meine Daten laden, verarbeiten, zur Verfügung stellen für Analysen?
Wie macht Pandas das?
Gibt's da Speziellen?
Naja, also, äh, ich, ich würd sagen, also, das ist auch das, äh, ähm, denke ich, Hauptfeature von, von Pandas ist, dass man damit die Daten überhaupt erstmal irgendwie, äh, in, in so ein, ähm, ja, äh, reinbekommt irgendwie.
Also, äh, Westman Kinney hat das auch mal gesagt, dass die, äh, populärste und, und wichtigste Methode, die, die Pandas halt hat, ist halt Read CSV.
Mhm.
Äh, die sehr, sehr flexibel ist und man kann irgendwie so ungefähr jedes CSV, was irgendwo...
Genau, ist ein sehr hässliches Format und Leute machen unglaubliche, äh, und, und unheilige Dinge damit, aber, äh, man, man kann irgendwie mit dieser, mit dieser Funktion kann man das fast alles parsen, ne?
Die hat sehr viele, ähm, Argumente und sehr viele Dinge, an denen man da irgendwie was drehen kann und man kriegt fast alles damit geparsed und, ähm, das heißt, ja, egal wie komisch die Daten aussehen, die man so hat, man kriegt sie irgendwie mit Read CSV oft irgendwie in Pandas rein und hat sie dann halt in einem sauberen Format und kann das dann halt wieder in anderen Formaten rausschreiben, aber gut, äh, Pandas kann das nicht.
Kann nicht nur CSV, äh, lesen, sondern halt auch diverse andere Formate, äh, ja, von JSON über, keine Ahnung, XML oder was auch immer. Teilweise werden dann halt, äh, andere Bibliotheken unten drunter verwendet, um das halt einzulesen, aber, äh, das ist halt, äh, also Pandas ist eigentlich immer so der, der erste Schritt, äh, wenn man irgendwo Daten herbekommt, um die halt in, in ein Format zu bringen, mit dem man irgendwas machen kann, um es halt irgendwie einzulesen, äh, in Programmen, da nimmt man halt eigentlich immer Pandas, weil das halt...
Eine Zeitreihenanalyse oder sowas?
Ähm, und die Projekte, die am meisten Geld bekommen, sind sowas wie TensorFlow oder so, ne, weil man drüber schreiten kann, inwiefern das halt noch Open Source ist, aber, ähm, und, äh, auch die ganzen Cloud-Dienste oder so, die haben alle irgendwie, äh, Methoden, Daten da reinzubekommen, Daten wieder rauszubekommen.
zu bekommen und auch in denen steckt relativ viel Geld drin, aber diese Sachen sind alle
ziemlich schlecht irgendwie und Pandas füllte halt so eine Lücke.
Ist halt eigentlich ultra wichtig, weil irgendwie diese ganzen Datenimport-Export-Geschichten
sind halt etwas, was man immer braucht und irgendwie es gibt außer Pandas keine Projekte,
die das irgendwie ordentlich gemacht haben und du kannst natürlich irgendwie deine tolle
Deep Learning TensorFlow-Geschichte nehmen, aber wenn du die Daten halt nicht hast, um
damit irgendwas machen zu können, dann hilft dir das alles nichts und ja, das, eben, weiß
man, Kenny erzählt davon halt auch immer, dass ihm das total wundert und dass er das
total seltsam findet, dass halt so ein wichtiger Teil der Infrastruktur so wenig Liebe erfährt
quasi und dass seine Hauptmotivation war zu sagen, okay, da muss man mal was tun, da muss
man, das muss doch irgendwie, dieses Problem muss man doch lösen, das ist halt irgendwie
ein Problem, was alle haben und was irgendwie sehr ärgerlich ist und ja.
Und das ist halt, das macht Pandas auch sehr gut irgendwie und das ist immer so ein erster
Schritt, wenn man irgendwie Daten, auch wenn man jetzt hinterher Machine Learning machen
möchte oder so, hat man trotzdem immer Pandas mit dabei, weil man die Daten ja erstmal in
irgendwie ein Format bringen muss vorher und vielleicht aufräumen muss, sauber machen
muss, da gibt es auch immer so einen schönen Spruch, irgendwie Data Science ist halt so
oder auch Machine Learning ist halt, 80% ist halt Data Cleaning, ja, und 20% ist darüber
beschweren, dass irgendwie 80% Data Cleaning, ja, ich meine, die andere Sache ist, als Mensch
möchte man ja auch sich die Daten vielleicht zwischendurch mal angucken können und dafür
braucht man irgendwie eine Datenstruktur, in der man sehr schnell zu Rahmendaten kommt,
vielleicht braucht man mal einen Mittelwert oder will sich mal die Verteilung angucken,
gruppiert bei irgendwelchen...
Kategorien oder sowas.
Also sicherlich ist diese Import-Geschichte von Pandas eine der mächtigsten, die ich bisher
gesehen habe, was auch so fehlende Datenpunkte angeht und wenn die Struktur mal nicht ganz
stimmt und man kann einzelne Zeilen überspringen, wenn da mal was kaputt geht oder sowas.
Da habe ich jetzt übrigens direkt eine doofe Frage zu, weil es gibt ja irgendwie bei Pandas
so ein paar Werte, die, wenn die halt nicht da sind, die man irgendwie füllen kann, da
gibt es ja irgendwie jetzt aber so drei Typen.
So Null und None und None.
Warum, wieso braucht man da drei?
In Pandas, also ich wüsste jetzt eigentlich nur, dass es da Not a Number gibt und das
ist historisch sozusagen, hier ist kein Wert von NumPy, das ist auch irgendwie sozusagen
ganz unten drunter ist das tatsächlich ein...
In Float kann man das halt ausdrücken und ja, das hat halt auch so das leichte Problem,
dass man im Grunde immer dann, wenn man solche Werte hat, dann halt auch der Datentyp irgendwie
Float sein muss, was so ein bisschen doof ist.
Das war bis vor ganz kurzem war das noch so, dass man halt, wenn man jetzt eine Integer-Spalte
hatte und da fehlt halt jetzt ein Wert und man hat halt gesagt, okay, da kommt irgendwie
was dazu, was halt irgendwie fehlt oder so und man macht dann einen Re-Index und guckt
und dann hat es...
Dann hat sich plötzlich der Typ der Spalte in Float geändert, weil es halt keine fehlenden
Werte in Integer-Typ, die Type-Spalten gibt und das ist ein ziemlich blödes Problem.
Aber jetzt gibt es halt irgendwie seit einiger Zeit diese Array-Extensions, Array-Extensions-API
für Pandas und die halt mit Cyber-Pandas dazugekommen ist, ich weiß gar nicht, welche
Version das genau war.
Und jetzt hat auch die, Ende Januar ist die letzte größere Release von Pandas erschienen,
ich glaube 0.224 oder so.
0.24, ja.
0.24 und da ist jetzt halt auch eine native, natives Integer-Spaltenformat drin, das halt
auch nannen kann und das ist natürlich total cool irgendwie und man kann jetzt für, also
dadurch, dass man jetzt quasi nicht mehr Namen-Pile unten drunter liegen hat, kann man da auch
diverse andere...
coole Datentypen irgendwie verwenden, die vorher so nicht möglich waren, weil man ja
immer auf Namen-Pile angewiesen war.
Also Namen-Pile ist auch ganz cool, aber Namen-Pile hat halt das Problem, dass das grundlegende
Design dafür ist halt, ja jetzt doch schon wahrscheinlich fast 20 Jahre alt und passt
halt auch nicht mehr so richtig auf die Anforderungen von heute und dummerweise hat Pandas aber
viele der Implementationsdetails in Namen-Pile halt rausgelegt und das kann man jetzt auch
nicht mehr so einfach ändern, weil das halt...
also wenn man das wieder ändern würde, würde das Code brechen und dann also wäre keine
abwärtskompatiblen Änderungen mehr und das ist natürlich alles so ein bisschen blöde
Situation, aber irgendwie mit dieser Array-Extension-API hat man auf jeden Fall eine Möglichkeit, wenn
man den Typ ändert, dann ist das alles eigentlich in Ordnung und dann kann man da auch schöne
neue Sachen machen, ohne dass man auf Namen-Pile irgendwie angewiesen ist.
Zum Beispiel was halt...
also das sind so Beschränkungen, die sind echt blöd.
Also wenn man auf Namen-Pile unten drunter basierendes Pandas hat, dann hat man halt so
was nicht wie zum Beispiel Decimal-Types, also einfach man hat keinen fehlenden Missing-Value-Support
für sowas wie Integer, was auch schon schlimm ist, aber man hat halt auch... wenn man jetzt
mit Geld zu tun hat, was man ja vielleicht auch irgendwie... dann hat man halt bloß
Float, das will man auch nicht, also man würde das dann irgendwie wahrscheinlich eher Geld
in Integer, also in Cent-Integer oder sowas verwenden.
Viele werden wahrscheinlich irgendwie Float nehmen und dann denken, ach das wird schon
irgendwie hinhauen.
Und dann böse Überraschungen überleben, weil das für... das funktioniert halt überhaupt
gar nicht.
Und man kriegt diverse richtig böse Probleme, wenn man das macht.
Und in Datenbanken ist das Problem eigentlich auch schon lange gelöst, da gibt es den Decimal-Type,
genau für sowas, der dann halt auch ordentlich rundet und so.
Und in Python gibt es auch einen nativen Decimal-Type, der ist blöderweise nur total super langsam,
also den kann man eigentlich auch nicht nehmen.
Also sozusagen als Array-Extension-Type halt auch Decimal, sodass man das halt auch in Pandas
Data Frames halt Geld quasi mit Kommastellen verwenden kann, ohne dass man da mit schlimmen
Konsequenzen rechnen muss.
Und es gibt sowas wie Date-Time mit Time-Zonen dran und so, das ging vorher auch nicht.
Und das ist...
Achso, sowas wie Grad mit Celsius-Erfahrenheit vielleicht.
Das ist nochmal ein anderes... genau, das möchte man auch gerne haben.
Ich weiß nicht, ich glaube, das ist nicht direkt in Pandas drin.
Es gibt Bibliotheken dafür, dass man halt an Spalten auch noch irgendwie so eine Maßeinheit dran klebt.
Die Annotationen und auch Skalierungsfaktoren kommen auch mit unter aus dem zugrunde liegenden Datenformat,
aus dem man nachher importiert.
Also es gibt irgendwie wissenschaftliche Datenformate, die speichern sowas alles mit.
HDF 5 oder NET-CDF oder wie das inzwischen heißt.
Wie sieht das dann aus? Hat das eine Spalte, ein Doppel drin oder?
Da gibt es im Prinzip irgendwie so eine Tabelle von Meta-Daten.
Meta-Daten, wo drin steht, welche Spalten, welche Maßeinheit, welche Skalierungsfaktoren haben,
wann die zuletzt bearbeitet wurden.
Und darunter stehen dann serialisiert die Daten drin.
Und dadurch hat man einen sehr, sehr schnellen sequentiellen Zugriff auf seine Daten,
hat aber trotzdem die Möglichkeit, diese Skalierungen und Einheiten mitzuführen.
Und in Pandas weiß ich nicht, ob das inzwischen mit importiert wird.
Aber diese Erweiterung...
Ja, ich habe jetzt normalerweise auch nicht mehr parat, wie die Bibliothek...
Es gibt eine Bibliothek für so Maßeinheiten und sowas.
Ich weiß aber nicht genau, wie das gemacht ist.
Das müsste ich nochmal nachgucken.
Vielleicht können wir das einfach dann beim nächsten Mal nachreichen oder so.
Auf jeden Fall, da gibt es etwas und das kriegt man schon irgendwie alles auch mit dazu geschrieben.
Ja, also genau, das ist eigentlich so wie früher.
Der Default ist immer noch bei Pandas.
Wie Sachen gespeichert werden, das nennt sich irgendwie Block Manager oder Block Storage.
Und das sind immer 2D NumPy Arrays.
Und die sind halt immer sozusagen...
Also man würde eigentlich denken, dass ein Data Frame, dass jede Spalte irgendwie ein 1D,
also ein eindimensionales NumPy Array ist.
Aber das ist halt nicht so, sondern ein Data Frame besteht aus Blocks von 2D NumPy Arrays,
jeweils zu einem, also unterteilt nach Datentyp.
Also wenn ich jetzt sagen habe, ein Data Frame, der 3 Spalten hat, 2 davon Float, 1 Integer,
dann besteht das Ding aus 2 NumPy Arrays, 1 mit Integer und 1 mit Float, das halt 2 Spalten hat.
Da muss man jetzt natürlich aufpassen, von welcher Seite man drauf guckt.
Weil aus Pandas Sicht ist das erstmal eine Liste von Pandas Series.
Da haben wir auch noch nicht drüber gesprochen, was das ist.
Also die Abbildung als NumPy Arrays ist natürlich dann irgendwie die technische zugrunde liegende Abbildung.
Ja, ja, genau.
Eigentlich sollte das egal sein.
Sollte man sich eigentlich keine Gedanken darüber machen, sondern eigentlich ist eine Series halt quasi,
kann man es verstehen als Spalte oder eben Vektor, eindimensionale Datenstruktur mit vielleicht noch einem Index dran.
Aber so wird es halt nicht gespeichert.
Und das Blöde ist, dass diese Abstraktion halt auch so liegt.
Weil wenn man jetzt...
zum Beispiel eine Spalte hinzufügt zu einem DataFrame,
dann hat man das Problem, dass dadurch, dass jetzt, wenn man schon ein paar Float-Spalten da drin hat
und man fügt jetzt eine dazu, dann geht das ja nicht mehr wirklich.
Sondern dann müssen die kompletten Daten alle kopiert werden dafür.
Und wenn man jetzt in der Schleife irgendwie Spalten hinzufügt oder so,
dann kann es sein, dass einem der Speicher platzt und man weiß überhaupt nicht warum.
Das heißt, man muss im Grunde wissen, dass Pandas das so macht.
Dann gibt es ja immer so Tipps, wie gesagt, wenn man da irgendwie viele Spalten hinzufügt,
dann immer erst mal die einzelnen Spalten sammeln und dann hinterher alle zusammenfügen oder so.
Nicht irgendwie auf einem großen DataFrame eine Spalte hinzufügen, dann noch eine hinzufügen, das ist schlecht.
Und das sollte eigentlich, das sind so Schwächen bei Pandas, das sollte einen gar nicht interessieren, wenn man das benutzt.
Dummerweise muss man solche Sachen aber dann vielleicht doch wissen, weil man halt dieses Problem da an der Stelle noch hat.
Aber das kann sein, dass das jetzt alles demnächst besser wird.
Und mit dieser Version, mit der letzten Version ist es halt schon ein Stück besser geworden.
Und da sind halt die einzelnen Spalten, haben ihren eigenen Typ und ihre eigene Speichergeschichte und dann ist alles nicht mehr so ein Problem.
Aber ja, das ist vielleicht auch noch interessant.
Also Pandas ist gedacht für so Daten, also Small Data kann man quasi sagen, also Daten im Bereich von so ein paar Gigabyte, also einstellig Gigabyte.
Weil halt da fast alle Operationen dazu führen, dass das irgendwie kopiert wird, kann es sehr schnell sein, dass man halt irgendwie auch,
fünf oder vielleicht sogar bis zu zehnfacher der Datenmenge, die tatsächlich auf der Platte landet oder so, man dann als Hauptspeicher braucht.
Weil man kopiert ein paar, man fügt ein paar Spalten hinzu, transformiert ein bisschen was und dann schon hat man irgendwie einen fünffachen Hauptspeicherverbrauch.
Und daher ist es halt nicht so richtig effizient.
Kann auch sein, dass es jetzt dann halt besser wird.
Aber also für größere Sachen kann man Pandas nicht so super benutzen.
Aber für diese kleinen Datenmengen ist es halt sehr, sehr cool, weil es super effektiv ist.
Da auch viel Optimierung reingesteckt wurde, die Operationen halt auch so auf den Datenmengen halt schnell zu machen, sodass man halt oft dann nicht ein paar Sekunden warten muss, sondern eigentlich immer nur so ein paar hundert Millisekunden.
Und gerade wenn man das zusammen mit Jupyter Notebooks halt interaktiv in einem Browser verwendet, ist es halt sehr wichtig, dass man da nicht irgendwie, wenn man irgendwas ausführt, halt lange warten muss, sondern man drückt irgendwo drauf, es wird ausgeführt, man sieht ein Ergebnis und kann damit direkt weiterarbeiten.
Ja, vielleicht noch mal kurz in Jupyter Notebooks, also tolles Tool tatsächlich, wenn man sich so gerade so Daten aus der Wissenschaft angucken will, einfach einen DataFrame laden, da die ganzen Daten reinkloppen und dann mit Matplotlib und C-Born irgendwo direkt live immer Anlehrungen verfolgen können.
Ja, ich würde fast noch sagen, also der ganz, ganz klassische Workflow ist, man ruft einmal Describe auf, dann kriegt man so einmal die Rahmendaten, Streumass und Lagemaß auf dem DataFrame.
Genau, .describe, Klammer auf, Klammer zu, fertig, dann kriegt man erstmal einen groben Überblick über seine Daten. Dann kann man natürlich auch in die Daten direkt reingucken mit Head und Tail. Und das ist in meiner Erfahrung auch das, was man bei einem neuen Datensatz als allererstes mal macht, um sich anzugucken, womit arbeite ich denn überhaupt.
Und spannenderweise, wir waren eben bei Datenimport, da ist noch eine Sache, meine Lieblingsfunktion ist an der Stelle tatsächlich Import from Clipboard.
Also man kann tatsächlich, wenn man gerade irgendwie mal in Excel war oder in OpenOffice und was kopiert hat, das in Pandas DataFrames direkt wieder einladen. Das habe ich allerdings noch nie ausprobiert in Jupyter Notebooks. Ich weiß nicht, ob der das hinkriegt, aber ich wüsste jetzt auch erstmal nicht, was dagegen sprechen sollte.
Nö, das kann gut sein, dass das funktioniert, ja.
Also kann man sich halt auch ganz kleine Datenchunks, kleine Tabellen direkt aus der Zwischenablage in sein DataFrame reinladen.
Das heißt, wenn wir jetzt von diesem Gigabyte-Bereich liegen, ich glaube,
für wissenschaftliche Anwendung müsste das in den meisten Fällen auch relativ ausreichend sein.
Ja, ja, absolut. Also das ist sowieso so, die allermeisten Leute haben nicht mehr Daten. Also für die allermeisten Leute reicht das aus.
Wenn man mehr hat, dann weiß man das und dann kann man auch was anderes nehmen.
Ja, aber stimmt, wir hatten eben noch gar nicht genau, vielleicht sollten wir da so ein bisschen systematisch auch nochmal kurz reingehen.
Also Pandas, genau, das hat auch was damit zu tun, wo der Name herkommt.
Also Pandas steht eigentlich für Penalty.
Penaldata, oder das war halt auch mal das, was halt so in der Finanzwelt, wo Leute von Geräte haben, von Penaldata.
Und damit meinen sie dann halt oft Excel-Sheets irgendwie oder mehrere davon.
Und das kann Pandas auch, ist aber irgendwie nicht mehr so.
Also es gibt auch noch, es gibt halt einmal Series, es gibt DataFrames, das ist halt sozusagen eine zweidimensionale Tabelle irgendwie.
Series ist eindimensional und dann gibt es auch noch Panels, die sind halt dann mehrdimensional.
Und die werden aber eigentlich nicht mehr verwertet.
Oder wurden eigentlich nie so wirklich viel verwendet.
Und das überlegen die Leute auch gerade, ob sie das irgendwie wieder rausnehmen, weil es eigentlich ziemlich sinnlos ist und der Hauptnutzen bei den DataFrames ist.
Ja, genau, daher kommt der Name.
Es ist ein bisschen blöd, wenn man danach googeln will und dann hat man Tierbilder.
Aber wir haben immer wieder Tierbilder dabei.
Auch interessant ist das Vorbild.
Vorbild für Pandas ist ja R, denke ich mal.
Das ist mit Googlen auch nicht viel einfacher.
Aber genau, ich weiß nicht, du hast auch schon mal mit R gearbeitet, Simon.
Was sind denn da so die, wie kann man das eigentlich miteinander vergleichen?
Oder ist da vielleicht auch ganz interessant zu sehen, wo das herkommt?
Ja, also ich habe in meiner Forschungszeit sehr viel zwischen R und Excel hin und her gewechselt.
Und tatsächlich muss ich sagen, die R...
Ja, DataFrames, die den Pandas DataFrames sehr, sehr ähnlich sind, die hatten irgendwie so zwei, drei zentrale Vorteile gegenüber Excel, weswegen ich irgendwann komplett gewechselt bin.
Einer ist sicherlich, dass die DataFrames immer rechteckig sind.
Also man kann nicht eine Spalte mit weniger Daten füllen als die nächste Spalte.
Es muss zu jeder Zeile immer für jede Spalte auch einen Wert geben.
Also es gibt für jeden Index irgendwie keinen Error.
Genau.
Wenn ein Not a Number ist, ist das okay.
Aber es muss auf jeden Fall irgendeinen Eintrag geben.
Das führt dann dazu, dass man keine Überprüfung mehr machen muss, wie lang ist denn meine Spalte gerade, in der ich bin.
Dann gibt es bei DataFrames grundsätzlich auch Typen je Spalte.
Das ist in Excel nicht so.
Da hat jede Zelle im Prinzip einen Typ, wenn man will.
Und da kann man auch ganz viel...
...bösen Schabernack mit treiben.
Und in DataFrames, dadurch einfach, dass man eine Series pro Spalte hat, hat auch eine Spalte immer nur einen Typ.
Und das Dritte, was ich an DataFrames unheimlich zu schätzen wusste, war, in A heißen die "Factors", in Pandas heißen, glaube ich, einfach nur "Categories" oder haben gar keinen speziellen Namen, dass, wenn man kategorische Daten hat, die erstmal als Texte...
...auch als Texte erscheinen, sowas wie blau, rot, gelb als Farben in einer Spalte, dass die in dem zugrunde liegenden Datenformat erstmal sowas wie Integers sind und entsprechend auch relativ schnell zum Indizieren benutzt werden können.
Das heißt, dass die Diktion-Lesbare wieder als rot, gelb, grün, blau dargestellt werden.
Okay.
Wie macht Pandas das?
Als Dictionary dann?
Oder...?
Das war lange...
Also, in Pandas heißen die Dinger "Categorials" und das wurde dann quasi intern irgendwie auf Integers abgebildet.
Man hatte die einfach durchnummeriert und dann war das halt, was halt natürlich auch viel weniger Platz braucht als Text, aber jetzt auch, glaube ich, mit 0.24 ist es jetzt so.
Und dann hat man halt so einen eigenen Datentyp bekommen, sodass es halt jetzt auch so ein First-Class-Citizen im Grunde ist.
So, vorher war es halt auch immer so, naja, es sind komische Dinge passiert.
Ich hatte zum Beispiel mal irgendwann mit Categoricals auch so ein Problem.
Ich hab da irgendwie größere Data-Frames irgendwie zusammengebastelt und dann ist mir irgendwie so regelmäßig der Hauptspeicher explodiert und ich wusste nicht warum, hab ich dann auch einen Bug irgendwie bei Pandas gefeilt und der war dann ziemlich lange offen und das hatte halt auch damit zu tun,
dass es nicht irgendwie nativ irgendwie da drin war, sondern das war halt mit den anderen Integers Geschichten irgendwie verknuselt und ja, das ist schrecklich.
Ja, aber genau, das ist natürlich eine sehr nette Sache, wenn man das halt so machen kann.
Ja, das heißt, man sieht halt den Text in der Tabelle, aber in Wirklichkeit speichert man halt viel weniger Daten, halt nur eine Zahl.
Ja, praktisch.
Wie schaut man sich denn so Daten dann an?
Ich musste ja irgendwie eine Struktur bringen.
Ich hab ja jetzt irgendwie ganz viele Spalten irgendwie mit Zeilen in meinem großen rechteckigen Datenfeld drin oder sowas und ich möchte jetzt irgendwie die kombinieren.
Also man kann auch direkt auf dem, also das benutze ich tatsächlich ziemlich gerne, ist, man kann sagen, also Data-Frame, man kürzt das normalerweise immer ab mit df, also das Standardobjekt, das man dann halt sozusagen hat, heißt einfach df und da kann man einfach sagen df.plot und dem halt noch so ein bisschen Parameter mitgeben und dann,
äh, plotet das halt direkt.
Dann kannst du ja dann Daten anzeigen, die du dann reingegeben hast, also ich, ähm, das, die Visualisierungsebene dann damit quasi.
Genau, genau, in einem Notebook sieht man halt auch dann direkt irgendwie quasi grafisch was.
Äh, standardmäßig ist es dann halt ein Matplotlib, aber man kann halt das auch, äh, das Plotting-Backend von Panda, äh, sozusagen austauschen, also es ist halt so pluggable und man kann das austauschen und man kann halt auch Bokeh zum Beispiel nehmen oder, äh, weiß gar nicht, es ist auch noch viel andere, ähm.
Ich hab Plotly schon gesehen.
Plotly, genau.
Und, äh, Seaborn ist ja im Prinzip Matplotlib nochmal ein bisschen erweitert, äh, kann man da auch rein, reinpluggen.
Genau, so dass es halt, äh, man hat halt immer, ähm, ähm, kann es dann anders aussehen lassen, so dass zum Beispiel bei, bei Bokeh oder, oder Plotly ist es halt so, wenn man dann sagt df.plot irgendwas, dann kann man das, dann ist halt, äh, ist das, was man sieht, dann halt auch scrollbar zum Beispiel, man kann da drin zoomen oder so, was man bei einem Matplotlib-Bild jetzt nicht machen kann, weil da ist einfach, das ist quasi dann halt so ein statisch rausgerendertes PNG oder so und dann, äh, wenn man da, äh,
da reinzoomt, dann wird es nur pixelig, aber, äh, man sieht nicht mehr, während halt bei, äh, eben dieser, äh, bei, bei Plotly oder so hat man dann, kann man, wenn man reinzoomt, sieht man einfach an der Stelle mehr und, äh, das, man muss an dem Aufruf, an dem Plotaufruf eigentlich nichts ändern, sondern man tauscht einfach nur das Backend aus und, äh, ja, das ist schon sehr nett und das verwende ich tatsächlich oft, äh, irgendwie um Sachen zu visualisieren, ja.
Also, wenn man gar nicht weiß, wie man anfangen soll, ähm, wenn ich mich richtig erinnere, macht Plot standardmäßig einfach ein Perplot, alles gegen alles, dann sieht man schon mal, wie sind die Daten zueinander verteilt, dann, äh, kann man Effekte sehen, wie, ähm, auf zwei bestimmten Variablen ist die Verteilung eher so bimodal, man hat zwei Felder von Punkten oder sowas, also da, da kann man schon grundsätzlich mal sehen, wie sind meine Daten überhaupt verteilt, äh, ansonsten, äh, gibt's ja oft eine Frage,
äh, eine Fragestellung, äh, in der ideellen Welt, äh, gibt's im Vorfeld eine Fragestellung und dann, äh, kann man auf diese Fragestellung hinzuarbeiten, dann weiß man genau, welche Spalten brauche ich jetzt gleich, ähm, Spaltenzugriffe, äh, sind in Pandas, finde ich, super, super easy und convenient, äh, man, man gibt im Prinzip einfach nur von seinem DataFrame-Objekt, ähm, per Dot-Syntax den Spaltennamen an oder in, ähm, eckigen Klammern wie bei einem Listenzugriff, ähm,
jetzt muss ich grad genau überlegen, äh, doch, da geht der Spaltenname auch, ja, es gibt, es gibt zwei Interfaces, es gibt halt mit, mit, ähm, man kann halt entweder den Namen nehmen oder man kann halt auch den numerischen Index nehmen, äh, das ist Log und iLog, glaube ich, sind die unterschiedlichen, äh, Funktionen, die man da aufrufen kann, aber, äh, also, ich würde auch eigentlich immer eher, also, die, die mit den Indizes ist eine ältere Geschichte und, äh, ich würde eher die Namen immer nehmen, weil das ist ja ein klarer, was, was da eigentlich gemeint ist, ja.
Also erstmal hat man Zugriff auf seine, äh, tabellarischen Daten und da kann man sagen, ich möchte jetzt, äh, Spalten A, B und E plotten, ähm, auf einer X-Achse, die ist in Spalte D meinetwegen.
Aber nur die roten oder die roten und die gelben vergleichen.
Genau, ähm, das ist dann der zweite Schritt, äh, dass man anfängt vorher zu aggregieren, man kann dann überlegen, äh, will ich, ähm,
nur bestimmte Gruppierungen haben, es gibt, äh, Funktionen, die heißen GroupBy, ähm, es gibt auch Funktionen, ähm, um, äh, eine kumulative Summe über irgendeinen Datensatz, äh, direkt per Funktion aufzurufen.
Das ist was, was man auch aufplott, einfach plotten möchte.
Dass man sagt, okay, ich hab jetzt hier meine Daten und, äh, ich plotte dahinter in einer zweiten Serie auch noch die kumulative Summe, dann, äh, ist das quasi per einzelnen Funktionsaufruf in Pandas möglich.
Ähm, ist darüberhin spannend für die ganze Anwendung, ne, wenn man irgendwie so kategorisierbare Daten mit verschiedenen Merkmalen hat und man dann, äh, bestimmten Merkmalen, bestimmte Wahrscheinlichkeiten zuordnen will, also mehrere Merkmale hat, also keine Ahnung, Leute ab zwei Meter und, äh, trotzdem unter, weiß nicht, 70 Kilo und, ähm, welche Wahrscheinlichkeit haben die für bestimmte Dinge im Vergleich?
Genau, da, da kommen wir in, in anderen Bereichen so ein bisschen rein und das ist, ähm, äh, Indizierung auf Basis von, von bullschen Werten, also man kann jetzt zum Beispiel sagen,
ich, äh, möchte aus meinem Datensatz eigentlich nur alle Zeilen auswählen, äh, in denen Spalte A, was zum Beispiel die Höhe sein könnte, sagen wir Höhe, äh, eines Menschen kleiner als 1,80 Meter und größer als 1,60 Meter ist.
Und dann würde der mir, ähm, entsprechend einen Slice aus meinem Data-Frame rausgeben, der nur dieser Bedingungen entspricht.
Was wird denn der technische Erzeuger? Also macht der eine Kopie der Tabelle mit diesen Werten oder setzt der halt dann noch eine
neue Tabelle daneben mit so Bullian-Werten, ist wahr, ist falsch oder, und macht da doch so ein Index, den er nur liest, oder?
Ähm, gut, also meistens wird tatsächlich, wenn man jetzt irgendwie, äh, da irgendwas extrahiert, wird, wird kopiert, man kann aber auch sagen, dass es nicht kopiert werden soll, ähm, ähm, ja, äh, also das sind meistens diese, diese Bullien, also im Grunde erzeugt das halt eine Spalte, äh, wenn man jetzt zum Beispiel sowas hat, man sagt, DF, eckige Klammer,
auf, irgendwie, ähm, DF.2 ist größer irgendwas und dann, und, äh, DF.2 ist kleiner irgendwas, äh, dieser, dieser, dieser Logo, äh, Bullscher-Ausdruck wird sozusagen dann halt, äh, irgendwie in eine Spalte verwendet, halt, wo dann irgendwie in jeder Zeile True oder False drinsteht.
Und dann wird das halt, wenn man jetzt zeilenweise filtert, äh, werden halt alle Zeilen, die halt, äh, True sind, raus, äh, werden halt rausgesucht und alle anderen werden halt ignoriert, quasi.
Ähm, und, ähm, ja, ganz genau, wie das technisch unten drunter funktioniert, weiß ich jetzt aber auch nicht.
Ähm, äh, und, ja, das sind halt so, ich kann mir vorstellen, dass irgendwie so ein NumPy halt irgendwie als Feature drin, dass man Sachen, dass man so Masken verwenden kann, aber ich bin mir nicht sicher, ob es wirklich verwendet wird, keine Ahnung.
Egal, muss man halt nochmal genauer nachlesen.
Ähm, ja, und, ähm, dann kann man da irgendwie weitere, weitere Dinge mitmachen.
Das ist, äh, das ist halt recht, äh, recht schön, schönes.
Schöne Methode, um da halt irgendwie Sachen rauszuselecten.
Vielleicht kann man an der Stelle auch mal grad, äh, ne, ne Blogartikel-Reihe erwähnen, das fällt mir da grad ein, ähm, die ich immer wieder, wenn ich irgendwie Leuten, äh, von Pandas erzähle, auch mit erwähne, weil die, weil die so toll ist.
und
ist von Tom Augsburger
ja genau, das heißt
Modern Pandas
und das ist Teil 1
bis, ich weiß gar nicht wie viel es gibt
bis 8
momentan
kenne ich noch gar nicht, muss ich auch mal reinschauen
so lernt man
immer dazu
genau und der beschreibt halt
sehr ausführlich wie das mit diesem Indexing
aus Userperspektive, was man damit alles machen kann
funktioniert
und ja
also gerade wenn man jetzt nicht nur einen Index hat
das ist auch etwas, was halt Pandas kennt
was ich von Datenbanken so nicht kenne
also Datenbanken bedeuten Indizes
ein bisschen was anderes als halt jetzt bei Pandas
man kann halt bei Pandas auch mehrdimensional
Indizes haben und dann halt irgendwie
kreuz und quer verschachtelte Abfragen macht
und da
wenn man das sich so zuerst anguckt, dann
raucht einem da relativ schnell so der Kopf
aber wenn man tatsächlich diese Probleme
hat, dann kann das ultra praktisch sein
wenn man da irgendwie sich mit auskennt
und diese Modern Pandas Serie ist halt eine
wo man das sehr schön
sehen kann, wie das funktioniert
im ersten Artikel werden glaube ich
da irgendwie so halt
diverse Indize-Geschichten erklärt
und dann gibt es halt einen Artikel
nur zu Method-Chaining
und ja
dann eins zu Indizes
und da wird dann auch nochmal das alte
Interface
gezeigt und halt was man jetzt
mit dem
neuen Interface an Dingen machen kann und da gibt es halt
wirklich verrückte Abfragen
die man
also
super spannend, was der neueste heiße Scheiß ist
was ich jetzt da gekannt habe, ist auch die einzige Quelle
deswegen habe ich jetzt den Vergleich natürlich wieder nicht
ist diese Einführung in
Python mit Data Science oder Data Science
mit Python von Jake Wanderplast
da ist auch ein schönes Artikel
zu Pandas drin, das ist auch frei
irgendwo bei GitHub
und sogar als Notebooks
die er alle gebraucht hat, da hat er irgendwie unter MIT
die Lizenz da online gestellt
und da kann man auch genau die Sachen als Notebooks direkt alle ausprobieren
das ist ein tolles Beispiel für diese, glaube ich, die
einfachen, so die Basissachen
drin, dass man das grundsätzliche alte Prinzip mal
versteht, das man direkt da mit Pandas potten kann
ich glaube über den Untergang der Titanic oder sowas
Ah ja
Ja, sonst benutzen die Tutorials
oft gerne den Iris-Datensatz
da geht es irgendwie um Blütenlänge
und Breite und
das war mir immer ein bisschen sympathischer als Biologe
Also welche
Klassen jetzt wie oder wie viele Frauen, Männer und
wie viele Jungs und Kinder
untergegangen sind, wie viele nicht
Das ist auch super spannend mit diesen
Multi-Level-Indizes
da sollten wir gleich auch nochmal vielleicht
ein paar Minuten uns Zeit für nehmen
Für den
Moment sei vielleicht
auch nochmal erwähnt, wenn man jetzt ein Pandas
DataFrame haben möchte und man
importiert das nicht aus einer Datei
oder aus der Zwischenablage
wie komme ich denn überhaupt zu meinem
DataFrame-Objekt und du hast eben gefragt
kann man da vielleicht Dictronix benutzen? Ja, kann man
tatsächlich. Also wenn ich in
Python schon ein Dictronary habe
was Keys und
als Values Listen hat
dann kann ich einfach
mein DataFrame erzeugen mit
pandas.dataframe oder
pd.dataframe, wenn man Pandas als
pd importiert
und da reingeben, mein Dictronary
dann macht er automatisch
aus den Keys Spaltennamen
und aus den Values, aus den Listen macht
er dann meine Series
hat natürlich
zur Bedingung, dass die gleich lang sind
sonst gibt es da einen Fehler
ich weiß gar nicht, ob der da mit na auffüllt
oder ob der
ja, ich bin mir gar nicht sicher
außer an das ein Fehler wirft, ich weiß es aber auch nicht
es gibt auch irgendwie so eine andere Funktion, ich weiß
jetzt nicht, bei was es genau geht, wenn man halt so ein DataFrame
über so ein NumPy-Array hat oder sowas
dass der automatisch neue Spalten erzeugen
kann, die er dann irgendwie
fortsetzt, ich weiß nicht, ob das linear passiert
oder sowas, habe ich irgendwie kurz entdeckt
wenn man einfach eine neue Spalte erstellt
dann, wenn man schon drei oder vier hat, dass
du dann, wenn du die fünfte erstellst, einfach dann
neue Werte reinbaut
kann sein, weiß ich nicht
vielleicht habe ich auch wieder
irgendwelchen Quatsch erzählt, ich weiß nicht
gerade nicht genau, was du da
meinst
jetzt habe ich das Buch natürlich zu Hause liegen lassen
irgendwo nachgeschlagen
Buch ist aber auch ein gutes
Stichwort, man
kriegt ja immer den gut gemeinten Ratschlag
guck doch mal ins Handbuch
das Pandas Handbuch ist tatsächlich
länglich, es hat
2900 irgendwas Seiten
davon sind
rund 900 so die Basisfunktionen
1400 nur die
API-Referenz und dann
nochmal weiterführende
Informationen
Hast du das durchgelesen?
Nee
So bei aller Liebe, das ist dann
doch etwas viel, aber
man kann halt relativ schnell kapitelweise
wenn man was ganz
bestimmtes sucht, da reinspringen
Es ist auch alles, also verlinkte
wie heißt das, Table of Contents
Inhaltsverzeichnis, genau
verlinktes Inhaltsverzeichnis, man kommt schnell dahin
Ja
Ja, die Dokumentation
von Pandas ist auch sehr gut, aber auch manchmal
die ist schon etwas trocken
manchmal muss man sich schon so ein bisschen
ein bisschen quälen
Vielleicht liegt das an dem Tabellenthema
Könnte auch, vielleicht liegt es einfach am Thema
Sollte man vielleicht eher irgendwie Schreiner werden
oder so
Das ist eigentlich total langweilig
Ja, das überlege ich mir manchmal
Das wäre toll
Ja, aber
genau
Stimmt, was hatten wir erwähnt
Was gibt es für Datentypen
so in Serien, Data Frames, Panels
Was kann man damit machen
Ja, so, genau
Man kann auch sehr viele Dinge
die man sonst vielleicht mit einer Datenbank machen würde
damit tun und das hätte ja auch so den Vorteil
Also das kann ich auch nur, ich finde
die Art, also das User Interface
von Pandas ist halt
ziemlich angenehm und ist auch relativ kurz
also wenn man in einer Datenbank arbeitet
und da SQL Statements schreibt, das geht natürlich auch
aber das ist halt viel
viel umständlicher
und Pandas hat halt eine sehr schöne
sehr schöne
sehr schöne UI eigentlich
und man kann viel damit machen
was man halt auch in einer Datenbank normalerweise tun würde
und insofern kann ich das auch nur empfehlen, wenn man jetzt irgendwie
so ein Datenbankproblem hat, man kann auch irgendwie die komplette
Datenbank, meistens sind die ja nicht so groß, auch irgendwie
in Pandas sich reinholen oder als Data Frames
aus der Datenbank ziehen und dann da
irgendwelche Dinge machen und dann schon mal
wenn man dann weiß, wie es geht, dann kann man es hinterher auch
in SQL machen, aber vieles
von dem lässt sich auch locker
in Pandas mal ausprobieren, weil Pandas hat ja eben auch solche
Funktionen wie, man kann Joins
machen, man kann halt Data Frames Merge
also da heißt das dann, also vielleicht
verwendet man eher den Aufruf Merge oder so
aber im Grunde macht das dann halt auch
ein Join zwischen zwei Data Frames, dann kann man
angeben, auf welchen Spalten gejoint
werden soll und solche Dinge
und genau, eben all diese
Group-By-Geschichten
gibt es tatsächlich so eine Funktion, wie man eine Datenbank in
Data Frame bekommt und andersrum, wie man eine
Data Frame, wie man irgendeinen Datenbank-Typen speichert?
Naja, also für alle Datenbanken
gibt es da Adapter, mit denen man
die Daten auch auslesen kann, ja.
Genau, also diese Import-Export-Geschichten
also wir haben nur über Import
gesprochen, aber
Export gibt es halt auch für alle diese
Daten-Typen. Warum schreibt dann irgendjemand noch
SQL-Statements?
Ja doch, also manchmal
es kann schon sinnvoll
durchaus sinnvoll sein,
also wenn du in der Datenbank ja auch irgendwas manipulieren
willst an Werten, dann musst du es ja tun,
kannst ja gar nicht, kannst du auch in Pandas machen,
aber dann hast du das Problem, musst du es ja irgendwie wieder zurück in die Datenbank
schreiben und dann...
Dann markierst du eine neue Datenbank.
Ja, und gegebenenfalls
ist das, was du in deinem Speicher
bearbeiten kannst, auch
kleiner als das, was
in der gesamten Datenbank ist, das heißt,
beim Import würdest du schon nur einen Teil aus der
Datenbank nehmen, kannst damit aber
dann relativ komfortabel rumspielen.
Ja.
Tatsächlich, der Befehl
ist Join, auch in
DataFrames. Ich verwechsel das auch immer wieder,
deswegen habe ich gerade mal kurz nachgeguckt.
Und es gibt noch Concatenate,
da kann man aus einem DataFrame irgendwie
Spalten in ein
anderes reinziehen.
Ja, und dann genau
solche, eben es gibt
so Datenmanipulationsgeschichten,
eben Join, Merge,
dann gibt es noch
solche Sachen wie,
genau, das ist auch schwer
zu erklären, wenn man das jetzt nur hört,
fürchte ich,
sowas wie Pivot,
Unpivot, Melt,
Stack, Unstack, so sehr praktische
Geschichten, aber ich weiß jetzt ehrlich gesagt nicht genau,
wie ich das erklären kann. Ja, du kannst,
also wenn du, hm, okay, ich versuch's
mal einfach, wenn du jetzt,
du machst im Grunde aus einer,
aus
Dingen, die in einer Spalte
stehen, machst du mit Pivot
irgendwie zusätzliche Spalten.
Achso, ich bin gerade völlig auf
den Kopf gefallen, ich hab's natürlich mit der Transformation gerade
verwechselt. Ja, so Transpose,
ja, das ist natürlich, das ist
relativ einfach, aber Pivot, das macht schon
so ein bisschen kompliziertere Dinge. Das aggregiert
irgendwas zur besseren Auswertung.
Einen Widerfall,
doch? Ne, das, das,
ja, also manchmal hat man Daten halt in einem Format,
in dem man schlecht plotten kann.
Und manchmal braucht man
halt Dinge, die in einer Zeile, die
irgendwo in einer Zeile stehen, die möchte man als Spalte haben,
um dann halt die Spalte besser plotten zu können, und dafür
fällt man dann auf Pivot. Und dann, äh,
äh, genau, die umgekehrte Funktion
dazu ist Melt, äh, und,
ähm, die, äh,
aber eigentlich noch allgemeineren Funktionen,
die funktionieren dann eben auf so, äh,
Multilevel-Indizesen, halt Stack und Unstack.
Ja. Aber das kann auch sehr schnell,
äh, einen so ein bisschen überfordern.
Also ich kann sagen, so aus
dem Biologen-Alltag, dass ich Pivot
und Melt nie benutzt hab, ähm, einfach,
weil, weil die vielleicht
auch zu viel Magie im Hintergrund noch machen
können. Äh, Stack und Unstack
aber sehr häufig, weil, äh,
in der, in der Realität
sind, äh, wir hatten ja eingangs
über die Excel-Tabellen gesprochen,
die nicht immer ganz maschinenlesbar sind.
Es gibt noch den Zwischenwert,
wo die zwar maschinenlesbar sind,
aber mehrere Level von Indizes
haben, und, äh, wenn
die mehrere Level von Indizes haben,
man könnte sich das zum Beispiel vorstellen
wie, ähm,
ähm, weiß ich nicht,
ein, äh,
ich hatte eben noch
ein Beispiel im Kopf, äh, äh,
äh, sowas wie, äh,
Klausurnoten nach Semestern
in zwei verschiedenen
Gruppen, sagen wir mal,
Biologen versus Chemiker oder sowas,
ähm, wie die in der Chemieklausur
abschneiden im ersten Semester,
im zweiten Semester. Und
dann hat man diese Gruppierung einmal,
ähm, zu welcher Gruppe
gehören die Personen an, aber
dann hat man auch, äh, für
jede Zeile im Prinzip eine spezifische
Person.
Das heißt, mehrere Personen
teilen die gleiche Gruppe,
also Biologe oder Chemiker,
ähm, aber jede Person hat
eigene Noten in Semester 1,
in Semester 2. Wenn man das
jetzt, jetzt muss ich kurz überlegen, in welche
Richtung man das stacken würde,
dann würde man im Prinzip
sagen, ich, ähm,
schreibe jetzt
jede
Person einzeln als Zeile
auf und habe eine neue Spalte, wo
die Gruppe nochmal als sich wiederholender
Wert mit drin steht.
Sodass ich wegkomme von
ich habe, ähm, im Prinzip
zwei Zeilen, die jeweils vier Unterzeilen
beinhalten, zu ich
habe einfach acht Zeilen, äh,
wo in, in jeder dieser
Zeilen die Gruppe nochmal explizit drinsteht.
Ähm, das
macht es dann einfacher nachher Gruppierungen
zu machen. Außerdem könnte
man dann mit Unstack in die andere
Richtung wieder sagen, ich möchte das jetzt
gar nicht nach den Gruppierungen unstacken, sondern
nach Semestern zum Beispiel. Und dann
tauscht man plötzlich die, die Spalte
identitäten. Aber ja, also,
Tabellentransformationen
einfach nur in einem Audio-Podcast zu erklären,
ist sehr schwierig.
Genau, ich, ja, ich weiß gar nicht, ob
es, ob es zu dem Stack-an-Stack oder so, äh,
äh, Thema halt auch ein Modern
Pandas Artikel gibt.
Ich fürchte, nein. Ah, schade.
Ah ja, muss man einfach mal nach, äh, also,
na ja, ich verlinke da einfach mal einen Artikel zu,
wie das, wie das so aussieht. Wenn man das sieht,
ist es eigentlich, dann kann man's, kann man's deutlich
besser verstehen. Ja.
Genau, das sind so die Dinge, die man dann, dann
mit dann tut. Hm.
Ja.
Äh.
Ja, vielleicht noch mal dieser Pivot, äh, kurz, das
wart ihr gerade kurz dabei, das sind wir kurz abgeschweift.
Mhm. Also, was macht man damit
jetzt genau? Also, ich kenne das irgendwie jetzt auch irgendwie aus Excel, wenn man
eine Auswertung hat, man hat dann irgendwelche Datenblätter
oder sowas, und dann möchte man dann
irgendwelche Aggregate
irgendeinem Endnutzer auf einem
Auswertungs-Dashboard zur Verfügung
stellen. Und da wird dann irgendwas zusammen
gerechnet.
Hm.
Ja, Excel genau kann ja auch sowas
so, Pivot-Tabellen. Ja. Also, ich hab hier
gerade mal das, das, äh, Data Science
Cheat-Cheat-Panda ist offen. Ah.
Können wir auch nachher verlinken. Ja.
Ähm, und da steht im Wesentlichen drin,
dass, äh, Pivot-Table,
wie gesagt, ich hab's noch nie benutzt, aber dass es, ähm,
eine
Pivot-Tabelle macht, die
äh, die
anhand von einer Spalte
gruppiert, und dann
aber über andere Spalten eine Funktion
aufruft. Das kann zum Beispiel sowas sein,
wie Mittelwert oder eine Summe oder
ähm, nahezu
beliebige Funktionen.
Hm.
Möglicherweise
hab ich das auch nie
benutzt, weil ich die Excel-Funktion
nie benutzt hab. Ähm,
was ich allerdings öfter benutzt hab,
ist, äh, die Funktion Apply.
Und Apply erlaubt einem jetzt
innerhalb eines Data Frames an,
auf, auf Basis einer
Achse sozusagen, eine
Funktion auszuführen. Das kann auch wieder
nur Mittelwert oder Standardabweichung
sein. Das können aber
auch, äh, komplexere Funktionen
sein. Und, ähm,
also
für, für die, die vielleicht schon Hintergrund
in R haben, da gibt's, äh,
T-Apply und L-Apply für
Zeilen, Spalten und was weiß
ich nicht alles. In Pandas
Data Frames gibt's im Wesentlichen Apply und
man gibt die Achse an. Also soll das
auf Reihen, auf Spalten,
äh, äh, agieren. Hm.
Und dann gibt man eine Funktion an und die
wird dann entsprechend für
eine komplette Spalte oder eine komplette
Zeile ausgeführt.
Ja, das ist vielleicht eben, genau, das ist auch noch ein ganz wichtiger
Punkt, den wir noch gar nicht erwähnt haben, dass
man, man kann, was man nicht tun sollte,
äh, äh, über Data Frames iterieren
und dann in der Vorschleife da irgendwelche
Dinge mitmachen. Ja, das könnte man sich auch vorstellen,
dass man das so tut, weil
das, wenn man das, äh, wenn man
aus Python kommt, äh, dann macht man das ja mit
Listen normalerweise so. Aber, äh,
das geht halt nicht, oder das geht schon,
ist halt nur dann sehr, sehr langsam.
Äh, während halt, wenn man jetzt
Apply aufruft, dann, äh, ist das halt
ziemlich schnell.
Äh, weil unten drunter, äh,
weil eben, also, vor, vor Loops in Python
sowieso langsam sind und man dann eben
keine Vorloop machen muss, sondern das läuft halt
alles, äh, irgendwie in, in, in den entsprechenden,
also kommt, je nachdem, hm,
wie der Datentyp ist, aber möglicherweise
halt landet das in einer dieser optimierten
vortragenden Bibliotheken, die unten drunter unter
der Lampe, äh, liegen. Und es
ist halt auch so, dass es dann in gewisser Weise schon
parallelisiert wird. Und halt diese, diese
ich weiß jetzt gar nicht, wofür SIMD steht,
diese Instruktions-Test,
diese Single Instruction Multiple Data.
Ah, okay. Ja, äh, genau.
Super. Dankeschön.
Äh, da, wo, ja, man
spricht da auch von Vektorisierung. Also, man,
ähm, äh, kann
halt mit einem Taktzyklus
halt mehrere, äh,
Operationen oder ausführen,
weil man hat so super lange Register,
äh, weiß ich nicht, vielleicht
512, äh, Byte oder so.
Und da sind dann halt viele, äh,
äh, wenn man jetzt Integer hat,
4 Byte, äh, Werte drin. Und die werden
dann halt alle addiert gleichzeitig oder
multipliziert oder sowas.
Und man zerlegt halt ein komplettes, äh,
äh, Array sozusagen, auf dem man
irgendwelche Dinge macht, halt in diese Blöcke
und kann, braucht dann halt viel weniger Takte,
als wenn man da einen For-Loop drüber machen würde.
Ja, und das ist,
macht Sachen super schnell, ja. Also das,
man hat halt, äh, irgendwie so
Python-Interface mit einem Jupyter Notebook,
das sieht dann halt so aus, als hätte man so super,
wäre man super high-levelig, aber wenn man eine Operation macht,
kann es sein, dass dann tatsächlich etwas sehr, sehr
Optimiertes, äh, passiert und es sehr schnell
ist und man, wenn jemand da hingehen würde,
würde es ein C schreiben, ist er möglicherweise
deutlich langsamer, wenn er, wenn er
nicht genau weiß, was er tut.
Ähm, und das ist natürlich für viele
Leute auch total überraschend, äh, äh, und
das ist auch eine sehr, sehr, sehr, sehr schöne Geschichte.
Aber ja, man muss halt, äh,
man muss halt auch so ein bisschen eine komische
Syntax dafür, äh, halt in Kauf nehmen.
Man kann halt nicht mehr For-Loops machen, man muss halt
immer Apply schreiben und dann halt eine
Funktion übergeben. Oft übergibt man dann halt so anonyme
Funktionen, schreibt dann Apply und dann Lambda,
X und dann kriegt man halt, äh, irgendwie ein Wert übergeben
und macht dann damit irgendwas. Ja.
Ähm. - Comprehensions oder sowas kann man auch
vergessen, genau, das selbe Problem. - Genau, das
geht alles nicht mehr. Ja.
Man schreibt halt alles nur noch, äh,
ja, quasi, ja, man
schreibt eigentlich fast alles in Apply. Ich weiß gar nicht, ob es
da noch andere Funktionen gibt, die so ähnlich sind wie Apply.
Naja.
Ne, das war eigentlich immer
Apply, ja.
Ja, ja, und dann chained man
halt die Sachen hintereinander.
Man kann halt dann, diese
Methode liefert dann halt das Ergebnis von dem Apply
zurück, dann, äh, ruft man
darauf wieder was anderes auf und dann hat man halt eine ganze Reihe
von so hintereinander gechaineden Apply aufrufen
unter Umständen. Und, ähm, ja.
Ähm.
Das ist auch, auch witzig, äh, äh,
fällt mir grad noch zu dieser Vektorisierungsgeschichte
ein, ähm,
früher haben auch
Leute irgendwie, äh, erzählt,
naja, ach, das mit dem, mit der
Parallelisierung, das ist ja alles gar kein Problem, wenn wir jetzt
viele CPUs haben, so, äh, irgendwie,
die, die, äh, Steigerung der Taktfrequenz war ja dann
irgendwann auch schon vor längerer Zeit irgendwie vorbei,
mehr oder weniger, und man muss halt,
man kriegt halt mehr Prozessoren, also
Moore's Law ist halt noch nicht wirklich weg, weil sich
das eigentlich auch nur auf die Transistoren, nicht auf, äh,
die Geschwindigkeit als solche irgendwie bezieht.
Ähm, aber, äh,
dann hieß es halt so, naja,
das, das ist kein Problem, wenn man mehrere Prozessoren hat,
da gibt's halt bestimmt Compiler, die das automatisch parallelisieren
oder so. Ne.
Ist nicht passiert, wird's auch nie
passieren, dass Sachen automatisch
parallelisieren geht halt nicht. Und, äh,
das Schlimme ist, selbst so was
wie automatisch vektorisieren geht halt nicht.
Weil, äh,
dummerweise, wenn man jetzt, äh,
in, in C, na, wenn man sich jetzt
mal vorstellt, man schreibt eine Vorschleife, die jetzt
zwei Vektoren addiert,
äh, also sagen wir mal so, die macht einfach nur
C gleich A plus B.
Wobei jetzt C, A und B sind
halt, äh, Vektoren der gleichen Länge.
Äh, naja, C ist der, der
erzeugt wird. Äh,
und man macht halt einfach vor, look, die das tut,
dann denkt man sich jetzt, könnte doch eigentlich der
Prozessor, äh, der, der Compiler hingehen und, äh,
das, äh, irgendwie in diese
Single Instruction Multiple Data, äh,
äh, Prozessorbefehle umwandeln
und dann irgendwie, äh, das deutlich schneller machen,
stellt sich heraus, nein, kann er nicht, weil,
äh, in C ist es, äh, ändert es
halt die Semantik von deinem Programm.
Weil, es könnte ja auch sein, dass
dieses C irgendwie, äh,
wieder was mit deinem A
und deinem B zu tun hat und die
Reihenfolge, in der du Sachen addierst,
sich auf die nächste Addition irgendwie auswirken.
Sodass halt, wenn du das in der Vorlog machst, kommt halt was
raus, als wenn du das parallel machst.
Und dann muss der Compiler natürlich sagen,
so, nee, kann ich nicht automatisch optimieren, weil,
weiß er nicht, vielleicht ist das irgendwie, hat das,
ist das die Programmlogik, dass das so sein muss.
So, das heißt, bei sowas
Simples geht's schon nicht. Also man kann natürlich irgendwie
dann so, äh, äh,
Hinweise an den Compiler dazuschreiben, also
man sagt so, hier ist okay, darfst du schon optimieren,
mach da mal, äh, aber
so generell kann ein Compiler das nicht machen.
Und damit ist es natürlich schon irgendwie,
ja, und das ist
einer der Gründe, warum das auch in Fortran so
viel, äh, schöner funktioniert ist, weil da
gehen solche Sachen nicht. Da kannst du nicht, äh,
kann nicht das Ergebnis, ähm,
einer Addition in,
bei, wenn du, wenn du zwei solche Arrays
addierst, äh, äh, kann
nicht sich auswirken auf die nächste,
sozusagen. Das ist, das T kann nicht irgendwie wieder
zu A oder zu B gehören. Sodass,
da das ausgeschlossen ist, kannst du in,
in Fortran solche Operationen halt automatisch
vektorisieren. Also einer der Gründe, warum das halt
irgendwann auch alles irgendwie Fortran ist.
Äh, auf der anderen Seite, das müsste nicht unbedingt,
du kannst auch ein C machen oder ein C++, wenn du
das halt dem Compiler entsprechende Hinweise gibst. Aber
es ist alles irgendwie nicht so, nicht so ganz einfach.
Und, ähm, ja.
Wahrscheinlich will man sich da auch nicht mit rumschlagen.
Aber wenn man einfach so Paddler verwendet, dann passiert das ja alles automatisch
und man hat nichts damit zu tun. Das ist gut.
Ja.
Ja, ähm,
genau.
Vektorisierung hatten wir dann.
Genau, was wir vielleicht nochmal, äh,
ein bisschen detaillierter ansprechen können, ist irgendwie
das Plotting. Also es gibt, äh,
für jedes DataFrame erstmal
ein DotPlot. Und da kann man
noch ein paar Parameter angeben und seinen Plot
konfigurieren. Es gibt auch
noch eine Reihe von anderen Funktionen.
Ich hab die auch nie alle im Kopf.
Aber da gibt's irgendwie noch Scatter und Box.
Und da hat man dann verschiedene
Diagrammtypen auch standardmäßig
schon vorimplementiert.
Damit man sich nicht mehr darum kümmern muss,
die Plot-Funktion entsprechend durchzukonfigurieren.
Sondern man bekommt
direkt die Plots, die man haben möchte.
Ja.
Und, ähm,
eine Sache, die ich ganz schön finde, ist,
man kann als Spalten
da auch wieder die Spalten-Namen angeben.
Man muss jetzt nicht irgendwelche
Koordinaten in dem DataFrame angeben,
sondern man sagt: Plotte bitte
Höhe, Breite,
Länge gegen Zeitachse.
Und dann passiert
das genau so.
Das ist einfach auch dann
deutlich besser lesbarer
und wartbarer Code, den man
schreibt. Ja.
Ja.
Welche
präferiert ihr von diesen Plotting-Bibliotheken?
Also jetzt so irgendwie Matplotlib mit Seaborn
oder dann doch Bookie, oder?
Ich verwende
meistens Seaborn tatsächlich, ähm,
in Notebooks.
Aber, ähm,
es kommt halt drauf an,
auf den Einsatzzweck. Also meistens
müssen die für mich nicht interaktiv sein.
Und dann verwende ich halt Seaborn.
Weil es einfach netter aussieht, als Matplotlib direkt zu verwenden.
Und das ist halt auch irgendwie einfacher.
Es gibt halt manche Plots, das geht auch
mit Matplotlib, aber, äh,
es ist halt schon so ein bisschen, also
ehrlich gesagt, ich mach das meistens so,
dass ich auf Seaborn, äh,
auf der Seaborn-Dokumentation halt dann so
angucke, was ich so grob brauche. Und dann
scrolle ich halt durch die Beispiele, bis ich irgendwas gefunden habe.
Dann kopiere ich den Aufruf und modifiziere
den so lange, bis es halt irgendwie funktioniert.
Ähm,
wenn man jetzt mit Matplotlib hingehen würde
und das so nachbauen würde, dann
ist das, äh, ist das halt
deutlich schwieriger. Und, äh,
es geht natürlich auch, Matplotlib ist, Seaborn baut
darauf auf, und Matplotlib ist sehr mächtig.
Aber es ist, äh, die API ist nicht
so ganz einfach. Und, ähm,
eigentlich musste ich da nie, da ich auch nie so
wirklich komplizierte Visualisierungen mache, musste ich da nie so tief
einsteigen, dass ich das irgendwie wirklich
gebraucht hätte, sondern für mich reicht Seaborn meistens aus.
Und dann gibt's aber natürlich auch noch Fälle,
wo man das halt, ähm,
äh, so ein bisschen interaktiv braucht, wo man
in, da drin zoomen können möchte, oder man möchte
es auf einer Webseite haben. Und
dann, ähm, ja,
ist eher sowas wie Bokeh oder Plotly,
äh, das, was man da verwenden möchte. Also,
äh, grad wenn man jetzt, also Plotly hab ich
glaub ich auch schon mal für so Dashboards
oder so, kann man das ganz gut verwenden.
Äh, man kann tatsächlich, äh,
relativ einfach eben, wenn man jetzt eine Datenbank
hat oder so, dann zockt man daraus wieder DataFrames.
Und, äh, die kann man dann
sehr einfach mit, mit Plotly, äh,
irgendwie auf einer Webseite visualisieren. Und dann
können sich die Leute, die
das angucken, halt auch dann, äh, irgendwie
den Bereich, der sie interessiert, halt irgendwie auswählen.
Und, ähm, daran zoomen und so.
Ja. Also ich bin auch totaler
Plotly-Fan, ähm,
äh, im Wesentlichen, was da rauskommt
als, als Graph ist ne
kleine HTML-Seite oder auch nur
ein Snippet, das man einbinden kann.
Und, äh, zugrunde liegt
im D3JS, das ist eine Visualisierungs-
Library in JavaScript.
Und, äh, das hat
super viele Funktionen, aber ich benutze
das hauptsächlich dafür, dass
man einen Mouse-Hover auf den Datensatz
hat. Man fährt halt
über den Graph drüber und man sieht den exakten Wert,
nochmal an der Maus. Äh, das ist so
die, die, die wichtigste
Funktion, die ich an Plotly immer wieder nutze.
Ähm, das kann man aber auch beliebig
weitereskalieren noch. Es gibt jetzt neu,
äh, von Plotly Dash, das
ist ein ganzes Dashboard mit
Plotly-Grafen, geschrieben in
Flask. Und, äh,
das kriegt man auch superschnell
hochgefahren. Und es gibt sogar inzwischen
ein GitHub-Projekt, das, äh, ne Django-Anbindung
für, für dieses Plotly-Dashboard
macht. Also, ähm,
da kann man dann im Wesentlichen ne
ganze Website mit Datenvisualisierung
als, als Django-Applikation
direkt ausliefern.
Was auch ziemlich nett ist,
hab ich aber noch nicht im Detail ausprobiert.
Gibt's sowas auch für R?
Ja, ja, ja, so, äh, man muss sogar sagen,
der Dash ist halt so im Nachbau von etwas,
was halt in R super populär
ist. Und das ist, in R heißt das Shiny.
Ja, genau. Und, ähm,
das, äh, ist
eigentlich immer noch so ein bisschen der, der Goldstandard für,
für diese, diese Geschichten, weil,
also, ich weiß nicht, wie weit, also,
ich hab jetzt auch schon lange nicht mehr angeguckt, aber,
wie weit Dash da jetzt ist, ob sie, also,
äh, ob sie das schon, ob sie da, da
dran sind, aber, ähm,
man hört immer noch, dass, dass viele Leute sagen,
so, ah, aber Shiny ist schon irgendwie toller
und ich mag das lieber als irgendwie,
da gibt's noch keine so richtige Alternative in der
breiten Welt, so, ja. Ich mein, äh,
da, da guckt auch jeder vom anderen ab, ehrlicherweise.
Also, ähm, äh,
R hat auch irgendwann angefangen
mit diesen Notebooks und, ähm,
hat jetzt die Möglichkeit, ganze Berichte
in Markdown zu mischen,
mit ausführbaren Codes zählen.
Also, im Prinzip das, was man mit Jupyter
Notebooks für Python hat, gibt's
auch in R. Ähm,
da, da, die, also, das
ist so eine Co-Evolution der beiden,
äh, der beiden
Analyse-Workflows, sag ich mal.
Ja, wobei man sagen muss, dass die ursprüngliche
Idee, äh, für diese Notebook-Geschichte,
ähm, die Art, wie wir das, das kommt aus
Mathematica, ähm,
und es gibt schon ganz lang,
äh, aber ist nie, hat sich nie
so wirklich durchgesetzt, bis dann,
äh, äh, das,
dann, äh, jemand als, äh,
äh, eben, bis, bis Leute das dann halt,
äh, irgendwie dieses Jupyter-Projekt, äh,
also das aus dem IPython, äh,
Interpreter halt, äh, irgendwie rausgewachsen ist, äh,
bis das da implementiert wurde.
Und ich hab jetzt auch letztens gehört, dass jemand, äh,
also den Mathematiker-Autor
gefragt hat
warum das jetzt, warum das eigentlich nicht
Open Source wäre, weil das hätte so
sich doch jetzt irgendwie durchgesetzt und voll toll
und so und das
die Idee war ja vorher schon da, aber
ist unbekannt geblieben und
äh, ja
Steven Waffram hatte glaube ich so
ja, also ich hätte das ja schon gerne als
Open Source irgendwie veröffentlicht, aber das ging damals nicht
weil es keine Distributionsmöglichkeiten
dafür gab, das wurde halt alles irgendwie auf
CDs und DVDs
irgendwie, tja
ja, es ist manchmal
es ist komisch, ne, so irgendwie Idee
es reicht nicht irgendwie, dass eine Idee super ist oder so
sondern es müssen mehrere Sachen zusammenkommen, damit
irgendwas wirklich dann abhebt
und manchmal
ja, kommt
dann, denken Leute, dass irgendwie eine Idee
erst kurz gibt oder so, das gibt sie schon ganz lange
aber die Umstände waren halt nicht
nicht richtig, so dass sie halt
vorher halt noch nicht abheben konnte
und das ist bei diesen
diesen Jupyter-Notebooks ist das halt schon, ich denke, das war halt genau
der richtige Moment und jetzt ist es halt groß geworden
und, ähm, ja
Shiny, let's be bad guys
Ich meine, gerade im Data-Science-Bereich, wo man
schnell viele Dinge ausprobieren
muss, ohne Skripte von Anfang
neu laufen zu lassen
äh, ist natürlich der
Killer-Anwendungszweck für diese Notebooks
Ja
Ja, haben wir noch was hier für
Pandas?
Ja, also Pandas ist ja nie
isoliert zu betrachten
Wir haben ja jetzt ganz viel schon auch über
NumPy gesprochen, über Seaborn und Mudplotlib
und, ähm, die eine
Bibliothek, die ich eingangs noch mit erwähnt hatte
war Studs Models
und die bringt
da im Prinzip noch eine Funktionalität
rein, die ich persönlich auch erstmal nur von
A kannte
und zwar ist das
ähm, Formeln
anzugeben
auf die man dann Fitting machen
kann oder die man auch plotten kann
und diese, diese Formeln
das ist vielleicht erstmal
ungewohnt, wenn man das noch nie gesehen hat
gibt man im Wesentlichen irgendwie an
als, äh, sagen wir mal eine
Geradengleichung y tilde x
also, äh, eine Variable
y, die abhängig ist von
äh, einer Variable x
und als lineare Funktion zu
verstehen ist und
ähm, in diesem
Studs Models gibt's, äh, die
ähm, die Funktionen
von OLS, um diese Formeln abzubilden
die kann man dann auch mit
Pandas Data Frames zusammen benutzen
um wieder Plotting zu machen
also, OLS meinte Optimal Linear
Squares Modeling, oder?
ähm, müsste ja
äh, Ordinary
Ordinary Linear
äh, least squares oder sowas
ich weiß nicht mehr, keine Ahnung
also im Wesentlichen irgendwie, ähm
äh, lineare Gleichungen
an, anzugeben, da gibt's auch noch ganz
viele andere Möglichkeiten, ähm,
das ist nur jetzt der, der einfachste Fall
immer, wo man eine lineare Gleichung
angibt
und, ähm, diese Variablen, die man
da angibt, ähm
die
können in meinem Pandas Data Frame
zu finden sein
und dann kann ich, äh,
das Plotting darüber machen
da kann ich einmal die Trendlinie direkt plotten
ich kann das Fitting direkt über die Pandas Data Frames
machen, also die, die greifen
da irgendwie, also alle diese Bibliotheken
greifen sehr stark ineinander
und da würde es auch gar nicht
reichen, die 2900 Seiten des
Pandas Handbuchs komplett zu lesen
weil man müsste halt auch
noch das NumPy Handbuch komplett lesen
und dann vielleicht das, äh, Matplotlib Handbuch
noch komplett lesen und
ähm
Also falls ihr die 2900 Seiten Handbuch gelesen habt
dann sagt mal Bescheid und schreibt uns eine E-Mail
Ja, äh, genau
ich, ich, äh
Satzmodels, äh, kenne ich auch so
was Zeitreihen, äh, Modellierungs
Geschichten angeht, aber habe ich noch
noch nie so wirklich viel mit, äh, ähm
gemacht, ähm
ich bin eher so bei
Scikit-Learn zu Hause und, ähm
also Maschinen-Learning-Bibliothek
äh, und auch da ist es so, also meistens
bevor man halt irgendwelche, äh, bevor man
Daten irgendwie in Modelle kippen kann
ähm, muss man die halt mit Pandas einmal
aufräumen und dann war es halt so, früher musste man dann
immer noch so, okay, ich hab das jetzt in einem
Data Frame, mhm, wie kriege ich die Daten jetzt
äh, ah, wie kriege ich die Daten
äh, äh, jetzt so
dass ich die an meine Modelle verfüttern
kann, und das war auch mal so ein bisschen
problematisch und das ist jetzt aber auch schon
weiß nicht, letzte oder vorletzte
Version, äh, von Scikit-Learn war
auch kein Problem mehr, weil man jetzt
automatisch auch, weil man jetzt auch nicht
früher brauchten die ganzen
äh, äh, also in Scikit-Learn
heißen die Dinger Estimators, äh,
Estimator API, die haben halt
äh, NumPy-Arrays genommen und jetzt
mittlerweile nehmen die halt auch Pandas, äh, Data Frames
und, äh, die Spalten einmal halten
und wenn man halt irgendwie hinterher gucken
möchte, okay, was ist denn jetzt,
wo gelandet und so, und, äh,
dann kann, kann man da auch mit den Spalten
haben, arbeiten und das ist alles sehr, sehr bequem geworden
und das greift halt auch da wiederum ineinander
und das ist halt eigentlich sehr schön
und was da, also, das ist, das ist
ein, ein großes Data Science Ökosystem
mittlerweile und das ist halt schon toll
äh, ah, dazu fällt mir ein, genau
äh, Sparse
äh, äh, Data ist natürlich auch so ein
Problem, da gibt's, äh, irgendwie
ein Sparse-Type von
Sci, SciPy, das hat man früher
immer verwendet, es gibt ein paar Modelle, die
halt in Scikit-Learn mit, mit Sparsen-Daten umgehen
können, also das sind halt, also Spars heißt
ähm, äh,
Daten, bei denen die
meisten Werte null sind
äh, also zum Beispiel
wenn man, wenn ich jetzt einen Text in, in
oder eine Menge von Texten in
äh, Lektoren
verwandle, dann ist jedes Wort
eine Dimension, sozusagen, und das heißt
ich hab eine Tabelle mit, wenn ich
äh, einen kompletten, wenn ich eine Menge
von Texten, äh, in, in, in
eine Matrix verwandeln, in so eine Feature-Matrix
verwandeln möchte, äh, und dann ist
jedes Dokument ist eine Teile, und, äh,
die Spalten sind halt die Worte, die
drin vorkommen, dann sind halt, die
kommen halt, äh,
die meisten Worte, die es so
gibt, in einem Text aber nicht vor, das heißt, die
allermeisten Werte sind halt null,
und das ist halt blöd, das ist halt dicht zu speichern,
diese ganzen Nullen immer mit zu speichern, weil eigentlich
interessieren die einen ja gar nicht, und
dafür gibt's dann so, so Spars, äh,
Formate, und dann gibt's dann, ja,
CSA, äh,
äh, äh, oder, oder
CSO-Formate in, in, in
Sci-Py, aber das ist
halt auch alles ein bisschen unschön,
und, ähm,
in, äh, jetzt eben der letzten
Release von Pandas war auch ein natives
Spars-Datenformat mit drin,
das hab ich mir aber noch nicht angeguckt, aber das sieht auch
interessant aus, ich weiß auch nicht, ob man das jetzt in, in
Sci-Cat Launcher verwenden kann, aber
das ist, äh, genau, das
wird halt auch noch mit abgedeckt,
und, ähm, ja,
das ist auch noch so ein nicht uninteressantes
Detail.
Gibt's noch andere, äh,
Bibliotheken aus den Web- und Sci-Learn
Starts Models, Sci-Py,
ja, äh,
die ganzen Visualisierungsgeschichten,
ähm,
oh, ja, doch eine, eine Geschichte,
äh, auch noch, äh, wichtig,
wenn man jetzt, äh, tatsächlich, äh,
äh, größere Datenmengen hat, oder halt auch,
äh, Operationen, die lange dauern, und man hatte
irgendwie so eine dicke Kiste mit irgendwie,
äh, weiß ich nicht,
64 Prozessoren, irgendwie
in einem halben Terabyte Hauptspeicher oder so,
äh, und, äh,
man ist so ein bisschen angeödet davon,
dass das irgendwie immer nur auf einem Prozessor läuft,
dann kann man da was tun.
Da gibt's ein auch sehr schönes Projekt, das nennt sich
DARS, ähm,
und damit kann man das halt so ein bisschen
auf mehrere Prozessoren skalieren, also was das,
äh, letztendlich tut, ist,
ein DataFrame halt in viele Kleider
zu zahacken, und dann halt, äh,
die Operationen halt
auf Prozessoren zu
verteilen, und dann halt das hinterher wieder zusammenzuführen,
aber es kann halt
komp-, also, ich hab mehr oder weniger
beliebige Compute
Drafts kann man da irgendwie angeben,
so, es ist halt, äh,
einfache Dinge sind halt einfach
damit zu parallelisieren, wenn man komplizierte Sachen
machen möchte, dann muss man dann auch so ein bisschen nachdenken
und dann halt eventuell, äh,
sich überlegen, wie man das halt ausgeführt kriegt, aber,
äh, im Grunde
funktioniert das so, man hat halt so eine Deferred
API, man sagt halt, was man tun möchte, und dann am Schluss
sagt man irgendwie jetzt Collect oder so,
und dann, äh, oder, äh,
ich glaub, weiß gar nicht, also,
man ruft halt irgendwie eine Funktion auf, die
sagt so, und jetzt rechnet das halt alles mal aus, und dann
wird das halt auf die unterschiedlichen Prozessoren verteilt,
wird alles ausgerechnet, und am Schluss hat man
das alles wieder in einem DataFrame, und, ähm,
die Geschwindigkeit
hat sich dann, wenn man Glück gehabt hat,
halt irgendwie linear, äh,
ähm, ist dann
linear skaliert, und man braucht nur noch ein Sechzigstel
der Zeit, oder so, ja.
Ähm, genau.
Das ist auf jeden Fall auch ein Ding,
was man sich auch angucken sollte, also,
was, was zu Skalierungsgeschichten angeht, ja, wenn die Datenmengen
dann noch viel größer sind, so, oder dass sie halt
nicht mehr in den Hauptspeicher auf einer Maschine passen, oder so,
äh, dann
muss man sich nochmal was anderes überlegen, dann, äh,
bleibt eigentlich nur, dass man das dann,
dass man irgendwie dann in Richtung
Spark geht, oder sowas.
Aber diesen, diesen Fall hat man fast nie, äh,
weil mittlerweile,
ja, die Maschinen so viele Hauptspeicher haben, dass das irgendwie
kaum vorkommt.
Wenn's nicht mehr in den Hauptspeicher passt, Geld dagegen
werfen und mehr Hauptspeicher besorgen.
Ja.
Ja, wenn wir schon beim halben Terabyte
angekommen sind, da ist ja schon noch ein bisschen Platz.
Ja.
Geht eine ganze Menge rein.
Ja, so, Skalierung hatten wir jetzt auch
so ein bisschen. Wir hatten noch, glaube ich, dieses, äh,
äh, Wes McKinney, hast du kurz erwähnt,
da hatten wir, glaube ich, einmal in unserer Weihnachtsfolge
dieses Ten Things I Hate About Pandas, irgendwie.
Ah, ja, ja, ja, genau.
Ähm, ich weiß nicht, ob da noch was rauskam.
Ja, der, ähm,
also, er arbeitet
halt hauptsächlich an dem Arrow-Projekt,
dass, da geht's darum, eine neue Grundlage zu schaffen,
äh, und zwar nicht nur
für Python, sondern, ähm, für
äh, alle anderen
Programmiersprachen auch, weil man hat halt das Problem, dass man
man möchte eigentlich
nicht, wenn man Daten hat, die groß sind,
und, äh, man möchte die nicht
mehrfach im Hauptspeicher halten, aber momentan kommt man nicht drum rum,
wenn man jetzt, äh,
beispielsweise in R
und in Python irgendwie auf Daten
irgendwie was machen möchte, dann muss man die
halt irgendwie erst, wenn man die jetzt in Python
hat, serialisieren, irgendwo hin auf die Platte schreiben,
dann in R wieder einlesen und
hat sie dann, im Endeffekt zahlen wir im Hauptspeicher, was natürlich
irgendwie doof ist, äh, und
das Projekt ist sozusagen, äh,
äh, äh,
stellt halt sozusagen Schnittstellen für alle Programmiersprachen
bereit, aber die Daten selber
werden nur, äh, im Hauptspeicher
an einer Stelle gehalten, da kann man mit allen Sprachen,
also, was weiß ich, von Java bis C,
äh, C++, Rust,
äh, was auch immer, irgendwelche Leute schreiben gerade eine Query Engine
für Arrow in, in Rust,
äh, Python A, äh, darauf zugreifen
und, äh, da irgendwelche
Manipulationen drauf machen,
äh, ohne dass es halt dann
jedes Mal eine Kopie macht. Und das ist
natürlich auch eine sehr, sehr interessante Geschichte,
weil das ist eben,
davon hatten wir jetzt ja auch schon ein paar Mal,
äh, irgendwie momentan so ein, wenn man mit so
Big Data-Geschichten, Hadoop-Clustern zu tun hat,
so ein Problem, dass man da nicht so gut an die
Daten rankommt, ähm,
und, ähm,
ja, das war auch eines der ersten
Geschichten, die Arrow gemacht hat, war, äh,
Parquet
Fileparser, äh,
zu implementieren, sodass man halt zumindest
die Files, äh, in denen die Daten liegen,
halt irgendwie lesen kann.
Ähm, ja, und, äh,
ähm,
das, äh, das ist, das ist,
glaube ich, also mittlerweile
funktioniert das irgendwie fast allen Sprachen,
dass man das halt sozusagen als,
äh, ähm,
äh, Ersatz für NumPy auch nehmen
kann, äh, äh,
und, dass das, also eine, eine
Geschichte ist so, dass, dass in, in,
in Pandas das nicht so wirklich schmerzfrei
NumPy aushauschen kann, weil das halt,
äh, viele Sachen in, in Pandas
beruhen halt darauf, dass NumPy so ist, wie es ist.
Das wird halt schwierig. Da gibt's auch, äh,
eine Serie von Artikeln zu,
nennt sich Pandas 2.0 irgendwie,
wo man dann halt überlegt, dass man die API
so nicht abwärtskompatibel ändert.
Das, das hat
Wesmerkini 2015 ein paar Artikel
geschrieben. Bisher ist da nicht so viel
passiert, aber man müsste, wenn man jetzt komplett auf Arrow umsteigen
wollte und so, dann müsste man da wahrscheinlich, äh,
irgendwie viel auch an dem Frontend
von Pandas ändern und das wird dann
nochmal, nochmal schwierig.
Ähm,
und, äh, ist es so, dass, äh,
was auch noch in, in nächster Zeit
bei Arrow ansteht, ist, es gibt
so einen großen, so ein großes
Kluft, äh, zwischen dem, was halt
im Datenbankenbereich passiert ist
und dem, was halt in, äh,
im Data Science-Bereich passiert ist und
da geht's auch darum, das so ein bisschen
anzugleichen. Also, was man zum Beispiel nicht hat, ist eine
Query-Engine für Arrow. Also, das wird, da
wird halt grad geschrieben. Also, nächsten,
ich glaub, das ist das Projekt so für die nächsten drei, zwei, drei Jahre
in Arrow ist halt so, wer
doch schickt, da auch so eine SQL-Engine
drauf zu haben, sodass man halt Arrow
auch als, ja,
Ersatz oder Alternative
zu Impala oder sowas halt auf Clustern
verwenden könnte.
Weil das ist im Grunde auch eine, äh, SQL-Engine
äh, in C geschrieben,
die halt, ähm,
äh, äh, die halt auf so einem
Hadoop-Cluster laufen kann. Ähm,
und dann
kann das aber viele der Sachen, die man halt in so
Datenbanken hat, auch noch nicht. Also, ganzen
Indiz-Index-Geschichten und so
und, ähm,
ja,
da, da, da, da, da läuft
das aber irgendwie so hin. Also, ich meine, wenn man jetzt
sich so eine ideale Zukunft mal ausmalen
würde, könnte,
würde ich sagen, wäre das eigentlich sowas, man hat, äh,
äh, äh, irgend so ein
In-Memory-Storage, äh,
also In-Memory-Storage-Arrow oder so.
Man hat, äh, irgendwie
als Frontend etwas Pandas-ähnliches.
Ähm, es gab da auch schon
einen, ähm, Ansatz von, äh,
eben auch wieder von West McKinney, das ist so ein zentraler
Figur, äh, das nennt sich Ibis, das
Projekt, äh, wo es darum geht,
eine, ein Superset
von SQL zu haben,
das möglichst Pandas-ähnlich ist,
ähm, mit dem man aber all das
machen kann, was man sonst auch mit SQL-Datenbanken macht.
Und, ähm,
ja, das halt auch so eine, so eine
Default-Execution-Geschichte macht,
dass man halt hinterher nur sagt, äh, irgendwie man, man
definiert die ganzen Transformationen, Abfragen,
die man da macht und dann am Schluss sagt man, so, und jetzt ausführen
und dann geht das quasi an so ein
Cluster raus. Und das ist,
Und mit SQL auch alles. SQL ist sowieso blöd, weil diverse Geschichten gehen halt mit SQL nicht so richtig gut. Also man kann auch Tests für SQL schreiben, aber das ist alles ziemlich hässlich. Und man kann auch nicht so wirklich Code sharen. Also es gibt nicht so etwas wie Funktionen, aber wenn man ähnliche Abfragen macht in unterschiedlichen Kontexten, dann kopiert man oft die Statements und so. Das ist alles nicht so schön.
Und das ist halt mit so einer Notation wie in Ibis halt deutlich besser, weil da kann man das einfach in Funktionen packen und die Funktionen woanders halt verwenden und so. Und das geht halt schöner.
Ja, und das dann halt auch nochmal ändern. Bei einem SQL-Statement könntest du das ja auch in eine Funktion packen, aber das Problem ist, dann hast du halt genau dieses Statement. Du kannst das Statement kaum ändern. Außer du nimmst halt ein ORM, aber ORM ist dann auch wieder eigene Probleme.
Und ja, also ich würde mir eine ideale Welt, würde ich mir so vorstellen, also für kleine Datenmengen funktioniert man das.
Das ist ja schon super. Bis auf diese kleinen Hässlichkeiten wie eben NAN und diese Block-Storage-Geschichten. Aber das kriegt man ja alles in den Griff mit der Array-Extension-API.
Aber für große Datenmengen, dass man halt so etwas Ähnliches hat wie Spark oder auch der DOOP, also man hat einen großen Cluster, wo dann in Memory halt die ganzen Daten in Apache Arrow quasi liegen und man dann auf Arrow aufsetzend irgendwelche Query-Execution-Engines hat, die man füttert.
Von einem Pandas-ähnlichen Frontend aus, wo man dann halt definiert, was man gerne hätte und das dann halt irgendwie auf den Cluster verteilt wird.
Also man hat irgendwie so eine Art Array-Datenbank, verteilte In-Memory-Array-Datenbank mit so einer vielleicht Intermediate-SQL-ähnlichen Query-Engine hat, aber so als Frontend sowas wie Pandas.
So dass man dann halt auch wirklich große Datenmengen einfach so Transformation machen kann wie in Pandas.
Das wird vielleicht noch ein paar Jahre dauern, aber das wäre so das, was ich mir wünschen würde, was passiert.
Und dass man vielleicht irgendwann dann tatsächlich Pandas 2.0 hat, wo man nochmal komplett neu irgendwie diese ganzen Geschichten, die in der Kombination mit einem API halt nicht so toll sind, gelöst werden.
Aber das kann auch sein, dass das nie passiert, weil so viele Leute jetzt Pandas verwenden.
Ja, ich weiß nicht, von meiner Seite, ich wüsste jetzt spontan nichts mehr.
Wenn ihr mich jetzt fragen würdet, fragt doch mal.
Was sind so die drei wichtigsten Sachen, die ich mit nach Hause nehmen muss, wenn ich mal mit Pandas anfangen möchte?
Was sind die wichtigsten drei Sachen, die du mit nach Hause nehmen musst, lieber Simon, wenn du mal mit Pandas anfangen möchtest?
Ich würde sagen, Describe, Plot und Apply sind so die drei ganz zentralen Dinge, die man sich angucken möchte, weil da kann man fast alles schon mitmachen.
Ja, okay.
Ja, ich würde sagen, Read CSV sollte man sich auch mal angucken.
Ja, okay, also Datenimport, ja.
Aber sonst, ja, nee, klar, doch.
Ja, schön, schön.
Ja.
Schöne Strukturierung mit unseren Daten über Pandas, ich finde es hervorragend.
Ja, dann würde ich sagen, sind wir mit dem Pandas-Thema tatsächlich für heute soweit durch.
Und vielleicht machen wir noch so ein bisschen Abschluss und erzählen noch ein bisschen was von euren Lieblings-Picks oder sowas.
Ja.
Erstmal.
Sieben, möchtest du anfangen? Irgendwie hast du einen Lieblings-Pick, irgendein Modul, weißt du?
Muss ich kurz einen Moment drüber nachdenken.
Bitte, dann ist nicht offen zuerst.
Ja, ich überlege gerade, ob ich irgendwas Pandas-mäßiges habe, aber ich fürchte, nee, ich, was man sich mal angucken kann, ist eine Bibliothek namens Alkali.
Das ist so ein Django-ORM-Style-Ding, aber für flache Files.
Und das ist halt auch ganz, ganz nett, wenn man jetzt irgendwie zum Beispiel irgendwelche, wenn man halt Django kann zum Beispiel und den ORM da schon so ein bisschen damit schon so Sachen gemacht hat, dann kann man halt auch da auf CSVs oder so halt Dinge machen, die so ähnlich sind.
Also das ist quasi so die umgekehrte Richtung. Also wahrscheinlich wäre es praktischer, wenn man Pandas kennt, das halt mit Pandas zu machen, aber wenn man das nicht kann, dann kann man halt auch irgendwie, wenn man Daten als CSV ausgeschrieben hat oder so, damit irgendwie wie auf einer Datenbank.
Das fand ich ganz witzig, die Idee. Deswegen würde ich das mal, das mal picken, aber ja.
Ja, ich würde tatsächlich Pickel nehmen. Ich weiß nicht, hatten wir das schon mal oder so? Ich fand das total super, dass man da so Python-Objekte speichern kann.
Stimmt, nee, das hatten wir noch nicht. Ist auch Teil der Standard-Bibliothek und genau, daher muss man nichts zusätzlich installieren. Das ist super, das, ja.
Kann man eigentlich auch mit DataFrames machen, oder? Ich weiß jetzt nicht, wie schnell sowas geht und ob man das nicht lieber in einer Datenbank dann speichert, aber.
Doch, kann man mit DataFrames auch machen. Ist auch tatsächlich ziemlich schnell.
Wenn man keine Lust mehr hat und wieder anfangen muss, immer an der gleichen Stelle zu debuggen, dann lädt man einfach dann irgendwann den Pickel ein oder so.
Ja, ja.
Und spart sich dann immer die Zeit beim Ausführen.
Ja, also genau, das ist, nee, das ist tatsächlich, wenn man, also ich finde DataFrames zu picklen, es funktioniert ganz gut.
Also man muss, man muss vielleicht dazu sagen, man muss dem Ganzen vertrauen.
Also wenn man, wenn einem jemand so ein Pickel-File gibt, ist das so, hier, so ein, wie war das bei der Sesamstraße immer so, macht so ein French-Code auf, so.
Willst du ein Pickel-File von mir realisieren?
Genau, dann lieber nicht machen, weil das kann, führt halt beliebigen Code aus und ja, das ist vielleicht nicht so schön.
Aber wenn man das selber generiert hat, dann ist das vielleicht okay.
Und dann ist es auch sehr schnell.
Also.
Da kann man durchaus, also wenn die, wenn die I.O., ich habe das nicht an die Grenzen, oder war da, nee, ich glaube, ich habe das tatsächlich nicht, nicht an die Grenzen bringen können, sondern das war immer so schnell, wie halt das Plattensystem drunter war.
Also ich habe damit auch schon, da ging halt so Gigabyte pro Sekunde, geht halt durch.
Also bei CSV ist, CSV ist richtig langsam.
CSV ist halt so, wenn es schnell ist, ein paar 10 Megabyte pro Sekunde, was halt, wenn du ein paar Gigabyte große Files hast, dann dauert das.
Und Pickel ist halt so, selbst wenn die Files Gigabyte groß sind, kannst du dann das halt, wenn das I.O.-System, das du hast, schnell ist, dann dauert das halt, zwei Sekunden ist das da.
Und das ist natürlich schon schön.
Es gibt andere Formate für, gerade um Daten wie in DataFrame, man sehr oft hat, irgendwie zu speichern, HDF5 zum Beispiel, oder Feather gibt es da auch eine Library, wo das auch veraltet eigentlich.
Heute würde man eher dann eben Arrow verwenden und dann ein paar K-Files lesen und schreiben.
Das ist auch sehr schnell.
Ähm, HDF5 ist, geht so, ist ein bisschen, ist nicht ganz so schnell, aber, ja, lassen wir mal, gibt es sonst noch irgendwelche Formate, die interessant sind?
Es gibt dieses NetCDF4, das ist die Weiterentwicklung von HDF5 und, ähm, da hat man dann...
NetCDF4 ist die Weiterentwicklung von 5?
NetCDF4, ähm, das ist schon die vierte Iteration von NetCDF, aber irgendwann sind die wohl aus HDF entstanden.
Wie das genau zustande gekommen ist, weiß ich auch nicht.
Äh, die haben dann so, so Späße wie, ähm, man kann direkt FileBlobs angeben und dann über mehrere Files eine Variable öffnen.
Äh, das ist ganz spannend, wenn man sehr große, äh, Datensätze als Chunks auf, auf seiner Festplatte hat.
Ähm, aber technische Details dazu weiß ich jetzt auch nicht.
Tja, Tim, hast du noch ein Lieblingsmodul?
Ja, ich hab ja eben schon gesagt, ich mag Plotly unheimlich gerne, aber wenn man Plotly grafen,
erstellen möchte, dann muss man irgendwie so ein ganz tief verschachteltes Data-Dictionary bauen
und dann ein Layout-Dictionary bauen und super viel konfigurieren.
Und Matplotlib geht halt schnell.
Und, ähm, Plotly hat kürzlich noch ein Tool rausgebracht, Matplotlib-to-Plotly-Grafen,
wo man, das, das funktioniert noch nicht perfekt, aber so, so die Basis-Grafen wie Boxplots oder Scatterplots oder sowas
kriegt man damit in Matplotlib ganz schnell definiert.
Irgendwie mit zwei, drei Zeilen Code und dann mit einer Zeile konvertiert in Plotly-Grafen.
Und dann hat man direkt dieses interaktive, ähm, man hat Mouse-Hover und man kann zoomen und, und so.
Das, das fand ich ganz schön, ist aber noch, ähm,
In den Kinderschuhen.
Ist noch in den Kinderschuhen, ja.
Ja, aber schön, das spannend zu verfolgen, ja.
Cool.
Ja.
Habt ihr noch irgendwas, was ihr loswerden wollt, irgendwie das, euer Modul der Woche, oder sind wir damit durch und, äh?
Loswerden.
Nö, ich glaub damit.
Achso, vielleicht, ja, äh, wollen wir, äh, genau, nächste Woche ist vielleicht ganz interessant, wenn, äh, irgendjemand da ist, der, der zuhört, zufällig, aber ich glaub's, glaub's wahrscheinlich eher nicht, äh, so, Podcast-Konferenz in Köln.
Ja, die Subscribe.
Bei uns genau um die Ecke ist, da gehen wir auch mal hin.
Genau, und da wüsstet ihr uns finden.
Und, äh, genau, da könnte man, äh, uns, äh, treffen, wenn man, wenn man wollte, also.
Ja, das.
Wer möchte, kann einfach eine Mail an uns fragen, ja.
Das, das kommt in den Veranstaltungen bei Ihnen, genau, aber ihr könnt uns sehr gerne treffen, tatsächlich.
Wir wissen noch nicht genau, ob wir Freitag und Samstag und Sonntag da sind, aber, äh, auf jeden Fall am Samstag und am Sonntag wird ihr das wahrscheinlich, äh, da sehen.
Das, äh, besprechen wir noch genauer.
Ja, kommst du.
Äh, ist ja immer mal wieder Django zur Sprache gekommen.
Anfang April ist die DjangoCon in Kopenhagen.
Oh, ja.
Vom 10. bis zum 14. April ist es, glaub ich.
Sieht man dich da?
Äh, mich nur am 9. April.
Äh, da ist das Django Girls Camp.
Einen Tag Django, ähm, äh, lernen.
Ja, ja.
Äh, da fliege ich kurz hin als Mentor.
Ich habe leider für die Konferenz selber keine Zeit.
Ja, ja, okay, super.
Ja, äh, wolltest du noch was zu, zu dem Cast sagen, zum Django-Cast, Jochen, oder machen wir das von anders?
Äh, ähm, ja, also da, letztens gab es irgendwie so ein, so ein, äh, Mail von Apple, wo sie gesagt haben, also, wir werden euch jetzt nicht direkt auslisten, äh, irgendwie, aber ihr solltet dann mal vielleicht irgendwie ein paar Sachen an eurem Feed ändern, dann muss ich jetzt nochmal rein.
Zum Beispiel sowas wie Episoden, Nummern sollten nicht im Titel sein und so.
Das machen aber alle, äh, ich auch.
Können wir doch nochmal irgendwas dran tun und, ähm, genau, ich, äh, ja, wir machen da auch so einen kleinen Workshop, äh, irgendwie auf dem, auf der Subscribe und, äh, müssen wir auch noch ein bisschen was für tun.
Und da wäre es natürlich auch interessant, was dann noch so, also, was ich jetzt schon implementiert habe, ist, dass man jetzt nicht mehr das Django-Admin-Interface braucht, um, äh, irgendwie Audio-Files hochzuladen.
Ähm, aber, ja, mal gucken.
Was dann noch so da dazukommt und dann, was, was super dringend ist, äh, ist irgendwie, dass die Dokumentation mal so ein bisschen besser wird und so.
Mal gucken, ob ich die drei Zeilen zuschraffe.
Ja.
Also mindestens so, so den, den First Step oder so.
Ja.
So den, den großen Struggle.
Ja, wenn ihr irgendwie so Anfänger seid wie ich, dann kommt ihr da bestimmt noch irgendwo dran.
Ja.
Ja, ansonsten.
Ja, dann vielen Dank, dass ihr zugehört habt heute wieder.
Dass ihr eingeschaltet habt.
Wie auch immer, wann auch immer, wo auch immer.
Mhm.
Lasst uns das übrigens wissen.
Schreibt eure E-Mails, Kommentare an hallo-at-python-podcast.de und, ja, kippt uns.
Äh, weiter an alle Leute, die Python interessiert in eurer Nähe, erzählt eure Freunden, Kommilitonen.
Äh, ja, das kann man vielleicht auch, also was man auch machen kann, ist, äh, auf iTunes bewerten, wenn das irgendwie, äh, weil, also das hilft natürlich stark.
Ähm, aber, äh, genau, ähm, ansonsten, ja.
Ja, genau.
Sagt Bescheid.
Erstmal, äh, hört uns gerne, vor allen Dingen wieder und so.
Bleibt uns gewogen, wie man so schön sagt.
Und bis zum nächsten Mal.
Bis zum nächsten Mal.
Tschüss.
Vielen Dank für die Einladung.
Tschüss.