2015-05-29 31 views
29

robię kilka ćwiczeń z zestawów danych tak:Lista wielu słowników Słownik VS z kilkoma listami?

Lista z wielu słowników

users = [ 
    {"id": 0, "name": "Ashley"}, 
    {"id": 1, "name": "Ben"}, 
    {"id": 2, "name": "Conrad"}, 
    {"id": 3, "name": "Doug"}, 
    {"id": 4, "name": "Evin"}, 
    {"id": 5, "name": "Florian"}, 
    {"id": 6, "name": "Gerald"} 
] 

słownik z kilku list

users2 = { 
    "id": [0, 1, 2, 3, 4, 5, 6], 
    "name": ["Ashley", "Ben", "Conrad", "Doug","Evin", "Florian", "Gerald"] 
} 

Pandy dataframes

import pandas as pd 
pd_users = pd.DataFrame(users) 
pd_users2 = pd.DataFrame(users2) 
print pd_users == pd_users2 

Pytania:

  1. Mam struktury zbiorów danych, takich jak użytkownicy lub podobnego users2?
  2. Czy występują różnice w wydajności?
  3. Czy jest czytelniejszy od drugiego?
  4. Czy istnieje standard, którego powinienem przestrzegać?
  5. Zwykle konwertuję je na ramki danych pand. Kiedy to robię, obie wersje są identyczne ... prawda?
  6. Dane wyjściowe są prawdziwe dla każdego elementu, więc nie ma znaczenia, czy pracuję z prawą panda df?
+5

Nicea pytania pójdę z pierwszej opcji, bo Recon wyszukiwania i wstawiania będzie mniej uciążliwe w porównaniu z drugi numer: – therealprashant

+4

Byłbym na pierwszym miejscu, o ile wygoda użytkowania jest najważniejszym aspektem. Posiadanie identyfikatora razem z NAME będzie przydatne podczas przenoszenia. –

+3

Pierwsza wersja jest łatwa do sortowania tam, gdzie druga nie. –

Odpowiedz

24

ten dotyczy column oriented databases kontra zorientowanej rzędu. Pierwszym przykładem jest struktura danych zorientowana na rząd, a druga kolumna. W szczególnym przypadku Pythona, pierwszy może być znacznie bardziej efektywny przy użyciu slots, tak że słownik kolumn nie musi być duplikowany dla każdego wiersza.

Który z formularzy działa lepiej zależy w dużej mierze od tego, co robisz z danymi; na przykład ustawienie zorientowane na wiersz jest naturalne, jeśli masz dostęp tylko do wszystkich wierszy. Z kolei zorientowane na kolumnę znacznie lepiej wykorzystują pamięci podręczne i takie, gdy wyszukuje się dane pole (w Pythonie może to być zmniejszone przez intensywne używanie odniesień, a typy takie jak array mogą je zoptymalizować). Tradycyjne bazujące na wierszach bazy danych często używają uporządkowanych indeksów kolumnowych, aby przyspieszyć wyszukiwanie, a znając te techniki, można zaimplementować dowolną kombinację przy użyciu magazynu kluczy.

Pandy przekształcają oba przykłady do tego samego formatu, ale sama konwersja jest droższa dla struktury zorientowanej na wiersz, ponieważ każdy pojedynczy słownik musi zostać odczytany. Wszystkie te koszty mogą być marginalne.

Jest trzecia opcja, która nie jest widoczna w twoim przykładzie: w tym przypadku masz tylko dwie kolumny, z których jedna jest liczbą całkowitą z sąsiadującego zakresu od 0. Może być zapisana w kolejności samych wpisów, co oznacza, że ​​cała struktura znajduje się na liście, którą nazwałeś: users2['name']; ale w szczególności wpisy są niekompletne bez ich pozycji. Lista tłumaczy się na wiersze za pomocą funkcji enumerate(). W bazach danych często występuje ten specjalny przypadek (na przykład sqlite rowid).

Zasadniczo zacznij od struktury danych, która zapewnia sensowność kodu i optymalizację tylko wtedy, gdy znasz przypadki użycia i masz wymierny problem z wydajnością. Narzędzia takie jak Panda prawdopodobnie oznaczają, że większość projektów będzie działała dobrze bez finetuningu.

+0

Przykład użycia 'slotów' do oszczędzania pamięci: http://tech.oyster.com/save-ram-with-python-slots/ –

4

users w sensie ogólnym jest w rzeczywistości zbiorem elementów user. Więc lepiej jest zdefiniować element user jako samodzielny byt. Twoja pierwsza opcja jest właściwa.

5

Czas złożoność dla wyszukiwań w -

  • List - O (n)
  • dicts - O (1)

