Jak zrobić dobre powtarzalne przykłady pand

221

Sporo czasu spędziłem na oglądaniu obu i tagi na SO, mam wrażenie, że pandaspytania zawierają mniej powtarzalnych danych. To jest coś, że społeczność R była dobra ładna o zachęcanie, a dzięki przewodników jak to nowicjusze są w stanie uzyskać jakąś pomoc na łącząc te przykłady. Ludzie, którzy są w stanie przeczytać te przewodniki i powrócić z powtarzalnymi danymi, często będą mieli znacznie więcej szczęścia, otrzymując odpowiedzi na swoje pytania.

Jak możemy stworzyć dobre, powtarzalne przykłady pandaspytań? Proste ramki danych można łączyć, np .:

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

Jednak wiele przykładowych zestawów danych wymaga bardziej skomplikowanej struktury, np .:

  • datetime indeksy lub dane
  • Wiele zmiennych kategorialnych (czy istnieje odpowiednik expand.grid()funkcji R , która tworzy wszystkie możliwe kombinacje niektórych danych zmiennych?)
  • Dane MultiIndex lub Panel

W przypadku zestawów danych, które trudno wyszydzić za pomocą kilku wierszy kodu, czy istnieje odpowiednik R, dput()który pozwala wygenerować kod do wklejenia w celu odtworzenia struktury danych?

Marius
źródło
8
Jeśli skopiujesz wynik drukowania, w większości przypadków autorzy mogą korzystać z read_clipboard () ... oprócz MultiIndex: s. Mówiąc to, dykt jest dobrym dodatkiem
Andy Hayden
8
Oprócz tego, co powiedział Andy, myślę, że kopiowanie i wklejanie df.head(N).to_dict(), gdzie Njest rozsądna liczba, jest dobrym sposobem. Bonus + 1 za dodanie ładnych podziałów linii do wyjścia. W przypadku znaczników czasu zazwyczaj wystarczy dodać from pandas import Timestampna górze kodu.
Paul H

Odpowiedzi:

323

Uwaga: Pomysły tutaj są dość ogólne w przypadku przepełnienia stosu, a nawet pytania .

Uwaga: pisanie dobrego pytania jest trudne.

Dobry:

  • dołącz małe * przykładowe DataFrame, jako kod uruchamialny:

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

    lub pd.read_clipboard(sep='\s\s+')możesz go „kopiować i wklejać” za pomocą , możesz sformatować tekst dla podświetlenia przepełnienia stosu i użyć Ctrl+ K(lub wstawić cztery spacje do każdej linii), lub umieścić trzy tyldy nad i pod kodem bez kodu:

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

    sprawdź pd.read_clipboard(sep='\s\s+')się.

    * Ja naprawdę mam na myśli małe , większość przykładowych DataFrames mogłaby być mniejsza niż 6 rzędów potrzebne źródło , a założę się, że mogę to zrobić w 5 rzędach. Czy możesz odtworzyć błąd za pomocą df = df.head(), jeśli nie majstrować, aby sprawdzić, czy możesz stworzyć małą ramkę DataFrame, która pokazuje napotkany problem.

    * Każda reguła ma wyjątek, oczywistym jest dla kwestii wydajności ( w tym przypadku na pewno użyć% timeit i ewentualnie% prun ), gdzie należy wygenerować (rozważyć użycie np.random.seed więc mamy dokładnie taką samą ramkę) df = pd.DataFrame(np.random.randn(100000000, 10)). Mówiąc, że „uczyń ten kod szybkim dla mnie” nie jest ściśle związane z tematem witryny ...

  • napisz pożądany wynik (podobnie jak powyżej)

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

    Wyjaśnij, skąd pochodzą liczby: 5 to suma kolumny B dla wierszy, w których A wynosi 1.

  • pokaż kod , który wypróbowałeś:

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

    Ale powiedz, co jest niepoprawne: kolumna A jest w indeksie, a nie w kolumnie.

  • pokaż, że przeprowadziłeś badania ( przeszukaj dokumenty , wyszukaj StackOverflow ), podaj podsumowanie:

    Dokumentowanie sumy mówi po prostu: „Oblicz sumę wartości grupy”

    Dokumenty grupujące nie podają na to żadnych przykładów.

    Na bok: odpowiedzią jest, aby użyć df.groupby('A', as_index=False).sum().

  • jeśli istotne jest, że masz kolumny sygnatury czasowej, np. próbujesz ponownie coś lub coś, to wyraź to i zastosuj pd.to_datetimeje dla zachowania dokładności **.

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

    ** Czasami jest to sam problem: były łańcuchami.

