Wie man gute reproduzierbare Pandas Beispiele macht

221

Nachdem ich eine anständige Zeit damit verbracht habe, beide zu beobachten und Tags auf SO, der Eindruck, den ich bekomme, ist, dass pandasFragen weniger wahrscheinlich reproduzierbare Daten enthalten. Das ist etwas , dass die R - Gemeinschaft ziemlich gut über ermutigend war und dank Führer wie diese , Neulinge können etwas Hilfe auf die Zusammenstellung dieser Beispiele erhalten. Menschen, die diese Anleitungen lesen und mit reproduzierbaren Daten zurückkommen können, haben oft viel mehr Glück, Antworten auf ihre Fragen zu erhalten.

Wie können wir gute reproduzierbare Beispiele für pandasFragen erstellen ? Einfache Datenrahmen können zusammengestellt werden, z.

import pandas as pd
df = pd.DataFrame({'user': ['Bob', 'Jane', 'Alice'], 
                   'income': [40000, 50000, 42000]})

Viele Beispieldatensätze benötigen jedoch eine kompliziertere Struktur, z.

  • datetime Indizes oder Daten
  • Mehrere kategoriale Variablen (gibt es ein Äquivalent zur expand.grid()Funktion von R , die alle möglichen Kombinationen einiger gegebener Variablen erzeugt?)
  • MultiIndex- oder Panel-Daten

Gibt es für Datensätze, die mit wenigen Codezeilen nur schwer zu verspotten sind, ein Äquivalent zu dput()Rs, mit dem Sie kopierbaren Code generieren können, um Ihre Datenstruktur neu zu generieren?

Marius
quelle
8
Wenn Sie die Druckausgabe kopieren, können die Antwortenden meistens read_clipboard () ... verwenden, mit Ausnahme von MultiIndex: s. Das zu sagen, Dikt ist eine gute Ergänzung
Andy Hayden
8
Zusätzlich zu dem, was Andy gesagt hat, denke ich, dass das Einfügen von Texten df.head(N).to_dict(), bei denen Nes sich um eine vernünftige Zahl handelt, ein guter Weg ist. Bonus + 1 für das Hinzufügen hübscher Zeilenumbrüche zur Ausgabe. Bei Zeitstempeln müssen Sie normalerweise nur from pandas import Timestampden Anfang des Codes hinzufügen .
Paul H

Antworten:

323

Hinweis: Die Ideen hier sind ziemlich allgemein für den Stapelüberlauf, in der Tat Fragen .

Haftungsausschluss: Eine gute Frage zu schreiben ist SCHWER.

Die gute:

  • Fügen Sie einen kleinen * Beispiel-DataFrame hinzu, entweder als ausführbaren Code:

    In [1]: df = pd.DataFrame([[1, 2], [1, 3], [4, 6]], columns=['A', 'B'])

    oder machen Sie es "kopieren und einfügen" mit pd.read_clipboard(sep='\s\s+'), Sie können den Text für die Stapelüberlauf-Hervorhebung formatieren und Ctrl+ verwenden K(oder jeder Zeile vier Leerzeichen voranstellen) oder drei Tildes über und unter Ihrem Code platzieren, wobei Ihr Code nicht eingerückt ist:

    In [2]: df
    Out[2]: 
       A  B
    0  1  2
    1  1  3
    2  4  6
    

    Teste pd.read_clipboard(sep='\s\s+')dich selbst.

    * Ich meine wirklich klein , könnte die überwiegende Mehrheit von Beispiel Datenrahmen sein weniger als 6 Zeilen Bearbeiten , und ich wette , dass ich es in 5 Reihen tun. Können Sie den Fehler mit reproduzieren df = df.head(), wenn Sie nicht herumspielen, um zu sehen, ob Sie einen kleinen DataFrame erstellen können, der das Problem zeigt, mit dem Sie konfrontiert sind?

    * Jede Regel hat eine Ausnahme, die offensichtliche ist für Leistungsprobleme ( in diesem Fall verwenden Sie definitiv% timeit und möglicherweise% prun ), wo Sie generieren sollten (erwägen Sie die Verwendung von np.random.seed, damit wir genau den gleichen Frame haben) : df = pd.DataFrame(np.random.randn(100000000, 10)). Zu sagen, dass "diesen Code für mich schnell machen", ist für die Site nicht unbedingt ein Thema ...

  • Schreiben Sie das gewünschte Ergebnis auf (ähnlich wie oben).

    In [3]: iwantthis
    Out[3]: 
       A  B
    0  1  5
    1  4  6
    

    Erklären Sie, woher die Zahlen stammen: Die 5 ist die Summe der B-Spalte für die Zeilen, in denen A 1 ist.

  • Zeigen Sie den Code an, den Sie versucht haben:

    In [4]: df.groupby('A').sum()
    Out[4]: 
       B
    A   
    1  5
    4  6
    

    Aber sagen Sie, was falsch ist: Die A-Spalte befindet sich im Index und nicht in einer Spalte.

  • Zeigen Sie, dass Sie einige Nachforschungen angestellt haben ( durchsuchen Sie die Dokumente , durchsuchen Sie StackOverflow ), und geben Sie eine Zusammenfassung:

    Der Dokumentstring für sum gibt einfach "Summe der Gruppenwerte berechnen" an.

    Die groupby-Dokumente geben hierfür keine Beispiele.

    Nebenbei: Die Antwort hier ist zu verwenden df.groupby('A', as_index=False).sum().

  • Wenn es relevant ist, dass Sie Zeitstempelspalten haben, z. B. wenn Sie ein Resampling durchführen oder so, dann seien Sie explizit und wenden Sie pd.to_datetimediese für ein gutes Maß an **.

    df['date'] = pd.to_datetime(df['date']) # this column ought to be date..

    ** Manchmal ist dies das Problem selbst: Es waren Zeichenfolgen.