Ale to nie zaszkodzi, jeśli ISN wiele danych” Te duże i nowoczesne procesory są dość wydajne.
Powinieneś pójść z tym, w którym odnośnik jest syntaktycznie czysty i czytelny (ważna jest czytelność).
Pierwsza opcja jest całkiem odpowiednia, ponieważ zmienna to zbiór użytkowników (którym przypisano identyfikator), podczas gdy druga to po prostu kolekcja nazw użytkowników i identyfikatorów.

+1

"Powinieneś pójść z tym, w którym wyszukiwanie jest syntaktycznie czyste i czytelne" +1. Ale nie sądzę, że złożoność czasu ma znaczenie, ponieważ nie wiemy, w jaki sposób uzyskuje dostęp do tych danych. –

6

Użytkownicy

  1. Kiedy trzeba dołączyć jakiś nowy użytkownik po prostu zrobić nowy dict wszystkie dane użytkownika i dołączyć go

  2. Łatwo sortable jak @StevenRumbalski zasugerował

  3. Wyszukiwanie będzie łatwe

  4. To jest bardziej kompaktowy i łatwy do opanowania, jak rośnie rekord (dla niektórych bardzo dużej liczby rekordów myślę, że musimy coś lepszego niż użytkownicy też)

Users2

  1. Osobiście widzę to po raz pierwszy i nie podchodzę do tego, jeśli mam dużą liczbę rekordów.

PS: Ale chciałbym dowiedzieć się zalety users2 nad users Znowu miła pytanie

1

Pierwsza opcja listy słowników będzie znacznie lepsza z kilku powodów. Lista zawiera takie metody, jak EXTEND, APPENT, PUSH, które nie są łatwo dostępne ze słownikami.

4

jakieś odpowiedzi dotyczące aspektu pandy:

  1. Oba dataframes rzeczywiście są takie same i są kolumny zorientowany, co jest dobre, bo pandy działa najlepiej, gdy dane w każdej kolumnie jest jednorodny (tj numery można zapisać jako ints i floats). Głównym powodem korzystania z pand jest przede wszystkim to, że możesz wykonywać wektoryzowane operacje numeryczne, które są o rząd wielkości szybsze od czystego Pythona - ale to zależy od organizacji kolumnowej, gdy dane są heterogeniczne.
  2. Możesz zrobić pd_users.T, aby przetransponować, jeśli chcesz, a następnie zobaczysz (przez info() lub dtypes), że wszystko jest następnie przechowywane jako obiekt ogólnego przeznaczenia, ponieważ kolumna zawiera zarówno ciągi, jak i liczby.
  3. Po przekonwertowaniu można wykonać pd_users.set_index('id'), aby Twoja ramka danych była zasadniczo słownikiem z kluczami id. Lub vice versa z name.
  4. To dość powszechne (i ogólnie dość szybko) zmiana indeksów, a następnie zmiana ich z powrotem, transpozycja, podzbiór itp. Podczas pracy z pandami, więc zwykle nie jest konieczne, aby myśleć zbyt dużo o strukturze na początku. Po prostu zmień go tak, jak potrzebujesz w locie.
  5. Może to zejść na styczną, ale prostszym analogiem pandy tego, co powyżej, może być Series, a nie DataFrame. Seria jest zasadniczo kolumną ramek danych, chociaż tak naprawdę jest to jednowymiarowa tablica danych z indeksem ("klucze").

Szybkie demo (używając df jak nazwa dataframe, wspólna konwencja):

>>> df.set_index('name') 

     id 
name  
Ashley 0 
Ben  1 
Conrad 2 
Doug  3 
Evin  4 
Florian 5 
Gerald 6 

>>> df.set_index('name').T 

name Ashley Ben Conrad Doug Evin Florian Gerald 
id   0 1  2  3  4  5  6 

>>> df.set_index('name').loc['Doug'] 

id 3 
Name: Doug, dtype: int64 
+0

Hej! Wspomniałeś, że obie ramki danych są zorientowane na kolumny. Najbardziej uprzywilejowana odpowiedź sugeruje teraz jedną kolumnę, a drugą - wiersz. Czy możesz potwierdzić? – megashigger

+1

Uważam, że @YannVernier odnosi się tylko do przypadku * przed * konwertowaniem na pandy. Już udowodniliście, że są tacy sami z 'pd_users == pd_users2'. Ale możesz zrobić 'pd_users == pd_users2.T' (wstaw transpozycję do jednej z nich) w celu dalszej weryfikacji. Zostanie zgłoszony wyjątek, ponieważ obie ramki danych przestają być zgodne. Oprócz sprawdzania równości, samo drukowanie ramki danych pokazuje, w jaki sposób panda porządkuje dane pod względem wierszy i kolumn. – JohnE

+0

Ach, to ma sens. Dzięki za wytłumaczenie. – megashigger