| | | |

Algoritmos e Programação I

Compre o e-book deste material aqui! Consulte outras formas de colaborar.

5.3 Arranjos multidimensionais

Um arranjo numpy.array é um tabelamento de elementos de um mesmo tipo. Os elementos são organizados por eixos indexados (em inglês, axes). Enquanto que nas seções anteriores nos restringimos a arrays unidimensionais (de apenas um eixo), aqui, vamos estudar a alocação e manipulação de arranjos de vários eixos.

5.3.1 Alocação, indexação e fatiamento

A alocação de um numpy.array com mais de um eixo pode ser feita usando-se de listas encadeadas. Por exemplo,

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

cria o arranjo a de dois eixos, enquanto

1b = np.array([[[1,2],[3,4]],[[-1,-2],[-3,-4]]])
2b
array([[[ 1, 2],
[ 3, 4]],
[[-1, -2],
[-3, -4]]])

cria o arranjo b de três eixos. Para fazer um paralelo com a matemática, o arranjo a é similar (mas, não equivalente) a matriz A=[ai,j]i,j=12,3

A=[123456], (5.51)

e o arranjo b é similar (mas, não equivalente) ao tensor B=[bi,j,k]i,j,k=12,2,2.

A propriedade .shape é um tuple contendo o tamanho de cada eixo. Por exemplo,

1a.shape
(2, 3)
1a.shape[0]
2

informa que a tem dois eixos, o primeiro com tamanho 2 e o segundo com tamanho 3. Um paralelo com matrizes, dizemos que a tem duas linhas e três colunas. No caso do arranjo b, temos

1b.shape
(2, 2, 2)
1b.shape[2]
2

o que nos informa tratar-se de um array de três eixos, cada um com tamanho 2.

O número total de elementos de um array pode ser obtido do atributo numpy.ndarray.size. Por exemplo,

1a.size, b.size
(6, 8)

Os elementos em um arranjo são indexados por eixos e o fatiamento também pode ser feito por eixos. Por exemplo,

1a[1,0]
4
1a[0]
array([1, 2, 3])
1a[:,1]
array([2, 5])
1a[:,2:]
array([[3],
[6]])
1a[1,::-1]
array([6, 5, 4])

No caso do arranjo b de três eixos, temos

1b[1,1,0]
-3
1b[0,1]
array([3, 4])
1b[1,0,::-1]
array([-2, -1])

5.3.2 Inicialização

O NumPy conta com várias funções para a inicialização de arrays, algumas das mais usadas são:

  • numpy.zeros inicialização com zeros

    1np.zeros((2,3))
    array([[0., 0., 0.],
    [0., 0., 0.]])
  • numpy.ones inicialização com uns

    1np.ones((2,3,2))
    array([[[1., 1.],
    [1., 1.],
    [1., 1.]],
    [[1., 1.],
    [1., 1.],
    [1., 1.]]])
  • numpy.empty inicialização com valor da memória

    1np.empty((2,1))
    array([[5.73021895e-300],
    [6.95260453e-310]])

Observamos que o tamanho dos eixos é passado por um tuple.

5.3.3 Manipulação

O NumPy contém várias funções para a manipulação de arrays. Algumas das mais usadas são:

  • numpy.reshape reformatação de um arranjo.

    1a = np.array([[1,2,3],[4,5,6]])
    2a.reshape(3,2)
    array([[1, 2],
    [3, 4],
    [5, 6]])
    1a.reshape(-1)
    array([1, 2, 3, 4, 5, 6])
  • numpy.concatenate concatena um tuple de arranjos.

    1a = np.array([1,2,3])
    2b = np.array([4,5,6])
    3np.concatenate((a,b))
    array([1, 2, 3, 4, 5, 6])
    1a = a.reshape(1,-1)
    2b = b.reshape(1,-1)
    3np.concatenate((a,b))
    array([[1, 2, 3],
    [4, 5, 6]])
    1np.concatenate((a,b), axis=1)
    array([[1, 2, 3, 4, 5, 6]])

5.3.4 Operações e funções elementares

De forma análoga a arranjos unidimensionais, as operações aritméticas e funções elementares são aplicadas elemento-a-elementos em um arranjo. Por exemplo,

1a = np.array([[0.,1/6],[1/4,1/3]])
2b = np.array([[0.,6],[4,3]])
3np.sin(np.pi*a*b)
array([[0.0000000e+00, 1.2246468e-16],
[1.2246468e-16, 1.2246468e-16]])

