Mam słownik, który zapewnia mapowanie z kanałów realnych numerów do identyfikatora. Biorąc pod uwagę listę Ktorek zawierających liczby, które są w obrębie tolerancji, ale nie Dokładnie równa tych w słowniku, chciałbym wyprodukować listę odpowiednich liczb całkowitych.

Przykład:

tdict = {(0.334, 0.333, 0.333):1, (0.167, 0.666, 0.167):2, (0.5, 0.5, 0):3}
tlist = [(0.333, 0.333, 0.333), (0.16667, 0.6666667, 0.17), (0.34, 0.33, 0.33), (0.5001, 0.4999, 0.0)]
tol = 0.01

Uruchamianie kodu, które chcę uzyskać wynik

ilist = [1,2,1,3]

Ponieważ wszystkie liczby w każdym z Ktorek mieści się w danej tolerancji tych w odpowiednich krotkach w tdict. Mógłbym to zrobić, idziesz nad tdict.keys() i porównując się z każdym indywidualnie, ale czuję, że powinna być lepsza droga. Jaki jest najbardziej skuteczny sposób na uzyskanie odpowiednich liczb całkowitych do tych krotek? Nie musi obejmować słownika, który właśnie wydawał się dla mnie najbardziej naturalny. Używam Pythona 3.

3
astay13 31 sierpień 2012, 19:58

5 odpowiedzi

Najlepsza odpowiedź

Najwyraźniej chcesz projektować punkty w przestrzeni 3D na siatce 3D z pewnym odstępem siatki (który jest bezpośrednio związany z wartością tolerancji) i stwórz jakiś histogram. Napisz sobie funkcję projekcji: potrzeba dowolnej liczby 3-elementu / krotle (wektor opisujący punkt w przestrzeni) jako argument i projektuje go na określony punkt siatki. Robisz to do wypełniania słownika, a także do odczytu. Ponadto, jeśli chodzi o klucze w słowniku, myślę, że powinieneś iść z Ktostwami liczb całkowitych zamiast unosi się, ponieważ nie jestem pewien, czy pływaki mogą być identyczne.

Jest to przykład realizacji:

from collections import defaultdict
from random import random as rn

class Grid(object):
    def __init__(self, spacing):
        self.spacing = spacing
        self.griddict = defaultdict(int)

    def add_point(self, coords):
        """
        `vid`, a voxel id, is a tuple of indices, indicating one grid
        bin for each dimension, e.g. (1, 5, 2)
        rule: i_x = int(floor(x_coord / spacing))
        """
        vid = tuple([int(c//self.spacing) for c in coords])
        self.griddict[vid] += 1

    def get_point(self, coords):
        vid = tuple([int(c//self.spacing) for c in coords])
        return self.griddict[vid]

    def vid_centercoords(self, vid):
        """
        Return the real coordinates in space for a certain voxel,
        which is identified by its voxel id `vid` (a tuple of indices).
        """
        return tuple([(i-1)*self.spacing + self.spacing/2 for i in vid])



N = 20
fillpoints = [(rn(),rn(),rn()) for _ in xrange(N)]
testpoints = [(rn(),rn(),rn()) for _ in xrange(N)]

grid = Grid(spacing=0.3)

for p in fillpoints:
    grid.add_point(p)

print [grid.get_point(p) for p in testpoints]

Co robi: tworzy 20 losowych wektorów w przestrzeni 3D (wszystkie współrzędne między 0 a 1). Wypełniona siatka 3D przy użyciu tych punktów w przestrzeni. Siatka ma odstępy 0,3 w każdym wymiarze. Każda z tych 20 punktów w przestrzeni jest przypisana do pewnego VOXEL (tylko słowo na piksel 3D) w sieci. Każde zadanie zwiększyło licznik odpowiedniego woksula o 1 (renderowanie siatki do histogramu). Następnie, inny losowy zestaw 20 wektorów służy do odczytania wokseli. Punkty te są ponownie wyświetlanymi na wokseli, ale tym razem licznik jest właśnie zwrócony zamiast wzrastał. Test wykonawczy:

$ python gridtest.py 
[2, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0]

Wykonanie za pomocą danych:

fillpoints = [(0.334, 0.333, 0.333), (0.167, 0.666, 0.167), (0.167, 0.666, 0.167), (0.5, 0.5, 0), (0.5, 0.5, 0), (0.5, 0.5, 0)]
testpoints = [(0.333, 0.333, 0.333), (0.16667, 0.6666667, 0.17), (0.34, 0.33, 0.33), (0.5001, 0.4999, 0.0)]

grid = Grid(spacing=0.03)
for p in fillpoints:
    grid.add_point(p)
print [grid.get_point(p) for p in testpoints]

Drukuje [1, 2, 1, 3] zgodnie z potrzebami. Nie pomyślałem głęboko o relacji spacing=3*tolerance. Prawdopodobnie jest nie tak. Wiem tylko, że istnieje relacja deterministyczna. Określenie / znalezienie tej formuły pozostaje dla Ciebie jako ćwiczenie :)

6
Dr. Jan-Philip Gehrcke 31 sierpień 2012, 16:46
  1. Sortuj tdict.keys() według odległości do każdego punktu tlist z kolei.
  2. Wybierz pierwsze kilka i spójrz w tdict.
2
Katriel 31 sierpień 2012, 16:03

Jeśli masz dostęp do NUMPY, możesz użyć numpy.allclose sprawdź dopasowanie:

>>> import numpy
>>> numpy.allclose((0.334, 0.333, 0.333), (0.333, 0.333, 0.333))
False
>>> numpy.allclose((0.334, 0.333, 0.333), (0.333, 0.333, 0.333), atol=0.1)
True
2
jterrace 31 sierpień 2012, 16:15

Możesz wykonać funkcję wyszukiwania (która szuka zaokrąglonej wersji Tuple):

def look_up_tdict( t ):
    return tdict[ (float('%.3f' % t[0]),
                   float('%.3f' % t[1]),
                   float('%.3f' % t[2])
                 ]

Uwaga: Daje błąd, jeśli nic w słowniku nie jest blisko t. możesz wypełnić ilist:

ilist = [ look_up_tdict(t) for t in tlist ]
1
Andy Hayden 31 sierpień 2012, 16:11
 tolerance = 0.1
 for i in tlist:
      list2 = filter(lambda x:abs(sum(i)-sum(x))<tolerance,tdict
      print [tdict[itm] for itm in list2]

Myślę, że to będzie działać ... nie pozytywnie ... W rzeczywistości wygląda na to, że nie daje ci pożądanego wyjścia

0
Joran Beasley 31 sierpień 2012, 16:12