Convertir matriz numpy en tupla

108

Nota: Esto solicita lo contrario de la conversión habitual de tupla a matriz.

Tengo que pasar un argumento a una función (c ++ envuelto) como una tupla anidada. Por ejemplo, las siguientes obras

X = MyFunction( ((2,2),(2,-2)) )

mientras que los siguientes no

X = MyFunction( numpy.array(((2,2),(2,-2))) )
X = MyFunction( [[2,2],[2,-2]] )

Desafortunadamente, el argumento que me gustaría usar me viene como una matriz numerosa. Esa matriz siempre tiene dimensiones 2xN para algunos N, que pueden ser bastante grandes.

¿Existe una manera fácil de convertir eso en una tupla? Sé que podría simplemente recorrer, creando una nueva tupla, pero preferiría que hubiera un buen acceso que proporciona la matriz numpy.

Si no es posible hacer esto tan bien como espero, ¿cuál es la forma más bonita de hacerlo mediante un bucle o lo que sea?

Miguel
fuente

Respuestas:

157
>>> arr = numpy.array(((2,2),(2,-2)))
>>> tuple(map(tuple, arr))
((2, 2), (2, -2))
Niklas B.
fuente
29
Entonces, para una matriz 1-d simpletuple(arr)
FindOutIslamNow
26

Aquí hay una función que lo hará:

def totuple(a):
    try:
        return tuple(totuple(i) for i in a)
    except TypeError:
        return a

Y un ejemplo:

>>> array = numpy.array(((2,2),(2,-2)))
>>> totuple(array)
((2, 2), (2, -2))
Bi Rico
fuente
1
Buena generalización. Sin embargo, como novato en Python, me pregunto si se considera un buen estilo usar excepciones para una condición que es casi tan común como el estado no excepcional. Al menos en c ++, el control de flujo por excepciones suele estar mal visto. ¿Sería mejor probar si type(a)==numpy.ndarray?
Mike
9
Esto es bastante común en Python debido al concepto de "tipificación de pato" y EAFT, más aquí: docs.python.org/glossary.html#term-duck-typing . La ventaja de este enfoque es que convertirá cualquier secuencia anidada en tuplas anidadas, no solo una matriz. Una cosa que debería haber hecho y que he solucionado es especificar qué errores quiero que se manejen con el bloque except.
Bi Rico
3
En C ++, las excepciones son lentas en relación con los condicionales por diversas razones. En Python, son aproximadamente los mismos en términos de rendimiento: este es uno de los lugares en los que tenemos que verificar nuestras intuiciones de C ++ en la puerta.
dbn
8

No estaba satisfecho, así que finalmente usé esto:

>>> a=numpy.array([[1,2,3],[4,5,6]])
>>> a
array([[1, 2, 3],
       [4, 5, 6]])

>>> tuple(a.reshape(1, -1)[0])
(1, 2, 3, 4, 5, 6)

No sé si es más rápido, pero parece más efectivo;)

esperando que ayude
fuente
3
Esa no era la forma que quería para la tupla.
Mike
5

Otra opción

tuple([tuple(row) for row in myarray])

Si está pasando matrices NumPy a funciones C ++, es posible que también desee utilizar Cython o SWIG.

Greg von Winckel
fuente
Eso no se convierte en tupla. ¿Se convierte en una lista?
Peter
¿Lo intentaste? Hace una tupla cuando entro. Tenga en cuenta que la última función llamada es tupla, que devuelve una tupla. Si solo tiene la parte [...] sin la tupla externa, obtendrá una lista de tuplas.
Greg von Winckel
¿Existe un método más rápido?
Vicrobot
1
Puede evitar crear el intermedio listomitiendo los corchetes, es decir, usandotuple(tuple(row) for row in myarray)
norok2
1

Si te gustan los cortes largos, aquí tienes otra forma de tupla (tupla (a_m.tolist ()) para a_m en a)

from numpy import array
a = array([[1, 2],
           [3, 4]])
tuple(tuple(a_m.tolist()) for a_m in a )

La salida es ((1, 2), (3, 4))

Tenga en cuenta que solo (tuple (a_m.tolist ()) para a_m en a) dará una expresión generadora. Algo inspirado por el comentario de @ norok2 a la respuesta de Greg von Winckel

Tejas Shetty
fuente