Das Schlechte:

  • Fügen Sie keinen MultiIndex hinzu, den wir nicht kopieren und einfügen können (siehe oben). Dies ist eine Art Beschwerde mit der Standardanzeige von Pandas, aber dennoch ärgerlich:

    In [11]: df
    Out[11]:
         C
    A B   
    1 2  3
      2  6
    

    Der richtige Weg ist, einen normalen DataFrame in einen set_indexAufruf aufzunehmen:

    In [12]: df = pd.DataFrame([[1, 2, 3], [1, 2, 6]], columns=['A', 'B', 'C']).set_index(['A', 'B'])
    
    In [13]: df
    Out[13]: 
         C
    A B   
    1 2  3
      2  6
    
  • Geben Sie einen Einblick in das, was es ist, wenn Sie das gewünschte Ergebnis erzielen:

       B
    A   
    1  1
    5  0
    

    Seien Sie genau darüber, wie Sie die Zahlen erhalten haben (was sind sie) ... überprüfen Sie noch einmal, ob sie korrekt sind.

  • Wenn Ihr Code einen Fehler auslöst, schließen Sie den gesamten Stack-Trace ein (dieser kann später bearbeitet werden, wenn er zu laut ist). Zeigen Sie die Zeilennummer (und die entsprechende Zeile Ihres Codes an, gegen die er ausgelöst wird).

Das hässliche:

  • Verlinken Sie nicht mit einer CSV, auf die wir keinen Zugriff haben (im Idealfall überhaupt nicht mit einer externen Quelle verknüpfen ...)

    df = pd.read_csv('my_secret_file.csv')  # ideally with lots of parsing options

    Die meisten Daten sind proprietär. Wir erhalten Folgendes: Machen Sie ähnliche Daten und prüfen Sie, ob Sie das Problem reproduzieren können (etwas Kleines).

  • Erklären Sie die Situation nicht vage in Worten, wie Sie einen DataFrame haben, der "groß" ist, und erwähnen Sie einige der Spaltennamen nebenbei (achten Sie darauf, ihre d-Typen nicht zu erwähnen). Versuchen Sie, auf viele Details einzugehen, die völlig bedeutungslos sind, ohne den tatsächlichen Kontext zu sehen. Vermutlich wird niemand bis zum Ende dieses Absatzes lesen.

    Essays sind schlecht, mit kleinen Beispielen ist es einfacher.

  • Schließen Sie nicht mehr als 10 (100+ ??) Datenzeilen ein, bevor Sie zu Ihrer eigentlichen Frage gelangen.

    Bitte, wir sehen genug davon in unseren Tagesjobs. Wir wollen helfen, aber nicht so ... .
    Schneiden Sie das Intro aus und zeigen Sie nur die relevanten DataFrames (oder kleine Versionen davon) in dem Schritt an, der Ihnen Probleme bereitet.