Multiplicação matriz-vetor

Dada uma matriz A=[ai,j]i,j=1n,m e um vetor 𝒙=(xi)i=1m, a multiplicação matriz-vetor A𝒙 é definida por

A𝒙=[a1,1a1,2a1,ma2,1a2,2a2,man,1an,2an,m][x1x2xm] (5.52)
=[a1,1x1+a1,2x2++a1,mxma2,1x1+a2,2x2++a2,mxman,1x1+an,2x2++an,mxm] (5.53)
Exemplo 5.3.1.

Considere a matriz

A=[112213021] (5.54)

e o vetor 𝒙=(1,2,1). A multiplicação matriz-vetor é

A𝒙=[112213021][121] (5.55)
=(1,3,5) (5.56)
1import numpy as np
2
3def MatrizVetor(A, x):
4 n,m = A.shape
5 y = np.empty(n)
6 for i in range(n):
7 y[i] = 0.
8 for j in range(m):
9 y[i] += A[i,j]*x[j]
10 return y
11
12A = np.array([[1, -1, 2],
13 [2, 1, 3],
14 [0, 2, 1]])
15x = np.array([-1, 2, 1])
16print(MatrizVetor(A,x))

Multiplicação matriz-matriz

Dadas matrizes A=[ai,j]i,j=1n,p e B=[bi,j]i,j=1p,m, a multiplicação matriz-matriz AB é a matriz AB=C=[ci,j]i,j=1n,m de elementos

ci,j=k=1pai,kbk,j. (5.57)
Exemplo 5.3.2.

Consideramos as matrizes

A=[112213021] (5.58)
B=[201202] (5.59)

A multiplicação matriz-matriz AB é

AB=[112213021][201202] =[125826] (5.60)
1def MatrizMatriz(A, B):
2 n,p = A.shape
3 m = B.shape[1]
4 C = np.empty((n,m))
5 for i in range(n):
6 for j in range(m):
7 C[i,j] = 0.
8 for k in range(p):
9 C[i,j] += A[i,k]*B[k,j]
10 return C
11
12A = np.array([[1, -1, 2],
13 [2, 1, 3],
14 [0, 2, 1]])
15B = np.array([[2, 0],
16 [1, 2],
17 [0, 2]])
18print(MatrizMatriz(A,B))

5.3.5 Exercícios

E. 5.3.1.

Complete as lacunas.

  1. a)

    A alocação de numpy.array com mais de um eixo pode ser feita usando-se de listas encadeadas.

  2. b)

    A propriedade .shape de um numpy.array é um tuple contendo o tamanho de cada eixo.

  3. c)

    O atributo .size é o número total de objetos de um numpy.array.

  4. d)

    O método numpy.reshape permite a reformatação de um numpy.array.

Resposta 0.

a) encadeadas; b) tuple; c) .size; d) numpy.reshape

E. 5.3.2.

Aloque o arranjo que corresponde a matriz

A=[214032157236] (5.61)

Sem implementar, forneça a saída das seguintes instruções:

  1. a)

    A[2,1]

  2. b)

    A[0,2]

  3. c)

    A[-2,-2]

  4. d)

    A[3]

  5. e)

    A[3:,:]

  6. f)

    A[:,2]

  7. g)

    A[:,1:2]

Resposta 0.

Dica: aloque o arranjo e implemente as instruções.

E. 5.3.3.

Considere o arranjo

1A = np.array([[[-1,2,0],
2 [3,-2,1],
3 [1,-4,2]],
4 [[2,-1,0],
5 [5,-2,0],
6 [2,6,3]],
7 [[1,-1,0],
8 [7,-2,4],
9 [2,-2,1]]])

Sem implementar, forneça a saída das seguintes instruções:

  1. a)

    A[2,0,1]

  2. b)

    A[1,1,0]

  3. c)

    A[2]

  4. d)

    A[1,2]

  5. e)

    A[1:,:2,2]

Resposta 0.

Dica: aloque o arranjo e implemente as instruções.

E. 5.3.4.

Considere o arranjo

1a = np.array([[1,2],[5,8],[2,6]])
2a
array([[1, 2],
[5, 8],
[2, 6]])

Sem implementar, escreva os seguintes arranjos derivados:

  1. a)

    a.reshape(6)

  2. b)

    a.reshape(2,3)

  3. c)

    a.reshape(-1)

  4. d)

    a.reshape(-1,3)

  5. e)

    a.reshape(3,-1)

  6. f)

    a.reshape(4,-1)

