Converter matriz numpy em tupla

108

Nota: Isso está pedindo o reverso da conversão usual de tupla em array.

Eu tenho que passar um argumento para uma função (c ++ empacotado) como uma tupla aninhada. Por exemplo, o seguinte funciona

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

Considerando que o seguinte não

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

Infelizmente, o argumento que eu gostaria de usar vem a mim como uma matriz numpy. Essa matriz sempre tem dimensões 2xN para algum N, que pode ser muito grande.

Existe uma maneira fácil de converter isso em uma tupla? Eu sei que poderia simplesmente fazer um loop, criando uma nova tupla, mas preferiria se houvesse algum bom acesso que a matriz numpy fornece.

Se não for possível fazer isso tão bem quanto eu espero, qual é a maneira mais bonita de fazer isso em loop ou algo assim?

Mike
fonte

Respostas:

157
>>> arr = numpy.array(((2,2),(2,-2)))
>>> tuple(map(tuple, arr))
((2, 2), (2, -2))
Niklas B.
fonte
29
Portanto, para uma matriz 1-d simplestuple(arr)
FindOutIslamNow
26

Aqui está uma função que fará isso:

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

E um exemplo:

>>> array = numpy.array(((2,2),(2,-2)))
>>> totuple(array)
((2, 2), (2, -2))
Bi Rico
fonte
1
Boa generalização. Como um novato em Python, no entanto, eu me pergunto se é considerado um bom estilo usar exceções para uma condição que é quase tão comum quanto o estado não excepcional. Pelo menos em c ++, o controle de fluxo por exceções geralmente é mal visto. Seria melhor testar se type(a)==numpy.ndarray?
Mike,
9
Isso é muito comum em python por causa do conceito de "duck-typing" e EAFT, mais aqui: docs.python.org/glossary.html#term-duck-typing . A vantagem dessa abordagem é que ela converterá qualquer sequência aninhada em tuplas aninhadas, não apenas um array. Uma coisa que eu deveria ter feito e consertado é especificar quais erros quero que sejam tratados pelo bloco except.
Bi Rico,
3
Em C ++, as exceções são lentas em relação às condicionais por vários motivos. Em Python, eles são aproximadamente os mesmos em termos de desempenho - este é um dos lugares em que temos que verificar nossas intuições C ++ na porta.
dbn
8

Eu não estava satisfeito, então finalmente usei isto:

>>> 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)

Não sei se é mais rápido, mas parece mais eficaz;)

esperando que ajude
fonte
3
Essa não era a forma que eu queria para a tupla.
Mike
5

Outra opção

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

Se você está passando arrays NumPy para funções C ++, você também pode querer usar Cython ou SWIG.

Greg von Winckel
fonte
Isso não se converte em tupla. Converte em uma lista?
Peter
Você experimentou? Faz uma tupla quando eu executo. Observe que a última função chamada é tupla, que retorna uma tupla. Se você tiver apenas a parte [...] sem a tupla externa, você receberá uma lista de tuplas.
Greg von Winckel
existe um método mais rápido?
Vicrobot
1
Você pode evitar a criação do intermediário listomitindo os colchetes, ou seja, usandotuple(tuple(row) for row in myarray)
norok2
1

Se você gosta de cortes longos, aqui está outra forma de tupla (tupla (a_m.tolist ()) para a_m em a)

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

A saída é ((1, 2), (3, 4))

Observe apenas (tupla (a_m.tolist ()) para a_m em a) fornecerá uma expressão de gerador. Meio inspirado pelo comentário de @ norok2 à resposta de Greg von Winckel

Tejas Shetty
fonte