Wie auch immer, viel Spaß beim Lernen von Python, NumPy und Pandas!

Andy Hayden
quelle
30
+1 für den pd.read_clipboard(sep='\s\s+')Tipp. Wenn ich SO-Fragen poste, die einen speziellen, aber leicht gemeinsam nutzbaren Datenrahmen benötigen, wie diesen, erstelle ich ihn in Excel, kopiere ihn in meine Zwischenablage und weise SOer an, dasselbe zu tun. Spart so viel Zeit!
Zelusp
1
Der pd.read_clipboard(sep='\s\s+')Vorschlag scheint nicht zu funktionieren, wenn Sie Python auf einem Remote-Server verwenden, auf dem viele große Datenmengen leben.
user5359531
1
Warum pd.read_clipboard(sep='\s\s+')und nicht einfacher pd.read_clipboard()(mit der Standardeinstellung ‘s+’)? Die ersten benötigen mindestens 2 Leerzeichen, was zu Problemen führen kann, wenn nur 1 vorhanden ist (siehe z. B. in der Antwort von @JohnE ).
MarianD
3
@MarianD Der Grund, warum \ s \ s + so beliebt ist, ist, dass es oft einen gibt, z. B. in einem Spaltennamen, aber mehrere sind seltener, und die Pandas-Ausgabe fügt mindestens zwei zwischen den Spalten ein. Da dies nur für Spielzeug / kleine Datensätze ist, ist es ziemlich mächtig / die meisten Fälle. Hinweis: Getrennte Registerkarten wären eine andere Geschichte, obwohl der Stapelüberlauf Registerkarten durch Leerzeichen ersetzt. Wenn Sie jedoch einen tsv haben, verwenden Sie einfach \ t.
Andy Hayden
3
Ugh, ich benutze immer pd.read_clipboard(), wenn es Leerzeichen sind, mache ich :: pd.read_clipboard(sep='\s+{2,}', engine='python')P
U10-Forward
72

So erstellen Sie Beispieldatensätze

Dies dient hauptsächlich dazu, die Antwort von @ AndyHayden zu erweitern, indem Beispiele dafür bereitgestellt werden, wie Sie Beispieldatenrahmen erstellen können. Pandas und (insbesondere) Numpy bieten Ihnen hierfür eine Vielzahl von Tools, mit denen Sie im Allgemeinen mit nur wenigen Codezeilen ein vernünftiges Faksimile eines realen Datensatzes erstellen können.

Stellen Sie nach dem Importieren von Numpy und Pandas sicher, dass Sie einen zufälligen Startwert angeben, wenn Sie möchten, dass die Benutzer Ihre Daten und Ergebnisse exakt reproduzieren können.

import numpy as np
import pandas as pd

np.random.seed(123)

Ein Beispiel für ein Spülbecken

Hier ist ein Beispiel, das eine Vielzahl von Möglichkeiten zeigt. Aus einer Teilmenge davon können alle Arten nützlicher Beispieldatenrahmen erstellt werden:

df = pd.DataFrame({ 

    # some ways to create random data
    'a':np.random.randn(6),
    'b':np.random.choice( [5,7,np.nan], 6),
    'c':np.random.choice( ['panda','python','shark'], 6),

    # some ways to create systematic groups for indexing or groupby
    # this is similar to r's expand.grid(), see note 2 below
    'd':np.repeat( range(3), 2 ),
    'e':np.tile(   range(2), 3 ),

    # a date range and set of random dates
    'f':pd.date_range('1/1/2011', periods=6, freq='D'),
    'g':np.random.choice( pd.date_range('1/1/2011', periods=365, 
                          freq='D'), 6, replace=False) 
    })

Dies erzeugt:

          a   b       c  d  e          f          g
0 -1.085631 NaN   panda  0  0 2011-01-01 2011-08-12
1  0.997345   7   shark  0  1 2011-01-02 2011-11-10
2  0.282978   5   panda  1  0 2011-01-03 2011-10-30
3 -1.506295   7  python  1  1 2011-01-04 2011-09-07
4 -0.578600 NaN   shark  2  0 2011-01-05 2011-02-27
5  1.651437   7  python  2  1 2011-01-06 2011-02-03

