Atribuição de matriz numpy com cópia

103

Por exemplo, se temos um numpyarray Ae queremos um numpyarray Bcom os mesmos elementos.

Qual é a diferença entre os métodos a seguir (veja abaixo)? Quando é alocada memória adicional e quando não é?

  1. B = A
  2. B[:] = A(igual a B[:]=A[:]?)
  3. numpy.copy(B, A)
mrgloom
fonte

Respostas:

127

Todas as três versões fazem coisas diferentes:

  1. B = A

    Isso associa um novo nome Bao objeto existente já nomeado A. Posteriormente, eles se referem ao mesmo objeto, portanto, se você modificar um no local, verá a mudança através do outro também.

  2. B[:] = A(igual a B[:]=A[:]?)

    Isso copia os valores Aem uma matriz existente B. As duas matrizes devem ter o mesmo formato para que isso funcione. B[:] = A[:]faz a mesma coisa (mas B = A[:]faria algo mais parecido com 1).

  3. numpy.copy(B, A)

    Esta não é uma sintaxe legal. Você provavelmente quis dizer B = numpy.copy(A). Isso é quase o mesmo que 2, mas cria uma nova matriz, em vez de reutilizar a Bmatriz. Se não houvesse outras referências ao Bvalor anterior , o resultado final seria igual a 2, mas usará mais memória temporariamente durante a cópia.

    Ou talvez você quisesse dizer numpy.copyto(B, A), que é legal e é equivalente a 2?

Blckknght
fonte
21
@Mr_and_Mrs_D: Matrizes Numpy funcionam de maneira diferente das listas. Cortar um array não faz uma cópia, apenas cria uma nova visualização dos dados do array existente.
Blckknght
O que significa but B = A[:] would do something more like 1? De acordo com este stackoverflow.com/a/2612815 new_list = old_list[:] também é uma cópia.
mrgloom
4
@mrgloom: As matrizes Numpy funcionam de maneira diferente das listas quando se trata de fatiar e copiar seu conteúdo. Uma matriz é uma "visualização" de um bloco de memória subjacente onde os valores numéricos são armazenados. Fazer um slice como some_array[:]criará um novo objeto de array, mas esse novo objeto será uma visualização da mesma memória do array original, que não terá sido copiado. É por isso que eu disse que é mais parecido B = A. Leva apenas O(1)espaço e tempo, ao invés O(n)de cada um que uma cópia real precisaria.
Blckknght
27
  1. B=A cria uma referência
  2. B[:]=A faz uma cópia
  3. numpy.copy(B,A) faz uma cópia

os dois últimos precisam de memória adicional.

Para fazer uma cópia profunda, você precisa usar B = copy.deepcopy(A)

Mailerdaimon
fonte
2
Referindo-se ao seu segundo exemplo: B[:] = Ase não fazer uma cópia profunda de matrizes de objeto do tipo, por exemplo A = np.array([[1,2,3],[4,5]]); B = np.array([None,None], dtype='O'). Agora tente B[:] = A; B[0][0]=99, isso mudará o primeiro elemento em A e B ! Que eu saiba, não há outra maneira de garantir uma cópia profunda, mesmo de um numpy-array, do quecopy.deepcopy
Rolf Bartstra
11

Esta é a única resposta que funciona para mim:

B=numpy.array(A)
Woeitg
fonte