2009-02-03 23 views
8

Tengo un pequeño problema de Java Deseo traducir a Python. Por lo tanto, necesito una matriz multidimensional. En Java se ve así:Conjunto multidimensional en Python

double dArray[][][] = new double[x.length()+1][y.length()+1][x.length()+y.length()+3]; 
dArray[0][0][0] = 0; 
dArray[0][0][1] = POSITIVE_INFINITY; 

Se crearán otros valores bei loops y se escribirán en la matriz.

¿Cómo puedo crear una instancia de la matriz?

PS: No hay multiplicación de matrices involucrados ...

+0

Por cierto, puedes obtener el infinito de coma flotante en python como' float ('inf') '. Se comporta más o menos como era de esperar, la mayoría de las operaciones solo te dan inf, y algunas te dan nan. –

+0

(se fusionó con una pregunta anterior; lo mantuvo como el maestro como un: el OP todavía existe, b: la pregunta está mejor redactada, yc: para evitar muchos nigromantes) –

Respuesta

11

Puede crear utilizando listas anidadas:

matrix = [[a,b],[c,d],[e,f]] 

Si tiene que ser dinámico que es más complicado, por qué no escribir una pequeña clase ti mismo?

class Matrix(object): 
    def __init__(self, rows, columns, default=0): 
     self.m = [] 
     for i in range(rows): 
      self.m.append([default for j in range(columns)]) 

    def __getitem__(self, index): 
     return self.m[index] 

Esto puede ser usado como esto:

m = Matrix(10,5) 
m[3][6] = 7 
print m[3][6] // -> 7 

estoy seguro de que uno podría aplicar mucho más eficiente. :)

Si necesita matrices multidimensionales, puede crear una matriz y calcular la compensación o utilizar matrices en matrices en matrices, lo que puede ser bastante malo para la memoria.(Podría ser más rápido sin embargo ...) He implementado la primera idea de esta manera:

class Matrix(object): 
    def __init__(self, *dims): 
     self._shortcuts = [i for i in self._create_shortcuts(dims)] 
     self._li = [None] * (self._shortcuts.pop()) 
     self._shortcuts.reverse() 

    def _create_shortcuts(self, dims): 
     dimList = list(dims) 
     dimList.reverse() 
     number = 1 
     yield 1 
     for i in dimList: 
      number *= i 
      yield number 

    def _flat_index(self, index): 
     if len(index) != len(self._shortcuts): 
      raise TypeError() 

     flatIndex = 0 
     for i, num in enumerate(index): 
      flatIndex += num * self._shortcuts[i] 
     return flatIndex 

    def __getitem__(self, index): 
     return self._li[self._flat_index(index)] 

    def __setitem__(self, index, value): 
     self._li[self._flat_index(index)] = value 

Puede ser utilizado como esto:

m = Matrix(4,5,2,6) 
m[2,3,1,3] = 'x' 
m[2,3,1,3] // -> 'x' 
3

Para los datos numéricos, Numpy Arrays:

>>> matrix1 = array(([0,1],[1,3])) 
>>> print matrix1 
[[0 1] 
[1 3]] 

Para los datos generales (por ejemplo, cadenas), se puede utilizar una lista de listas, la lista de tuplas, ...

matrix2 = [['a','b'], ['x','y']] 
+0

¿Puedo inicializarlo un número determinado de filas y columnas como ¿Cª? –

+0

Los objetos mutables (por ejemplo, la lista) pueden cambiar, por lo que la inicialización no siempre es relevante. En numpy, una matriz tiene una forma (dimensiones) que se puede modificar sin cambiar los datos. – gimel

+1

@Popper: Sí. ceros ((3,4)) creará una matriz de ceros de 3x4. –

18

Si se restringe a sí mismo a la biblioteca estándar de Python, a continuación, una lista de listas es la construcción más cercano:

arr = [[1,2],[3,4]] 