Einige Notizen:

  1. np.repeatund np.tile(Spalten dund e) sind sehr nützlich, um Gruppen und Indizes auf sehr regelmäßige Weise zu erstellen. Für 2 Spalten kann dies verwendet werden, um Rs leicht zu duplizieren, ist expand.grid()aber auch flexibler in der Fähigkeit, eine Teilmenge aller Permutationen bereitzustellen. Bei 3 oder mehr Spalten wird die Syntax jedoch schnell unhandlich.
  2. Für einen direkteren Ersatz für Rs expand.grid()siehe die itertoolsLösung im Pandas-Kochbuch oder die hiernp.meshgrid gezeigte Lösung . Diese erlauben eine beliebige Anzahl von Dimensionen.
  3. Sie können ziemlich viel damit machen np.random.choice. In der Spalte ghaben wir beispielsweise eine zufällige Auswahl von 6 Daten aus dem Jahr 2011. Außerdem können replace=Falsewir durch Festlegen sicherstellen, dass diese Daten eindeutig sind - sehr praktisch, wenn wir dies als Index mit eindeutigen Werten verwenden möchten.

Gefälschte Börsendaten

Zusätzlich zur Verwendung von Teilmengen des obigen Codes können Sie die Techniken weiter kombinieren, um so gut wie alles zu tun. Im Folgenden finden Sie ein kurzes Beispiel, in dem Beispiel-Ticker-Daten für 4 Aktien mit denselben Daten kombiniert np.tileund date_rangeerstellt werden:

stocks = pd.DataFrame({ 
    'ticker':np.repeat( ['aapl','goog','yhoo','msft'], 25 ),
    'date':np.tile( pd.date_range('1/1/2011', periods=25, freq='D'), 4 ),
    'price':(np.random.randn(100).cumsum() + 10) })

Jetzt haben wir einen Beispieldatensatz mit 100 Zeilen (25 Daten pro Ticker), aber wir haben nur 4 Zeilen verwendet, damit alle anderen problemlos reproduzieren können, ohne 100 Codezeilen kopieren und einfügen zu müssen. Sie können dann Teilmengen der Daten anzeigen, wenn dies zur Erläuterung Ihrer Frage beiträgt:

>>> stocks.head(5)

        date      price ticker
0 2011-01-01   9.497412   aapl
1 2011-01-02  10.261908   aapl
2 2011-01-03   9.438538   aapl
3 2011-01-04   9.515958   aapl
4 2011-01-05   7.554070   aapl

>>> stocks.groupby('ticker').head(2)

         date      price ticker
0  2011-01-01   9.497412   aapl
1  2011-01-02  10.261908   aapl
25 2011-01-01   8.277772   goog
26 2011-01-02   7.714916   goog
50 2011-01-01   5.613023   yhoo
51 2011-01-02   6.397686   yhoo
75 2011-01-01  11.736584   msft
76 2011-01-02  11.944519   msft
JohnE
quelle
2
Gute Antwort. Nachdem ich diese Frage geschrieben habe, habe ich tatsächlich eine sehr kurze, einfache Implementierung geschrieben expand.grid(), die im Pandas-Kochbuch enthalten ist. Sie können dies auch in Ihre Antwort aufnehmen. Ihre Antwort zeigt, wie Sie komplexere Datensätze erstellen können, als meine expand_grid()Funktion verarbeiten kann. Das ist großartig.
Marius
46

Tagebuch eines Antwortenden

Mein bester Rat, um Fragen zu stellen, wäre, mit der Psychologie der Menschen zu spielen, die Fragen beantworten. Als einer dieser Menschen kann ich einen Einblick geben, warum ich bestimmte Fragen beantworte und warum ich andere nicht beantworte.

Motivationen

Ich bin aus mehreren Gründen motiviert, Fragen zu beantworten

  1. Stackoverflow.com war für mich eine enorm wertvolle Ressource. Ich wollte zurückgeben.
  2. Bei meinen Bemühungen, etwas zurückzugeben, habe ich festgestellt, dass diese Website eine noch mächtigere Ressource ist als zuvor. Das Beantworten von Fragen ist für mich eine Lernerfahrung und ich lerne gerne. Lesen Sie diese Antwort und kommentieren Sie von einem anderen Tierarzt . Diese Art der Interaktion macht mich glücklich.
  3. Ich mag Punkte!
  4. Siehe # 3.
  5. Ich mag interessante Probleme.