Resposta 0.

Dica: aloque o arranjo e implemente as instruções.

E. 5.3.5.

Considere os arranjos

1a = np.array([1,2,3]).reshape(1,-1)
2b = np.array([4,5,6]).reshape(-1,1)

Sem implementar, escreva os seguintes arranjos derivados:

  1. a)

    np.concatenate((a,b.reshape(1,-1)))

  2. b)

    np.concatenate((a.reshape(-1,1),b))

  3. c)

    np.concatenate((a,b.reshape(1,-1)), axis=1)

  4. d)

    np.concatenate((a.reshape(-1,1),b), axis=1)

Resposta 0.

Dica: aloque o arranjo e implemente as instruções.

E. 5.3.6.

Implemente uma função que recebe uma matriz (representada por um array) e retorna a sua transposta. Teste seu código para diversas matrizes com diversos formatos.

Resposta 0.
1import numpy as np
2
3def Transposta(A):
4 n,m = A.shape
5 B = np.empty((m,n))
6 for i in range(n):
7 for j in range(m):
8 B[j,i] = A[i,j]
9 return B
E. 5.3.7.

Implemente uma função que compute a multiplicação vetor-matriz

𝒚=𝒙A (5.62)
:=[x1x2xn][a1,1a1,2a1,ma2,1a2,2a2,man,1an,2an,m] (5.63)

onde, por definição, 𝒚=[yj]j=1m, com elementos

yj=k=1nxkak,j. (5.64)
Resposta 0.

Dica: a função numpy.dot também computa a multiplicação vetor-matriz. Teste sua implementação para diferentes matriz e vetores de diferentes tamanhos.


Envie seu comentário

Aproveito para agradecer a todas/os que de forma assídua ou esporádica contribuem enviando correções, sugestões e críticas!

Opcional. Preencha seu nome para que eu possa lhe contatar.
Opcional. Preencha seu e-mail para que eu possa lhe contatar.
As informações preenchidas são enviadas por e-mail para o desenvolvedor do site e tratadas de forma privada. Consulte a política de uso de dados para mais informações.

Licença Creative Commons
Este texto é disponibilizado nos termos da Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional. Ícones e elementos gráficos podem estar sujeitos a condições adicionais.

Algoritmos e Programação I

Compre o e-book deste material aqui! Consulte outras formas de colaborar.

5.3 Arranjos multidimensionais

Um arranjo numpy.array é um tabelamento de elementos de um mesmo tipo. Os elementos são organizados por eixos indexados (em inglês, axes). Enquanto que nas seções anteriores nos restringimos a arrays unidimensionais (de apenas um eixo), aqui, vamos estudar a alocação e manipulação de arranjos de vários eixos.

5.3.1 Alocação, indexação e fatiamento

A alocação de um numpy.array com mais de um eixo pode ser feita usando-se de listas encadeadas. Por exemplo,

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

cria o arranjo a de dois eixos, enquanto

1b = np.array([[[1,2],[3,4]],[[-1,-2],[-3,-4]]])
2b
array([[[ 1, 2],
[ 3, 4]],
[[-1, -2],
[-3, -4]]])

cria o arranjo b de três eixos. Para fazer um paralelo com a matemática, o arranjo a é similar (mas, não equivalente) a matriz A=[ai,j]i,j=12,3

A=[123456], (5.51)

e o arranjo b é similar (mas, não equivalente) ao tensor B=[bi,j,k]i,j,k=12,2,2.

A propriedade .shape é um tuple contendo o tamanho de cada eixo. Por exemplo,

1a.shape
(2, 3)
1a.shape[0]
2

informa que a tem dois eixos, o primeiro com tamanho 2 e o segundo com tamanho 3. Um paralelo com matrizes, dizemos que a tem duas linhas e três colunas. No caso do arranjo b, temos

1b.shape
(2, 2, 2)
1b.shape[2]
2

o que nos informa tratar-se de um array de três eixos, cada um com tamanho 2.

O número total de elementos de um array pode ser obtido do atributo numpy.ndarray.size. Por exemplo,

1a.size, b.size
(6, 8)

Os elementos em um arranjo são indexados por eixos e o fatiamento também pode ser feito por eixos. Por exemplo,

1a[1,0]
4
1a[0]
array([1, 2, 3])
1a[:,1]
array([2, 5])
1a[:,2:]
array([[3],
[6]])
1a[1,::-1]
array([6, 5, 4])

No caso do arranjo b de três eixos, temos