Źli:

  • nie dołączaj MultiIndexu, którego nie możemy skopiować i wkleić (patrz wyżej), jest to rodzaj skargi z domyślnym wyświetlaniem pand, ale irytujące:

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

    Prawidłowym sposobem jest dołączenie zwykłego DataFrame do set_indexwywołania:

    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
  • zapewniaj wgląd w to, co to jest, gdy dajesz pożądany wynik:

       B
    A   
    1  1
    5  0

    Sprecyzuj, w jaki sposób otrzymałeś liczby (jakie to są) ... dokładnie sprawdź, czy są poprawne.

  • Jeśli kod zgłasza błąd, dołącz cały ślad stosu (można go później edytować, jeśli jest zbyt głośny). Pokaż numer wiersza (i odpowiadający mu wiersz kodu, przeciwko któremu się podnosi).

Brzydki:

  • nie linkuj do pliku CSV, do którego nie mamy dostępu (najlepiej w ogóle nie linkuj do zewnętrznego źródła ...)

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

    Wię kszość danych jest prawnie własna , otrzymujemy to: Twórz podobne dane i zobacz, czy możesz odtworzyć problem (mały).

  • nie wyjaśniaj niejasno sytuacji słowami, ponieważ masz ramkę DataFrame, która jest „duża”, podaj niektóre nazwy kolumn na marginesie (pamiętaj, aby nie wspominać o ich typach). Spróbuj zagłębić się w wiele szczegółów na temat czegoś, co jest całkowicie pozbawione znaczenia, nie widząc rzeczywistego kontekstu. Przypuszczalnie nikt nawet nie przeczyta do końca tego akapitu.

    Eseje są złe, łatwiej jest z małymi przykładami.

  • nie dołączaj ponad 10 linii (100+ ??) linii danych przed przejściem do rzeczywistego pytania.

    Widzimy to dość w naszych codziennych zadaniach. Chcemy pomóc, ale nie tak ... .
    Wytnij wprowadzenie i po prostu pokaż odpowiednie ramki danych (lub ich małe wersje) w kroku, który powoduje problemy.

W każdym razie, baw się dobrze, ucząc się języka Python, NumPy i Pand!

Andy Hayden
źródło
30
+1 za pd.read_clipboard(sep='\s\s+')wskazówkę. Kiedy zamieszczam pytania SO, które wymagają specjalnej, ale łatwo udostępnianej ramki danych, takiej jak ta , buduję ją w programie Excel, kopiuję ją do mojego schowka, a następnie polecam SOers zrobić to samo. Oszczędza tyle czasu!
zelusp
1
pd.read_clipboard(sep='\s\s+')sugestia nie wydaje się działać, jeśli używasz Python na zdalnym serwerze, czyli tam, gdzie wiele dużych zbiorów danych żyć.
user5359531,
1
Dlaczego pd.read_clipboard(sep='\s\s+')nie jest to prostsze pd.read_clipboard()(z domyślnymi ‘s+’)? Pierwsza potrzeba co najmniej 2 białych znaków, które mogą powodować problemy, jeśli jest tylko 1 (patrz np taki w @JohnE „s odpowiedzi ).
MarianD
3
@MarianD powodem, dla którego \ s \ s + jest tak popularny, jest to, że często występuje jeden np. W nazwie kolumny, ale wielokrotność jest rzadsza, a wyjście pandy ładnie umieszcza co najmniej dwie między kolumnami. Ponieważ jest to tylko dla zabawek / małych zestawów danych, jest dość potężne / większość przypadków. Uwaga: rozdzielone tabulatory byłyby inną historią, chociaż przepływ stosu zastępuje tabulatory spacjami, ale jeśli masz tsv, po prostu użyj \ t.
Andy Hayden,
3
Ugh, zawsze używam pd.read_clipboard(), kiedy są spacjami, robię pd.read_clipboard(sep='\s+{2,}', engine='python'):: P
U10-Forward
72