Alle meine reinsten Absichten sind großartig und alle, aber ich bekomme diese Befriedigung, wenn ich 1 oder 30 Fragen beantworte . Was meine Auswahl für die zu beantwortenden Fragen antreibt , hat einen großen Anteil an der Punktmaximierung.

Ich werde auch Zeit mit interessanten Problemen verbringen, aber das ist selten und hilft einem Fragesteller nicht, der eine Lösung für eine nicht interessante Frage benötigt. Ihre beste Wette, um mich zur Beantwortung einer Frage zu bewegen, besteht darin, diese Frage auf einer Platte zu servieren, die reif ist, damit ich sie mit so wenig Aufwand wie möglich beantworten kann. Wenn ich mir zwei Fragen ansehe und eine Code enthält, kann ich sie kopieren und einfügen, um alle benötigten Variablen zu erstellen ... Ich nehme diese! Ich werde vielleicht zu dem anderen zurückkehren, wenn ich Zeit habe.

Hauptratschlag

Machen Sie es den Leuten, die Fragen beantworten, einfach.

  • Stellen Sie Code bereit, der die benötigten Variablen erstellt.
  • Minimieren Sie diesen Code. Wenn meine Augen beim Betrachten des Beitrags glasig werden, komme ich zur nächsten Frage oder komme zu dem zurück, was ich sonst noch tue.
  • Denken Sie darüber nach, was Sie fragen, und seien Sie genau. Wir möchten sehen, was Sie getan haben, weil natürliche Sprachen (Englisch) ungenau und verwirrend sind. Codebeispiele dessen, was Sie versucht haben, helfen dabei, Inkonsistenzen in einer Beschreibung in natürlicher Sprache zu beheben.
  • BITTE zeigen, was Sie erwarten !!! Ich muss mich setzen und Dinge ausprobieren. Ich weiß fast nie die Antwort auf eine Frage, ohne einige Dinge auszuprobieren. Wenn ich kein Beispiel dafür sehe, wonach Sie suchen, kann ich die Frage weitergeben, weil ich keine Lust habe zu raten.

Ihr Ruf ist mehr als nur Ihr Ruf.

Ich mag Punkte (das habe ich oben erwähnt). Aber diese Punkte sind nicht wirklich mein Ruf. Mein wirklicher Ruf ist eine Verschmelzung dessen, was andere auf der Website über mich denken. Ich bemühe mich, fair und ehrlich zu sein, und ich hoffe, dass andere das sehen können. Für einen Fragesteller bedeutet dies, dass wir uns an das Verhalten der Fragesteller erinnern. Wenn Sie keine Antworten auswählen und gute Antworten positiv bewerten, erinnere ich mich. Wenn Sie sich so verhalten, wie ich es nicht mag oder wie ich es mag, erinnere ich mich. Dies spielt auch eine Rolle, auf welche Fragen ich antworten werde.


Wie auch immer, ich kann wahrscheinlich weitermachen, aber ich werde alle von Ihnen verschonen, die dies tatsächlich lesen.

piRSquared
quelle
26

Die Herausforderung Einer der schwierigsten Aspekte bei der Beantwortung von SO-Fragen ist die Zeit, die zum erneuten Erstellen des Problems (einschließlich der Daten) benötigt wird. Fragen, bei denen die Daten nicht eindeutig reproduziert werden können, werden mit geringerer Wahrscheinlichkeit beantwortet. Da Sie sich die Zeit nehmen, eine Frage zu schreiben, und ein Problem haben, bei dem Sie Hilfe benötigen, können Sie sich leicht selbst helfen, indem Sie Daten bereitstellen, die andere zur Lösung Ihres Problems verwenden können.

Die Anweisungen von @Andy zum Schreiben guter Pandas-Fragen sind ein ausgezeichneter Ausgangspunkt. Weitere Informationen finden Sie unter Fragen und Erstellen von minimalen, vollständigen und überprüfbaren Beispielen .

Bitte geben Sie Ihre Frage im Voraus klar an. Nachdem Sie sich die Zeit genommen haben, Ihre Frage und einen Beispielcode zu schreiben, versuchen Sie, diese zu lesen und Ihrem Leser eine Zusammenfassung zu geben, in der das Problem zusammengefasst und die Frage klar angegeben wird.

Ursprüngliche Frage :

Ich habe diese Daten ...