1b[1,1,0]
-3
1b[0,1]
array([3, 4])
1b[1,0,::-1]
array([-2, -1])

5.3.2 Inicialização

O NumPy conta com várias funções para a inicialização de arrays, algumas das mais usadas são:

  • numpy.zeros inicialização com zeros

    1np.zeros((2,3))
    array([[0., 0., 0.],
    [0., 0., 0.]])
  • numpy.ones inicialização com uns

    1np.ones((2,3,2))
    array([[[1., 1.],
    [1., 1.],
    [1., 1.]],
    [[1., 1.],
    [1., 1.],
    [1., 1.]]])
  • numpy.empty inicialização com valor da memória

    1np.empty((2,1))
    array([[5.73021895e-300],
    [6.95260453e-310]])

Observamos que o tamanho dos eixos é passado por um tuple.

5.3.3 Manipulação

O NumPy contém várias funções para a manipulação de arrays. Algumas das mais usadas são:

  • numpy.reshape reformatação de um arranjo.

    1a = np.array([[1,2,3],[4,5,6]])
    2a.reshape(3,2)
    array([[1, 2],
    [3, 4],
    [5, 6]])
    1a.reshape(-1)
    array([1, 2, 3, 4, 5, 6])
  • numpy.concatenate concatena um tuple de arranjos.

    1a = np.array([1,2,3])
    2b = np.array([4,5,6])
    3np.concatenate((a,b))
    array([1, 2, 3, 4, 5, 6])
    1a = a.reshape(1,-1)
    2b = b.reshape(1,-1)
    3np.concatenate((a,b))
    array([[1, 2, 3],
    [4, 5, 6]])
    1np.concatenate((a,b), axis=1)
    array([[1, 2, 3, 4, 5, 6]])

5.3.4 Operações e funções elementares

De forma análoga a arranjos unidimensionais, as operações aritméticas e funções elementares são aplicadas elemento-a-elementos em um arranjo. Por exemplo,

1a = np.array([[0.,1/6],[1/4,1/3]])
2b = np.array([[0.,6],[4,3]])
3np.sin(np.pi*a*b)
array([[0.0000000e+00, 1.2246468e-16],
[1.2246468e-16, 1.2246468e-16]])

Multiplicação matriz-vetor

Dada uma matriz A=[ai,j]i,j=1n,m e um vetor 𝒙=(xi)i=1m, a multiplicação matriz-vetor A𝒙 é definida por

A𝒙=[a1,1a1,2a1,ma2,1a2,2a2,man,1an,2an,m][x1x2xm] (5.52)
=[a1,1x1+a1,2x2++a1,mxma2,1x1+a2,2x2++a2,mxman,1x1+an,2x2++an,mxm] (5.53)
Exemplo 5.3.1.

Considere a matriz

A=[112213021] (5.54)

e o vetor 𝒙=(1,2,1). A multiplicação matriz-vetor é

A𝒙=[112213021][121] (5.55)
=(1,3,5) (5.56)
1import numpy as np
2
3def MatrizVetor(A, x):
4 n,m = A.shape
5 y = np.empty(n)
6 for i in range(n):
7 y[i] = 0.
8 for j in range(m):
9 y[i] += A[i,j]*x[j]
10 return y
11
12A = np.array([[1, -1, 2],
13 [2, 1, 3],
14 [0, 2, 1]])
15x = np.array([-1, 2, 1])
16print(MatrizVetor(A,x))

Multiplicação matriz-matriz

Dadas matrizes A=[ai,j]i,j=1n,p e B=[bi,j]i,j=1p,m, a multiplicação matriz-matriz AB é a matriz AB=C=[ci,j]i,j=1n,m de elementos

ci,j=k=1pai,kbk,j. (5.57)
Exemplo 5.3.2.

Consideramos as matrizes

A=[112213021] (5.58)
B=[201202] (5.59)

A multiplicação matriz-matriz AB é

AB=[112213021][201202] =[125826] (5.60)
1def MatrizMatriz(A, B):
2 n,p = A.shape
3 m = B.shape[1]
4 C = np.empty((n,m))
5 for i in range(n):
6 for j in range(m):
7 C[i,j] = 0.
8 for k in range(p):
9 C[i,j] += A[i,k]*B[k,j]
10 return C
11
12A = np.array([[1, -1, 2],
13 [2, 1, 3],
14 [0, 2, 1]])
15B = np.array([[2, 0],
16 [1, 2],
17 [0, 2]])
18print(MatrizMatriz(A,B))