Jak utworzyć przykładowe zestawy danych

Ma to na celu przede wszystkim rozwinięcie odpowiedzi @ AndyHayden, podając przykłady tworzenia przykładowych ramek danych. Pandy i (zwłaszcza) numpy zapewniają do tego różnorodność narzędzi, dzięki czemu można generalnie stworzyć rozsądny telefaks dowolnego prawdziwego zestawu danych za pomocą zaledwie kilku wierszy kodu.

Po zaimportowaniu numpy i pand, pamiętaj, aby podać losowy materiał siewny, jeśli chcesz, aby ludzie mogli dokładnie odtworzyć twoje dane i wyniki.

import numpy as np
import pandas as pd

np.random.seed(123)

Przykład zlewu kuchennego

Oto przykład pokazujący różne rzeczy, które możesz zrobić. Na podstawie tego podzbioru można utworzyć wszelkiego rodzaju przydatne przykładowe ramki danych:

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) 
    })

Daje to:

          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

Niektóre uwagi:

  1. np.repeatoraz np.tile(kolumny di e) są bardzo przydatne do tworzenia grup i indeksów w bardzo regularny sposób. W przypadku 2 kolumn można to wykorzystać do łatwego powielania r, expand.grid()ale jest również bardziej elastyczny w zakresie możliwości zapewnienia podzbioru wszystkich permutacji. Jednak w przypadku 3 lub więcej kolumn składnia szybko staje się nieporęczna.
  2. Aby uzyskać bardziej bezpośredni zamiennik dla r, expand.grid()zobacz itertoolsrozwiązanie w książce kucharskiej pand lub np.meshgridrozwiązanie pokazane tutaj . Pozwolą one na dowolną liczbę wymiarów.
  3. Możesz zrobić z tym całkiem sporo np.random.choice. Na przykład w kolumnie gmamy losowy wybór 6 dat z 2011 roku. Dodatkowo, ustawiając replace=Falsemożemy zapewnić, że te daty są unikalne - bardzo przydatne, jeśli chcemy użyć tego jako indeksu o unikalnych wartościach.

Fałszywe dane giełdowe

Oprócz przejmowania podzbiorów powyższego kodu, możesz dalej łączyć techniki, aby zrobić wszystko. Na przykład, oto krótki przykład, który łączy np.tilei date_rangetworzy przykładowe dane giełdowe dla 4 akcji obejmujących te same daty:

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) })

Teraz mamy przykładowy zestaw danych zawierający 100 wierszy (25 dat na ticker), ale wykorzystaliśmy tylko 4 wiersze, aby ułatwić reprodukcję bez kopiowania i wklejania 100 wierszy kodu. Następnie możesz wyświetlić podzbiory danych, jeśli pomoże to wyjaśnić pytanie:

>>> 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
źródło
2
Świetna odpowiedź. Po napisaniu tego pytania napisałem bardzo krótką, prostą implementację, expand.grid()która jest zawarta w książce kucharskiej pandy , możesz to również uwzględnić w swojej odpowiedzi. Twoja odpowiedź pokazuje, jak tworzyć bardziej złożone zestawy danych, niż moja expand_grid()funkcja mogłaby obsłużyć, co jest świetne.
Marius
46

Dziennik odpowiedzi