ofrece una matriz similar a 2d. Se puede acceder a las filas como arr[i] para i en {0,..,len(arr}, pero el acceso a la columna es difícil.

Si está dispuesto a agregar una dependencia de biblioteca, el paquete NumPy es lo que realmente desea. Se puede crear una matriz de longitud fija de una lista de listas usando:

import numpy 
arr = numpy.array([[1,2],[3,4]]) 

acceso de columna es el mismo que para las listas de la lista-de-, pero el acceso columna es fácil: arr[:,i] para i en {0,..,arr.shape[1]} (el número de columnas).

De hecho, las matrices NumPy pueden ser n-dimensionales.

matrices vacías pueden ser creados con

numpy.empty(shape) 

donde shape es una tupla de tamaño en cada dimensión; shape=(1,3,2) proporciona una matriz de 3 d con el tamaño 1 en la primera dimensión, el tamaño 3 en la segunda dimensión y el 2 en la 3ra dimensión.

Si desea almacenar objetos en una matriz NumPy, se puede hacer eso también:

arr = numpy.empty((1,), dtype=numpy.object) 
arr[0] = 'abc' 

Para obtener más información sobre el proyecto NumPy, echa un vistazo a la NumPy homepage.

+0

No es necesario usar tupla. 'numpy.empty ([1])' funciona también. – jfs

+0

El generador de números "aleatorios" simple: 'noise = lambda: numpy.empty ([1]) [0]' – jfs

+0

Es cierto que cualquier iterable (lista, tupla, etc.) funciona como el argumento de dimensiones. Su generador de números "aleatorios" se basa en que la memoria no inicializada es "aleatoria" y no debe usarse * nunca * como fuente de aleatoriedad para nada que se relacione (por ejemplo, criptografía). –

13

para crear una matriz estándar de Python de matrices de tamaño arbitrario:

a = [[0]*cols for _ in [0]*rows] 

Se accede así:

a[0][1] = 5 # set cell at row 0, col 1 to 5 

Una pequeña Gotcha pitón que vale la pena mencionar: Es tentador simplemente escriba

a = [[0]*cols]*rows 

pero que va a copiar el mismo conjunto de columnas a cada fila, lo que da como resultado un comportamiento no deseado. A saber:

>>> a[0][0] = 5 
>>> print a[1][0] 
5 
+4

Prefiero usar: '[[0] * cols para _ en xrange (filas)]' – jfs

+0

@ J.F.Sebastian Ya yo también, de verdad. Acabo de encontrar la simetría atractiva en el momento de escribir esto. :-) – Deestan

+0

plus1 para el gotcha. – AShelly

10

Las matrices multidimensionales son un poco turbias. Hay pocas razones para usarlos y muchas razones para pensarlo dos veces y usar algo más que refleje más adecuadamente lo que está haciendo. [Insinuación. su pregunta era delgada en contexto ;-)]

Si está haciendo cálculos matemáticos, entonces use numpy.

Sin embargo, algunas personas han trabajado con idiomas que les obligan a utilizar matrices multidimensionales porque es todo lo que tienen. Si eres tan viejo como yo (comencé a programar en los años 70), entonces puedes recordar los días en que las matrices multidimensionales eran la única estructura de datos que tenías. O bien, su experiencia puede haberlo limitado a los idiomas en los que tuvo que transformar su problema en matrices multidimensionales.

Supongamos que tiene una colección n Puntos 3D. Cada punto tiene un valor de x, y, z y de tiempo. ¿Es esto una matriz n x 4? O una matriz 4 * n? Realmente no.

Dado que cada punto tiene 4 valores fijos, esta es más propiamente una lista de tuplas.

a = [ (x, y, z, t), (x, y, z, t), ... ] 

Mejor aún, podríamos representar esto como una lista de objetos.

class Point(object): 
    def __init__(self, x, y, z, t): 
     self.x, self.y, self.z, self.t = x, y, z, t 

a = [ Point(x,y,x,t), Point(x,y,z,t), ... ] 
+1

+1. Mencionaría 'namedtuple's – jfs

0

Otra opción es el uso de un diccionario:

>>> from collections import defaultdict 
>>> array = defaultdict(int) # replace int with the default-factory you want 
>>> array[(0,0)] 
0 
>>> array[(99,99)] 
0 