Ich möchte das machen...

Ich möchte, dass mein Ergebnis so aussieht ...

Wenn ich jedoch versuche, [dies] zu tun, erhalte ich das folgende Problem ...

Ich habe versucht, Lösungen zu finden, indem ich [dies] und [das] getan habe.

Wie behebe ich das?

Abhängig von der Datenmenge, dem Beispielcode und den bereitgestellten Fehlerstapeln muss der Leser einen langen Weg zurücklegen, bevor er das Problem versteht. Versuchen Sie, Ihre Frage so zu wiederholen, dass die Frage selbst oben steht, und geben Sie dann die erforderlichen Details an.

Überarbeitete Frage :

Frage: Wie kann ich das tun?

Ich habe versucht, Lösungen zu finden, indem ich [dies] und [das] getan habe.

Wenn ich versucht habe, [dies] zu tun, bekomme ich das folgende Problem ...

Ich möchte, dass meine Endergebnisse so aussehen ...

Hier ist ein minimaler Code, der mein Problem reproduzieren kann ...

Und so erstellen Sie meine Beispieldaten neu: df = pd.DataFrame({'A': [...], 'B': [...], ...})

MACHEN SIE BEISPIELDATEN BEISPIEL !!!

Manchmal reicht nur der Kopf oder das Ende des DataFrame aus. Sie können auch die von @JohnE vorgeschlagenen Methoden verwenden, um größere Datensätze zu erstellen, die von anderen reproduziert werden können. Verwenden Sie sein Beispiel, um einen 100-Zeilen-DataFrame mit Aktienkursen zu generieren:

stocks = pd.DataFrame({ 
    'ticker':np.repeat( ['aapl','goog','yhoo','msft'], 25 ),
    'date':np.tile( pd.date_range('1/1/2011', periods=25, freq='D'), 4 ),
    'price':(np.random.randn(100).cumsum() + 10) })

Wenn dies Ihre tatsächlichen Daten waren, möchten Sie möglicherweise nur den Kopf und / oder das Ende des Datenrahmens wie folgt angeben (stellen Sie sicher, dass Sie alle vertraulichen Daten anonymisieren):

>>> stocks.head(5).to_dict()
{'date': {0: Timestamp('2011-01-01 00:00:00'),
  1: Timestamp('2011-01-01 00:00:00'),
  2: Timestamp('2011-01-01 00:00:00'),
  3: Timestamp('2011-01-01 00:00:00'),
  4: Timestamp('2011-01-02 00:00:00')},
 'price': {0: 10.284260107718254,
  1: 11.930300761831457,
  2: 10.93741046217319,
  3: 10.884574289565609,
  4: 11.78005850418319},
 'ticker': {0: 'aapl', 1: 'aapl', 2: 'aapl', 3: 'aapl', 4: 'aapl'}}

>>> pd.concat([stocks.head(), stocks.tail()], ignore_index=True).to_dict()
{'date': {0: Timestamp('2011-01-01 00:00:00'),
  1: Timestamp('2011-01-01 00:00:00'),
  2: Timestamp('2011-01-01 00:00:00'),
  3: Timestamp('2011-01-01 00:00:00'),
  4: Timestamp('2011-01-02 00:00:00'),
  5: Timestamp('2011-01-24 00:00:00'),
  6: Timestamp('2011-01-25 00:00:00'),
  7: Timestamp('2011-01-25 00:00:00'),
  8: Timestamp('2011-01-25 00:00:00'),
  9: Timestamp('2011-01-25 00:00:00')},
 'price': {0: 10.284260107718254,
  1: 11.930300761831457,
  2: 10.93741046217319,
  3: 10.884574289565609,
  4: 11.78005850418319,
  5: 10.017209045035006,
  6: 10.57090128181566,
  7: 11.442792747870204,
  8: 11.592953372130493,
  9: 12.864146419530938},
 'ticker': {0: 'aapl',
  1: 'aapl',
  2: 'aapl',
  3: 'aapl',
  4: 'aapl',
  5: 'msft',
  6: 'msft',
  7: 'msft',
  8: 'msft',
  9: 'msft'}}

Möglicherweise möchten Sie auch eine Beschreibung des DataFrame bereitstellen (wobei nur die entsprechenden Spalten verwendet werden). Dies erleichtert es anderen, die Datentypen jeder Spalte zu überprüfen und andere häufige Fehler zu identifizieren (z. B. Datumsangaben als Zeichenfolge vs. Datum / Uhrzeit64 vs. Objekt):