Moją najlepszą radą przy zadawaniu pytań byłoby rozważenie psychologii ludzi, którzy odpowiadają na pytania. Będąc jedną z tych osób, mogę wgląd w to, dlaczego odpowiadam na niektóre pytania i dlaczego nie odpowiadam innym.

Motywacje

Mam motywację do odpowiedzi na pytania z kilku powodów

  1. Stackoverflow.com był dla mnie niezwykle cennym zasobem. Chciałem oddać.
  2. Starając się oddać, odkryłem, że ta strona jest jeszcze potężniejszym zasobem niż wcześniej. Odpowiadanie na pytania to dla mnie doświadczenie edukacyjne i lubię się uczyć. Przeczytaj tę odpowiedź i skomentuj od innego weterynarza . Ten rodzaj interakcji sprawia, że ​​jestem szczęśliwy.
  3. Lubię punkty!
  4. Zobacz nr 3.
  5. Lubię ciekawe problemy.

Wszystkie moje najczystsze intencje są świetne i wszystkie, ale czerpię satysfakcję, jeśli odpowiem na 1 pytanie lub 30. To, co napędza moje wybory, na które pytania należy odpowiedzieć, ma ogromny wpływ na maksymalizację punktów.

Spędzę też czas na interesujących problemach, ale jest ich niewiele i nie pomaga i pytający nie potrzebuje rozwiązania nieciekawego pytania. Najlepszym rozwiązaniem, aby zmusić mnie do udzielenia odpowiedzi na pytanie, jest podanie tego pytania na półmisku gotowym do udzielenia odpowiedzi przy jak najmniejszym wysiłku. Jeśli patrzę na dwa pytania i jedno ma kod, mogę skopiować wklej, aby utworzyć wszystkie zmienne, których potrzebuję ... Biorę to! Może wrócę do drugiego, jeśli będę miał czas.

Główne porady

Ułatw ludziom odpowiadanie na pytania.

  • Podaj kod, który tworzy potrzebne zmienne.
  • Zminimalizuj ten kod. Jeśli moje oczy błyszczą, gdy patrzę na post, przechodzę do następnego pytania lub wracam do wszystkiego, co robię.
  • Pomyśl o co pytasz i bądź konkretny. Chcemy zobaczyć, co zrobiłeś, ponieważ języki naturalne (angielski) są niedokładne i mylące. Próbki kodu tego, co wypróbowałeś, pomogą rozwiązać niespójności w opisie języka naturalnego.
  • PROSZĘ pokazać, czego oczekujesz !!! Muszę usiąść i spróbować. Prawie nigdy nie znam odpowiedzi na pytanie bez wypróbowania pewnych rzeczy. Jeśli nie widzę przykładu tego, czego szukasz, mogę przekazać pytanie, ponieważ nie mam ochoty zgadywać.

Twoja reputacja jest czymś więcej niż tylko reputacją.

Lubię punkty (wspomniałem o tym powyżej). Ale te punkty nie są tak naprawdę moją reputacją. Moja prawdziwa reputacja jest połączeniem tego, co myślą o mnie inni na stronie. Staram się być uczciwy i szczery i mam nadzieję, że inni to zobaczą. Dla pytającego oznacza to, że pamiętamy jego zachowanie. Jeśli nie wybierzesz odpowiedzi i nie ocenisz dobrych odpowiedzi, pamiętam. Jeśli zachowujesz się w sposób, który mi się nie podoba lub w sposób, który lubię, pamiętam. To także odgrywa rolę, na którą odpowiem na pytania.


W każdym razie pewnie mogę kontynuować, ale oszczędzę wam wszystkich, którzy to przeczytali.

piRSquared
źródło
26

Wyzwanie Jednym z najtrudniejszych aspektów odpowiedzi na pytania SO jest czas potrzebny do odtworzenia problemu (w tym danych). Odpowiedzi na pytania, które nie mają jasnego sposobu na odtworzenie danych, są mniej prawdopodobne. Biorąc pod uwagę, że poświęcasz czas na napisanie pytania i masz problem, z którym chciałbyś pomóc, możesz łatwo pomóc sobie, dostarczając dane, które inni mogą następnie wykorzystać, aby rozwiązać problem.