Tendrá que hacer un seguimiento de los límites inferiores & superiores también.

11

Tome un vistazo a numpy

He aquí un fragmento de código para usted

import numpy as npy 

d = npy.zeros((len(x)+1, len(y)+1, len(x)+len(y)+3)) 
d[0][0][0] = 0 # although this is unnecessary since zeros initialises to zero 
d[i][j][k] = npy.inf 

No creo que necesite implementar una aplicación científica para justifica el uso de numpy. Es más rápido y más flexible y puedes almacenar prácticamente cualquier cosa. Dado que creo que probablemente sea mejor tratar de justificar no usándolo. Hay razones legítimas, pero agrega mucho y cuesta muy poco, por lo que merece consideración.

P.S. ¿Son las longitudes de su matriz correcta? Se ve como una matriz de forma bastante peculiar ...

4

Probablemente no es relevante para usted, pero si usted está haciendo un trabajo serio matriz ver numpy

5

Si estás bien utilizando matrices dispersas, podría utilizar un diccionario para almacenar su valores. dicts de Python permiten usar tuplas como claves, como tal, podría asignar a y acceder a los elementos de la "matriz dispersa" (que en realidad es un diccionario aquí) como este:

d = {} 
d[0,2,7] = 123 # assign 123 to x=0, y=2, z=7 
v = d[0,2,7] 
+0

Buen truco para almacenar un conjunto multidimensional. Sin embargo, las cosas se pondrían muy complicadas al tratar de repetir los elementos, por ejemplo, de una columna, o una fila, o incluso para poder obtener las 'dimensiones'. –

+0

De hecho. Si tuviera que usar algo como esto, por supuesto, encapsular esto en una clase e introducir métodos para el acceso de lectura/escritura. Una variable de instancia almacenaría la dimensión de la matriz y los métodos de lectura/escritura devolverían un valor predeterminado para los elementos no asignados (capturando KeyError). – paprika

+0

+1: el diccionario es considerablemente más simple. La iteración sobre dimensiones es fácil, no desordenada. xRange = set ([k [0] para k en d.keys()]), yRange = set ([k [1] para k en d.keys()]) –

2

He aquí una forma rápida de crear un anidado lista de 3 dimensiones inicializado con ceros:

# dim1, dim2, dim3 are the dimensions of the array 
a =[[[0 for _ in range(dim1)] for _ in range(dim2)] for _ in range(dim1) ] 
a[0][0][0] = 1 

esta es una lista de listas de listas, un poco más flexible que una matriz, que puede hacer:

a[0][0] = [1,2,3,4] 

para reemplazar toda una fila en la matriz, o ev en el abuso de esa manera:

a[0] = "Ouch" 
print a[0][0] #will print "O", since strings are indexable the same way as lists 
print a[0][0][0] #will raise an error, since "O" isn't indexable 

pero si necesita el rendimiento, entonces estoy de acuerdo que numpy es el camino a seguir.

Además, tenga cuidado de:

a = [[[0] * 5]*5]*5] 

Si intenta a[0][0][0]=7 en el objetivo anterior, se verá lo que está mal con eso.

0

acabo entré en una necesidad similar y codificados esto:

def nDimensionsMatrix(dims, elem_count, ptr=[]): 
    if (dims > 1): 
     for i in range(elem_count[dims-1]): 
      empty = [] 
      ptr.append(empty) 
      nDimensionsMatrix(dims-1, elem_count, empty) 
     return ptr 
    elif dims == 1: 
     ptr.extend([0 for i in range(elem_count[dims])]) 
     return ptr 

matrix = nDimensionsMatrix(3, (2,2,2)) 

No estoy buscando a la velocidad, funcionalidad única;)

Quiero crear una matriz con n dimensiones y inicializar con 0 (un elem_count cantidad de elementos en cada dimensión).

Espero su ayuda a alguien

0

fácil, cuando se utiliza numpy:

b = ones((2,3,4)) # creates a 2x3x4 array containing all ones. 

'unos' pueden ser sustituidos con 'ceros'

Cuestiones relacionadas