2015-05-12 10 views
8

Chciałbym połączyć funkcjonalność numpy's array z natywnym pytonem dict, a mianowicie stworzyć wielowymiarową tablicę, która może być indeksowana za pomocą łańcuchów.Python jak indeksować wielowymiarową tablicę z kluczem ciąg, jak dyktafon

Na przykład, mogę to zrobić:

dict_2d = {'a': {'x': 1, 'y': 2}, 
      'b': {'x': 3, 'y': 4}} 
print dict_2d['a','y'] # returns 2 

Wiem, że mógłbym zrobić dict_2d['a']['x'] ale długoterminowe Chciałbym móc je traktować jak NumPy tablicami tym robi mnożenia macierzy i takie, a nie ów możliwe z warstwowymi dyktami.

Nie jest też trudno napisać prostą wersję klasy, w której używam klasy do zamiany wszystkich łańcuchów na indeksy int, a następnie użyj numpy, ale chciałbym użyć czegoś, co już istnieje, jeśli to możliwe.

Edytuj: Nie potrzebuję niesamowitej wydajności. Będę pracował z może 10x10 tablic. Moim celem jest uczynienie pisania kodu prostym i solidnym. Praca z numpy tablicami nie różni się tak bardzo od pisania w Fortranie. Spędziłem wystarczająco dużo mojego życia wyszukując błędy indeksowania Fortran ...

+1

Czy rzeczywiście potrzebujesz danych do przechowywania w strukturze zagnieżdżonej? Możesz po prostu użyć dyktatury, której kluczami są krotki. – BrenBarn

+0

@BrenBarn, który mógłby użyć _a lot_ pamięci – 0x539

+0

zawsze możesz utworzyć klasę kontenerów, która przeciąża '__getitem__', aby to zrobić, ponieważ nie można używać krotek jako indeksów w zagnieżdżonych dyktach. – 0x539

Odpowiedz

9

Być może szukasz pandas, który zapewnia przydatne typy danych, które zawijają numpy tablice, umożliwiając dostęp do wierszy i kolumn według nazwy, a nie tylko przez liczbę .

2

lubię daje gotowych odpowiedzi - ale myślę, że zajęłoby znacznie więcej czasu, aby wyjaśnić w języku angielskim -

Podstawowym pomysłem sprowadzić obiektów droga numpy nie jest dostosowanie sposobu __getitem__ - przecinek oddzielone wartości są prezentowane w metodzie jako krotki - ty po prostu użyj wartości w krotce jako indeksy do zagnieżdżonych słowników w sekwencji.

Poza tym, Python wykonane łatwo stworzyć w pełni funkcjonalne DICT jako ekwiwalent z tych collections.abc klas: jeśli wdrożenie minimalny zestaw metod, gdy inhetiring z collections[.abc].MutableMapping wszystkie słowniku zachowanie jest emulowane - (__getitem__, __setitem__, __delitem__, __iter__, __len__) - Wtedy, to to kwestia właściwej iteracji poprzez kluczowe komponenty i tworzenia nowych, pustych, zwykłych słowników do przechowywania potrzebnych wartości.

try: 
    from collections import MutableMapping 
except ImportError: 
    # Python3 compatible import 
    from collections.abc import MutableMapping 

class NestedDict(MutableMapping): 
    def __init__(self, *args, **kw): 
     self.data = dict(*args, **kw) 

    def get_last_key_levels(self, key, create=False): 
     if not isinstance(key, tuple): 
      key = (key,) 
     current_data = self.data 
     for subkey in key: 
      previous = current_data 
      current_data = current_data[subkey] if not create else current_data.setdefault(subkey, {}) 
     return previous, current_data, subkey 

    def __getitem__(self, key): 
     previous, current_data, lastkey = self.get_last_key_levels(key) 
     return current_data 

    def __setitem__(self, key, value): 
     previous, current_data, lastkey = self.get_last_key_levels(key, True) 
     previous[lastkey] = value 

    def __delitem__(self, key): 
     previous, current_data, lastkey = self.get_last_key_levels(key) 
     del previous[lastkey] 

    def __iter__(self): 
     return iter(self.data) 

    def __len__(self): 
     return len(self.data) 

    def __repr__(self): 
     return "NestedDict({})".format(repr(self.data)) 

I jesteś ustawiony, aby przejść:

>>> from nesteddict import NestedDict 
>>> x = NestedDict(a={}) 
NestedDict({'a': {}}) 
>>> x["a", "b"] = 10 
>>> x 
NestedDict({'a': {'b': 10}}) 
>>> x["a", "c", "e"] = 25 
>>> x 
NestedDict({'a': {'c': {'e': 25}, 'b': 10}}) 
>>> x["a", "c", "e"] 
25 
>>> 

Należy pamiętać, że jest to realizacja na wysokim poziomie, który będzie po prostu działać, ale trzeba będzie nigdzie w pobliżu poziomu optymalizacji można uzyskać na NumPy z tym - wręcz przeciwnie. Jeśli będziesz potrzebował wykonać szybkie operacje na danych w tych obiektach, być może powinieneś sprawdzić "cython" - lub uciekniesz się do pomysłu transponowania kluczy dyktujących na klucze nuemric i użyj NumPy (ten pomysł może wciąż wybierać pomysły z tej odpowiedzi)

+1

Sugestia pandy BrenBarna robi większość tego, czego chcę, chociaż nie pozwala na NestedDict ['a', 'x']. Zawinięcie cienkiej warstwy na pandach za pomocą '__getitem__' i' __setitem__' zgodnie z opisem spowoduje zebranie ich wszystkich razem. – ericksonla

0

Stosować pandy Powiedzmy, że plik jest tak:

test.csv:

Params, Val1, Val2, Val3 
Par1,23,58,412 
Par2,56,45,123 
Par3,47,89,984 

Więc można zrobić coś takiego w Pythonie:

import pandas as pd 
x = pd.read_csv('test.csv', index_col='Params') 
x['Val1']['Par3'] 
47