Instrukcje dostarczone przez @Andy dotyczące pisania dobrych pytań dotyczących pand są doskonałym miejscem na rozpoczęcie. Aby uzyskać więcej informacji, zapoznaj się z pytaniem i jak tworzyć przykłady minimalne, kompletne i weryfikowalne .

Proszę jasno podać swoje pytanie z góry. Po poświęceniu czasu na napisanie pytania i kodu przykładowego postaraj się je przeczytać i dostarczyć czytelnikowi „Streszczenie”, które podsumowuje problem i jasno określa pytanie.

Oryginalne pytanie :

Mam te dane ...

Chce to zrobić...

Chcę, aby mój wynik wyglądał tak ...

Jednak gdy próbuję to zrobić, pojawia się następujący problem ...

Próbowałem znaleźć rozwiązania, robiąc [to] i [tamto].

Jak to naprawić?

W zależności od ilości danych, przykładowego kodu i stosów błędów, czytnik musi przejść długą drogę, zanim zrozumie, na czym polega problem. Spróbuj ponownie sformułować pytanie, aby samo pytanie było na górze, a następnie podaj niezbędne szczegóły.

Zmienione pytanie :

Pytanie: Jak mogę to zrobić?

Próbowałem znaleźć rozwiązania, robiąc [to] i [tamto].

Gdy próbuję to zrobić, pojawia się następujący problem ...

Chciałbym, aby moje wyniki końcowe wyglądały tak ...

Oto minimalny kod, który może odtworzyć mój problem ...

A oto jak odtworzyć moje przykładowe dane: df = pd.DataFrame({'A': [...], 'B': [...], ...})

PODAJ PRZYKŁADOWE DANE, JEŚLI POTRZEBUJESZ !!!

Czasami wystarczy tylko głowa lub ogon DataFrame. Możesz także użyć metod zaproponowanych przez @JohnE, aby utworzyć większe zbiory danych, które mogą być powielane przez innych. Korzystając z tego przykładu, wygenerował 100-ramkowy DataFrame cen akcji:

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) })

Jeśli były to twoje rzeczywiste dane, możesz po prostu zamieścić nagłówek i / lub ogon ramki danych w następujący sposób (pamiętaj o anonimizacji poufnych danych):

>>> 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'}}

Możesz także podać opis DataFrame (używając tylko odpowiednich kolumn). Ułatwia to innym sprawdzanie typów danych w każdej kolumnie i identyfikowanie innych typowych błędów (np. Daty jako ciąg vs. datetime64 vs. obiekt):

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)

UWAGA: Jeśli twoja ramka danych ma MultiIndex:

Jeśli twoja DataFrame ma multiindeks, musisz najpierw zresetować przed wywołaniem to_dict. Następnie musisz ponownie utworzyć indeks, używając 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
źródło
12

Oto moja wersja dput- standardowego narzędzia R do generowania powtarzalnych raportów - dla Pandas DataFrame. Prawdopodobnie nie powiedzie się w przypadku bardziej złożonych ramek, ale wydaje się, że wykonuje to zadanie w prostych przypadkach:

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)

teraz,

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)))

Zauważ, że daje to dużo więcej informacji wyjściowych niż DataFrame.to_dictnp.

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}}

do dupowyżej, ale zachowuje typy kolumn . Np. W powyższym przypadku testowym

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

ponieważ du.dtypesjest uint8i pd.DataFrame(du.to_dict()).dtypesjest int64.

sds
źródło
jest jaśniejsze, choć przyznaję, że nie rozumiem, dlaczego miałbym chcieć go używaćto_dict
Paul H
2
Ponieważ zachowuje typy kolumn. Dokładniej du.equals(eval(dput(df))).
sds