5.3.5 Exercícios

E. 5.3.1.

Complete as lacunas.

  1. a)

    A alocação de numpy.array com mais de um eixo pode ser feita usando-se de listas encadeadas.

  2. b)

    A propriedade .shape de um numpy.array é um tuple contendo o tamanho de cada eixo.

  3. c)

    O atributo .size é o número total de objetos de um numpy.array.

  4. d)

    O método numpy.reshape permite a reformatação de um numpy.array.

Resposta 0.

a) encadeadas; b) tuple; c) .size; d) numpy.reshape

E. 5.3.2.

Aloque o arranjo que corresponde a matriz

A=[214032157236] (5.61)

Sem implementar, forneça a saída das seguintes instruções:

  1. a)

    A[2,1]

  2. b)

    A[0,2]

  3. c)

    A[-2,-2]

  4. d)

    A[3]

  5. e)

    A[3:,:]

  6. f)

    A[:,2]

  7. g)

    A[:,1:2]

Resposta 0.

Dica: aloque o arranjo e implemente as instruções.

E. 5.3.3.

Considere o arranjo

1A = np.array([[[-1,2,0],
2 [3,-2,1],
3 [1,-4,2]],
4 [[2,-1,0],
5 [5,-2,0],
6 [2,6,3]],
7 [[1,-1,0],
8 [7,-2,4],
9 [2,-2,1]]])

Sem implementar, forneça a saída das seguintes instruções:

  1. a)

    A[2,0,1]

  2. b)

    A[1,1,0]

  3. c)

    A[2]

  4. d)

    A[1,2]

  5. e)

    A[1:,:2,2]

Resposta 0.

Dica: aloque o arranjo e implemente as instruções.

E. 5.3.4.

Considere o arranjo

1a = np.array([[1,2],[5,8],[2,6]])
2a
array([[1, 2],
[5, 8],
[2, 6]])

Sem implementar, escreva os seguintes arranjos derivados:

  1. a)

    a.reshape(6)

  2. b)

    a.reshape(2,3)

  3. c)

    a.reshape(-1)

  4. d)

    a.reshape(-1,3)

  5. e)

    a.reshape(3,-1)

  6. f)

    a.reshape(4,-1)

Resposta 0.

Dica: aloque o arranjo e implemente as instruções.

E. 5.3.5.

Considere os arranjos

1a = np.array([1,2,3]).reshape(1,-1)
2b = np.array([4,5,6]).reshape(-1,1)

Sem implementar, escreva os seguintes arranjos derivados:

  1. a)

    np.concatenate((a,b.reshape(1,-1)))

  2. b)

    np.concatenate((a.reshape(-1,1),b))

  3. c)

    np.concatenate((a,b.reshape(1,-1)), axis=1)

  4. d)

    np.concatenate((a.reshape(-1,1),b), axis=1)

Resposta 0.

Dica: aloque o arranjo e implemente as instruções.

E. 5.3.6.

Implemente uma função que recebe uma matriz (representada por um array) e retorna a sua transposta. Teste seu código para diversas matrizes com diversos formatos.

Resposta 0.
1import numpy as np
2
3def Transposta(A):
4 n,m = A.shape
5 B = np.empty((m,n))
6 for i in range(n):
7 for j in range(m):
8 B[j,i] = A[i,j]
9 return B
E. 5.3.7.

Implemente uma função que compute a multiplicação vetor-matriz

𝒚=𝒙A (5.62)
:=[x1x2xn][a1,1a1,2a1,ma2,1a2,2a2,man,1an,2an,m] (5.63)

onde, por definição, 𝒚=[yj]j=1m, com elementos

yj=k=1nxkak,j. (5.64)
Resposta 0.

Dica: a função numpy.dot também computa a multiplicação vetor-matriz. Teste sua implementação para diferentes matriz e vetores de diferentes tamanhos.


Envie seu comentário

Aproveito para agradecer a todas/os que de forma assídua ou esporádica contribuem enviando correções, sugestões e críticas!

Opcional. Preencha seu nome para que eu possa lhe contatar.
Opcional. Preencha seu e-mail para que eu possa lhe contatar.
As informações preenchidas são enviadas por e-mail para o desenvolvedor do site e tratadas de forma privada. Consulte a política de uso de dados para mais informações.

Licença Creative Commons
Este texto é disponibilizado nos termos da Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional. Ícones e elementos gráficos podem estar sujeitos a condições adicionais.

Pedro H A Konzen
| | | |