stocks.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 100 entries, 0 to 99
Data columns (total 3 columns):
date      100 non-null datetime64[ns]
price     100 non-null float64
ticker    100 non-null object
dtypes: datetime64[ns](1), float64(1), object(1)

HINWEIS: Wenn Ihr DataFrame über einen MultiIndex verfügt:

Wenn Ihr DataFrame über einen Multiindex verfügt, müssen Sie vor dem Aufruf zunächst einen Reset durchführen to_dict. Anschließend müssen Sie den Index neu erstellen mit set_index:

# MultiIndex example.  First create a MultiIndex DataFrame.
df = stocks.set_index(['date', 'ticker'])
>>> df
                       price
date       ticker           
2011-01-01 aapl    10.284260
           aapl    11.930301
           aapl    10.937410
           aapl    10.884574
2011-01-02 aapl    11.780059
...

# After resetting the index and passing the DataFrame to `to_dict`, make sure to use 
# `set_index` to restore the original MultiIndex.  This DataFrame can then be restored.

d = df.reset_index().to_dict()
df_new = pd.DataFrame(d).set_index(['date', 'ticker'])
>>> df_new.head()
                       price
date       ticker           
2011-01-01 aapl    10.284260
           aapl    11.930301
           aapl    10.937410
           aapl    10.884574
2011-01-02 aapl    11.780059
Alexander
quelle
12

Hier ist meine Version von dput- dem Standard-R-Tool zur Erstellung reproduzierbarer Berichte - für Pandas DataFrame. Bei komplexeren Frames wird es wahrscheinlich fehlschlagen, aber es scheint in einfachen Fällen die Aufgabe zu erfüllen:

import pandas as pd
def dput (x):
    if isinstance(x,pd.Series):
        return "pd.Series(%s,dtype='%s',index=pd.%s)" % (list(x),x.dtype,x.index)
    if isinstance(x,pd.DataFrame):
        return "pd.DataFrame({" + ", ".join([
            "'%s': %s" % (c,dput(x[c])) for c in x.columns]) + (
                "}, index=pd.%s)" % (x.index))
    raise NotImplementedError("dput",type(x),x)

jetzt,

df = pd.DataFrame({'a':[1,2,3,4,2,1,3,1]})
assert df.equals(eval(dput(df)))
du = pd.get_dummies(df.a,"foo")
assert du.equals(eval(dput(du)))
di = df
di.index = list('abcdefgh')
assert di.equals(eval(dput(di)))

Beachten Sie, dass dies eine viel ausführlichere Ausgabe erzeugt als DataFrame.to_dictz.

pd.DataFrame({
  'foo_1':pd.Series([1, 0, 0, 0, 0, 1, 0, 1],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1)),
  'foo_2':pd.Series([0, 1, 0, 0, 1, 0, 0, 0],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1)),
  'foo_3':pd.Series([0, 0, 1, 0, 0, 0, 1, 0],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1)),
  'foo_4':pd.Series([0, 0, 0, 1, 0, 0, 0, 0],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1))},
  index=pd.RangeIndex(start=0, stop=8, step=1))

vs.

{'foo_1': {0: 1, 1: 0, 2: 0, 3: 0, 4: 0, 5: 1, 6: 0, 7: 1}, 
 'foo_2': {0: 0, 1: 1, 2: 0, 3: 0, 4: 1, 5: 0, 6: 0, 7: 0}, 
 'foo_3': {0: 0, 1: 0, 2: 1, 3: 0, 4: 0, 5: 0, 6: 1, 7: 0}, 
 'foo_4': {0: 0, 1: 0, 2: 0, 3: 1, 4: 0, 5: 0, 6: 0, 7: 0}}

für duoben, aber es behält Spaltentypen bei . ZB im obigen Testfall

du.equals(pd.DataFrame(du.to_dict()))
==> False

weil du.dtypesist uint8und pd.DataFrame(du.to_dict()).dtypesist int64.

sds
quelle
es ist klarer, obwohl ich zugebe, dass ich nicht verstehe, warum ich es über verwenden möchteto_dict
Paul H
2
Weil es Spaltentypen beibehält. Genauer gesagt du.equals(eval(dput(df))).
SDS