Jak zrobić dobre powtarzalne pandy przykłady
Po spędzeniu przyzwoitej ilości czasu oglądając zarówno r i pandy znaczniki na tak, mam wrażenie, że pandas
pytania są mniej prawdopodobne, aby zawierać powtarzalne dane. Jest to coś, co społeczność R była całkiem dobra w zachęcaniu, a dzięki przewodnikom takim jak this, nowi gracze mogą uzyskać pomoc przy zestawianiu tych przykładów. Ludzie, którzy są w stanie przeczytać te przewodniki i wrócić z powtarzalnych danych często mają dużo więcej szczęścia uzyskanie odpowiedzi na ich pytania.
Jak możemy tworzyć dobre powtarzalne przykłady dla pandas
pytań? Proste ramki danych można zestawiać, np.:
import pandas as pd
df = pd.DataFrame({'user': ['Bob', 'Jane', 'Alice'],
'income': [40000, 50000, 42000]})
Ale wiele przykładowych zbiorów danych wymaga bardziej skomplikowanej struktury, np.:
-
datetime
Wskaźniki lub dane - wiele zmiennych kategorycznych (czy istnieje odpowiednik funkcji R
expand.grid()
, która wytwarza wszystkie możliwe kombinacje niektórych podanych zmiennych?) - MultiIndex lub dane Panelu
Dla zbiorów danych, które są trudno zrobić makietę używając kilku linijek kodu, czy istnieje odpowiednik R dput()
, który pozwala na wygenerowanie kodu do kopiowania w celu regeneracji struktury danych?
5 answers
Uwaga: pomysły tutaj są dość ogólne dla przepełnienia stosu, rzeczywiście pytania .
Zastrzeżenie: pisanie dobrego pytania jest trudne.
Dobry:
-
W tym celu należy dołączyć małe* przykładowe ramki danych, albo jako kod wykonywalny:
In [1]: df = pd.DataFrame([[1, 2], [1, 3], [4, 6]], columns=['A', 'B'])
Lub zrobić go "Kopiuj i wklejaj" za pomocą
pd.read_clipboard(sep='\s\s+')
, możesz sformatować tekst dla podświetlenia przepełnienia stosu i użyć Ctrl+K (lub poprzedzić cztery spacje do każdej linii), lub umieścić trzy tyldy powyżej i poniżej Twojego kodu z niezindeksowanym kodem:In [2]: df Out[2]: A B 0 1 2 1 1 3 2 4 6
Przetestuj
pd.read_clipboard(sep='\s\s+')
siebie.* mam na myśli małe, zdecydowana większość przykładowych ramek danych może być mniejsza niż 6 wierszy potrzebne cytowanie , i 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 możesz zrobić małej ramki danych, która pokazuje problem, z którym się borykasz.* każda reguła ma wyjątek, oczywistym jest dla problemów z wydajnością ( W takim przypadku zdecydowanie użyj %timeit i ewentualnie %prun ), gdzie powinieneś wygenerować (rozważ użycie np.przypadkowe.seed więc mamy dokładnie tę samą ramkę):
df = pd.DataFrame(np.random.randn(100000000, 10))
. Powiedzenie, że "zrób ten kod szybko dla mnie" nie jest ściśle związane z tematem strony... -
Napisz pożądany wynik (podobnie jak powyżej)
In [3]: iwantthis Out[3]: A B 0 1 5 1 4 6
wyjaśnij, z czego pochodzą liczby: 5 jest sumą kolumny B dla wierszy, w których A jest 1.
-
Pokaż kod próbowałeś:
In [4]: df.groupby('A').sum() Out[4]: B A 1 5 4 6
ale powiedz, co jest nieprawidłowe: kolumna A jest w indeksie, a nie w kolumnie.
-
Pokaż, że zrobiłeś jakieś badania ( przeszukaj dokumenty, wyszukaj StackOverflow ), podaj podsumowanie:
Docstring dla sum po prostu stwierdza "Oblicz sumę wartości grupy"
Groupby docs nie podawaj żadnych przykładów dla to.
na marginesie: odpowiedzią tutaj jest użycie
df.groupby('A', as_index=False).sum()
. -
Jeśli jest istotne, że masz kolumny znacznika czasu, np. resamplujesz lub coś takiego, to bądź wyraźny i zastosuj
pd.to_datetime
do nich na dobrą miarę**.df['date'] = pd.to_datetime(df['date']) # this column ought to be date..
** czasami jest to kwestia sama w sobie: były to struny.
Zły:
-
Nie dołączamy Multiindexu, którego nie możemy kopiować i wklejać (patrz wyżej), jest to jest to jeden z najbardziej znanych i cenionych producentów pand na świecie.]}
In [11]: df Out[11]: C A B 1 2 3 2 6
prawidłowym sposobem jest dołączenie zwykłej ramki danych z
set_index
zadzwoń: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
-
Zapewnij wgląd w to, co to jest, dając wynik, który chcesz:
B A 1 1 5 0
bądź konkretny o tym, jak masz numery (co to są)... sprawdź, czy są poprawne.
Jeśli Twój kod wyświetli błąd, Dołącz cały stos trace (można to później edytować, jeśli jest zbyt głośno). Pokaż numer wiersza (i odpowiadającą mu linię kodu, przeciwko której jest podnoszony).
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 zastrzeżona otrzymujemy to: Stwórz podobne dane i sprawdź, czy możesz odtworzyć problem (coś małe).
-
Nie wyjaśniaj sytuacji niejasno słowami, jak masz ramkę danych, która jest "duża", wymieniaj niektóre nazwy kolumn na przelotnie(pamiętaj, aby nie wspominać o ich typach dtyp). Postaraj się wniknąć w wiele szczegółów o czymś, co jest całkowicie bezsensowne, nie widząc rzeczywistego kontekstu. Prawdopodobnie nikt nawet nie będzie czytać do końca tego akapitu.
eseje są złe, łatwiej jest z małymi przykłady.
-
Nie włączaj 10+ (100+??) linie danych munging przed przejściem do rzeczywistego pytania.
Proszę, dość tego widzimy w naszych codziennych pracach. Chcemy pomóc, ale nie w ten sposób....
Wytnij intro 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 Pythona, NumPy i pandy!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-08 15:45:49
Jak tworzyć przykładowe zbiory danych
Ma to głównie na celu rozszerzenie odpowiedzi @AndyHayden poprzez podanie przykładów jak można tworzyć przykładowe ramki danych. Pandy i (szczególnie) numpy dają Ci wiele narzędzi do tego, że możesz ogólnie stworzyć rozsądny faksymile dowolnego rzeczywistego zbioru danych za pomocą zaledwie kilku linijek kodu.
Po zaimportowaniu numpy i pandy, upewnij się, że dostarczysz losowe nasiona, 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 zlewozmywaka
Oto przykład pokazujący różne rzeczy, które możesz zrobić. Wszystkie rodzaje użytecznych przykładowych ramek danych mogą być tworzone z podzbioru tego:
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)
})
To daje:
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
Kilka uwag:
-
np.repeat
inp.tile
(kolumnyd
ie
) są bardzo przydatne do tworzenia grup i indeksów w bardzo regularny sposób. Dla 2 kolumn, można to wykorzystać do łatwego powielania rexpand.grid()
, ale jest również bardziej elastyczne w możliwość dostarczenia podzbioru wszystkich permutacji. Jednak dla 3 lub więcej kolumn składnia szybko staje się nieporęczna. - dla bardziej bezpośredniego zamiennika r
expand.grid()
Zobaczitertools
rozwiązanie w pandy cookbook lubnp.meshgrid
rozwiązanie pokazane tutaj . Pozwalają one na dowolną liczbę wymiarów. - można zrobić sporo z
np.random.choice
. Na przykład w kolumnieg
mamy losowy wybór 6 dat z 2011 roku. Dodatkowo ustawiającreplace=False
możemy upewnij się, ż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 pobierania podzbiorów powyższego kodu, możesz dodatkowo łączyć techniki, aby zrobić prawie wszystko. Na przykład, oto krótki przykład, który łączy np.tile
i date_range
, aby utworzyć przykładowe dane 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 z 100 liniami (25 dat na ticker), ale używaj tylko 4 linii, aby to zrobić, co ułatwia wszystkim innym odtwarzanie bez kopiowania i wklejania 100 linii kodu. Możesz wtedy wyświetlić podzbiory danych, jeśli pomoże to wyjaśnić twoje 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:22
Pamiętnik Answerera
Moją najlepszą radą do zadawania pytań byłoby pobawić się psychologią ludzi, którzy odpowiadają na pytania. Będąc jedną z tych osób, mogę dać wgląd w to, dlaczego odpowiadam na pewne pytania i dlaczego nie odpowiadam na inne.
Motywacje
Jestem zmotywowany do odpowiadania na pytania z kilku powodów]}- Stackoverflow.com był dla mnie niezwykle cennym zasobem. Chciałem się odwdzięczyć.
- w moich wysiłkach oddania, Odkryłem, że ta strona jest jeszcze potężniejszym zasobem niż wcześniej. Odpowiadanie na pytania jest dla mnie doświadczeniem uczenia się i lubię się uczyć. przeczytaj tę odpowiedź i komentarz innego weterynarza . Taka interakcja mnie uszczęśliwia. Lubię punkty!
- Patrz # 3. Lubię ciekawe problemy.
Będę również spędzać czas na ciekawych problemach, ale to niewiele i nie pomaga pytającemu, który potrzebuje rozwiązania nieciekawego pytania. Najlepiej, żebym odpowiedziała na pytanie, to podać je na talerzu, abym mogła odpowiedzieć z jak najmniejszym wysiłkiem. Jeśli patrzę na dwa pytania i jeden ma kod mogę skopiować wklej, aby utworzyć wszystkie zmienne, których potrzebuję... Biorę to. raz! Może wrócę do tego drugiego, jeśli będę miał czas.
Główna Rada
Ułatw ludziom odpowiadanie na pytania.- Podaj kod, który tworzy zmienne, które są potrzebne.
- zminimalizuj ten kod. Jeśli moje oczy glazurują się, gdy patrzę na post, przechodzę do następnego pytania lub wracam do tego, co jeszcze robię. Pomyśl o tym, o co prosisz i bądź konkretny. Chcemy zobaczyć, co zrobiłeś, ponieważ języki naturalne (Angielski) są niewytłumaczalne i mylące. Próbki kodu tego, co próbowałeś, pomagają rozwiązać niespójności w opisie języka naturalnego.
- Pokaż, czego oczekujesz!!! Muszę usiąść i spróbować. Prawie nigdy nie znam odpowiedzi na pytanie bez wypróbowania niektórych rzeczy. Jeśli nie widzę przykładu tego, czego szukasz, mogę odpuścić pytanie, ponieważ nie mam ochoty zgadywać.
Lubię punkty (I wspomniałem o tym powyżej). Ale te punkty nie są tak naprawdę moją reputacją. Moja prawdziwa reputacja jest połączeniem tego, co inni na stronie myślą o mnie. Staram się być uczciwy i uczciwy i mam nadzieję, że inni to widzą. Dla pytającego oznacza to, że pamiętamy zachowania pytających. Jeśli nie wybierzesz odpowiedzi i nie wybierzesz dobrych odpowiedzi, pamiętam. Jeśli zachowujesz się w sposób, który mi się nie podoba lub w sposób, który mi się podoba, pamiętam. To również gra w które pytania będę odpowiedz.
W każdym razie, prawdopodobnie mogę kontynuować, ale oszczędzę wam wszystkich, którzy to czytają.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-01 09:39:28
Wyzwanie jednym z najtrudniejszych aspektów odpowiedzi na tak pytania jest czas potrzebny na odtworzenie problemu (w tym dane). Odpowiedzi na pytania, które nie mają jasnego sposobu odtworzenia 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, podając dane, które inni mogą wykorzystać do rozwiązania Twojego problemu.
Instrukcje dostarczone przez @ Andy do pisania dobre pytania Pandy są doskonałym miejscem do rozpoczęcia. Aby uzyskać więcej informacji, zobacz Jak zapytać i jak utworzyć Minimalne, kompletne i weryfikowalne przykłady.
Proszę jasno przedstawić swoje pytanie z góry. po poświęceniu czasu na napisanie pytania i przykładowego kodu, spróbuj je przeczytać i dostarczyć "Streszczenie" dla czytelnika, które podsumowuje problem i wyraźnie stwierdza pytanie.
pytanie oryginalne :
Mam te dane... Chcę to zrobić... Chcę, żeby mój wynik wyglądał tak...Jednak, kiedy próbuję zrobić [to], dostaję 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, czytelnik musi przejść długą drogę, zanim zrozumie, co problem w tym. Spróbuj ponownie Zadać pytanie, aby samo pytanie było na wierzchu, a następnie podaj niezbędne szczegóły.
Zmienione Pytanie :
Qustion: Jak mogę to zrobić?
Próbowałem znaleźć rozwiązania, robiąc [to] i [tamto].
Kiedy próbowałem zrobić [to], dostaję następujący problem...
Chciałbym, żeby moje ostateczne wyniki wyglądały tak...Oto jakiś minimalny kod, który może odtworzyć moje problem...
A oto jak odtworzyć moje przykładowe dane:
df = pd.DataFrame({'A': [...], 'B': [...], ...})
W RAZIE POTRZEBY PODAJ PRZYKŁADOWE DANE!!!
Czasami tylko głowa lub ogon ramki danych jest wszystkim, co jest potrzebne. Możesz również użyć metod zaproponowanych przez @ JohnE do tworzenia większych zbiorów danych, które mogą być powielane przez innych. Korzystając z jego przykładu do wygenerowania 100-rzędowej ramki danych 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 to były twoje rzeczywiste dane, możesz po prostu chcieć dołączyć głowę i / lub ogon dataframe w następujący sposób (pamiętaj, aby anonimizować wrażliwe dane):
>>> 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 również podać opis ramki danych (używając tylko odpowiednich kolumn). Ułatwia to innym sprawdzanie typów danych każdej kolumny i identyfikowanie innych typowych błędów (np. dat jako string vs. datetime64 vs. object):
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 ramka danych ma MultiIndex:
Jeśli ramka danych ma multiindex, musisz najpierw zresetować przed wywołaniem to_dict
. Ty następnie należy odtworzyć 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55
Oto moja wersja dput
- standardowe narzędzie R do tworzenia powtarzalnych raportów-dla pand DataFrame
s.
Prawdopodobnie nie powiedzie się w przypadku bardziej złożonych ramek, ale wydaje się, że działa 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 o wiele bardziej wyraziste wyjście niż DataFrame.to_dict
, np.,
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}}
Dla du
powyżej, ale zachowuje typy kolumn.
Np. w powyższym teście case,
du.equals(pd.DataFrame(du.to_dict()))
==> False
Ponieważ du.dtypes
jest uint8
i pd.DataFrame(du.to_dict()).dtypes
jest int64
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-08 03:20:49