5. Vetores

5.1. Criação de vetores

Em economia fazemos uso recorrente de matrizes e vetores. Em Python, precisamos de um pacote para isso.

Pacotes são conjuntos ou bibliotecas de código utilizados para um fim específico.

Para vetores, matrizes e suas operações, vamos utilizar o pacote Numpy (Numerical Python).

Na Plataforma Anaconda esse pacote já está previamente instalado (o mesmo vale para o Google Colab). Porém, se você estiver utilizando outra inferface, poderá instalar o Numpy, na janela de comando, utilizando:

pip install numpy

Mesmo com Numpy instalado, você irá precisar sempre importar o pacote antes de usá-lo.

É comum utilizar uma abreviação do nome do pacote na importação, o que irá facilitar seu uso no restante do código. No caso do Numpy, vamos usar np, que é uma abreviação utilizada recorrentemente, por convenção (você pode escolher qualquer letra). Como é uma convenção muito utilizada, manter np permite que outras pessoas entendam melhor o seu código e facilita o uso de códigos prontos.

Para importar o Numpy como np utilize:

[1]:
import numpy as np

Agora sim, você pode criar um vetor.

Vamos criar o vetor x com os elementos [1, 5, 6] com auxílio da função array. Observe que array é uma função do pacote Numpy, sendo assim, sempre utilizaremos np.array para chamar essa função:

[2]:
x = np.array([1, 5, 6])

O vetor fica disponível apenas com o nome x:

[3]:
x
[3]:
array([1, 5, 6])

Ou, você pode utilizar a função print() para visualizar o conteúdo da variável:

[4]:
print(x)
[1 5 6]

Vale observar que os vetores não precisam ser numéricos!

Por exemplo, podemos criar o vetor y apenas com texto:

[5]:
y = np.array(["NEDUR", "UFPR", "Regional", "Urbana"])
print(y)
['NEDUR' 'UFPR' 'Regional' 'Urbana']

Observe que ao utilizar a função type() para verificar o tipo de variável, você terá como resposta numpy.ndarray (abreviação para numpy N-dimensional array) para ambos os vetores:

[6]:
print(type(x))
print(type(y))
<class 'numpy.ndarray'>
<class 'numpy.ndarray'>

Para sabermos o tipo dentro de um objeto do Numpy, podemos utilizar o atributo dtype do vetor.

Atributos são informações ou características relacionadas à determinada função, dtype (abreviatura de data type) é um atributo de um array.

[7]:
print(x.dtype)
print(y.dtype)
int32
<U8

A saída nos indica que temos um vetor com inteiros (int) e 32 caracteres para a variável x, enquanto y é vetor de texto Unicode String (U), com 11 caracteres. Esses tamanhos podem ser diferentes se você estiver utilizando outro ambiente que não seja o Jupyter Notebook.

Observação:

A informação <U8’, indica que o vetor está salvo no formato Unicode (Universal Character Encoding) com até 8 caracteres. O formato Unicode é um padrão de representação para texto universal.

Não vamos detalhar todas as combinações possíveis aqui, elas estão disponíveis na documentação do Numpy

Vetores lógicos (booleanos) também podem ser criados no Numpy:

[8]:
v = np.array([True, False, True])
print(v)
v.dtype
[ True False  True]
[8]:
dtype('bool')

Diferente das listas, que podem conter qualquer tipo de dado ao mesmo tempo, um vetor pode ter apenas um tipo de dado.

Se tentarmos colocar números e letras no mesmo vetor, todos os elementos serão convertidos para letras:

[9]:
z = np.array(["NEDUR", "UFPR", "Regional", "Urbana", 1])
print(z)
z.dtype
['NEDUR' 'UFPR' 'Regional' 'Urbana' '1']
[9]:
dtype('<U11')

Podemos criar uma vetor com uma sequência de números.

Um vetor de 0 a 4, por exemplo, pode ser criado com auxílio da função numpy arange:

[10]:
r = np.arange(5)
print(r)
[0 1 2 3 4]

Observe que ao informar que queremos um array com uma sequência até 5, o vetor começa em zero e possui cinco elementos.

No exemplo anterior usamos np.arrange(5), em que o número 5 é chamado de argumento da função, e se refere ao valor final da sequência de números criada. A função np.arange possui vários argumentos, ou seja, vários outros parâmetros que podem ser alterados para formar sequências diferentes, como valor inicial, intervalos, entre outros.

Para conhecer os argumentos da função, use a função help():

[11]:
help(np.arange)
Help on built-in function arange in module numpy:

arange(...)
    arange([start,] stop[, step,], dtype=None, *, like=None)

    Return evenly spaced values within a given interval.

    Values are generated within the half-open interval ``[start, stop)``
    (in other words, the interval including `start` but excluding `stop`).
    For integer arguments the function is equivalent to the Python built-in
    `range` function, but returns an ndarray rather than a list.

    When using a non-integer step, such as 0.1, the results will often not
    be consistent.  It is better to use `numpy.linspace` for these cases.

    Parameters
    ----------
    start : integer or real, optional
        Start of interval.  The interval includes this value.  The default
        start value is 0.
    stop : integer or real
        End of interval.  The interval does not include this value, except
        in some cases where `step` is not an integer and floating point
        round-off affects the length of `out`.
    step : integer or real, optional
        Spacing between values.  For any output `out`, this is the distance
        between two adjacent values, ``out[i+1] - out[i]``.  The default
        step size is 1.  If `step` is specified as a position argument,
        `start` must also be given.
    dtype : dtype
        The type of the output array.  If `dtype` is not given, infer the data
        type from the other input arguments.
    like : array_like
        Reference object to allow the creation of arrays which are not
        NumPy arrays. If an array-like passed in as ``like`` supports
        the ``__array_function__`` protocol, the result will be defined
        by it. In this case, it ensures the creation of an array object
        compatible with that passed in via this argument.

        .. versionadded:: 1.20.0

    Returns
    -------
    arange : ndarray
        Array of evenly spaced values.

        For floating point arguments, the length of the result is
        ``ceil((stop - start)/step)``.  Because of floating point overflow,
        this rule may result in the last element of `out` being greater
        than `stop`.

    See Also
    --------
    numpy.linspace : Evenly spaced numbers with careful handling of endpoints.
    numpy.ogrid: Arrays of evenly spaced numbers in N-dimensions.
    numpy.mgrid: Grid-shaped arrays of evenly spaced numbers in N-dimensions.

    Examples
    --------
    >>> np.arange(3)
    array([0, 1, 2])
    >>> np.arange(3.0)
    array([ 0.,  1.,  2.])
    >>> np.arange(3,7)
    array([3, 4, 5, 6])
    >>> np.arange(3,7,2)
    array([3, 5])

Observe que os dois primeiros argumentos da função são início (start) e fim (stop). Assim, para criar um vetor começando em 1, e terminando em 5, podemos utilizar:

[12]:
r1 = np.arange(1, 6)
print(r1)
[1 2 3 4 5]

Observe que a sequência agora começa em 1 (incluso), e “termina” em 6 (não incluso)! O último número do intervalo não será incluído.

Podemos ainda definir intervalos (argumento step). Por exemplo, criar uma sequência de 0.5 em 0.5, começando em 2 e terminando em 4. Para isso, podemos utilizar os três primeiros argumentos da função: número inicial (incluso), número final (não incluso) e intervalo.

Observe que, para incluir o valor 4 e não incluir 4.5, o segundo argumento (stop) deve estar entre 4 e 4.5. Optamos por deixar 4.5.

[13]:
q = np.arange(2,4.5,0.5)
print(q)
[2.  2.5 3.  3.5 4. ]

Você pode mudar os parâmetros dos argumentos dentro da função. Teste os três próximos exemplos e observe os resultados:

[14]:
np.arange(1, 10, 2)
[14]:
array([1, 3, 5, 7, 9])
[15]:
np.arange(1, 11)
[15]:
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
[16]:
np.arange(1, 9, 3.141593)
[16]:
array([1.      , 4.141593, 7.283186])

Além dos exemplos acima, podemos criar sequências regulares dentro de um intervalo. Nesse caso, precisamos usar a função linspace.

Vamos usar os quadro primeiros argumentos da função: Início, Fim, Número de intervalos, e inclusão ou não do ponto final (endpoint).

Teste as opções abaixo e observe os resultados:

[17]:
np.linspace(0, 1, num=2, endpoint=False)
[17]:
array([0. , 0.5])
[18]:
np.linspace(0, 1, num=2, endpoint=True)
[18]:
array([0., 1.])
[19]:
np.linspace(0, 1, num=3, endpoint=True)
[19]:
array([0. , 0.5, 1. ])
[20]:
np.linspace(0, 1, num=4, endpoint=True)
[20]:
array([0.        , 0.33333333, 0.66666667, 1.        ])
[21]:
np.linspace(0, 1, num=5, endpoint=True)
[21]:
array([0.  , 0.25, 0.5 , 0.75, 1.  ])

Alguns tipos de vetores são necessários em alguns cálculos. Você pode utilizar outras funções para criar um vetor de zeros (np.zeros), ou um vetor apenas com o número 1 (np.ones):

[22]:
np.zeros(5)
[22]:
array([0., 0., 0., 0., 0.])
[23]:
np.ones(5)
[23]:
array([1., 1., 1., 1., 1.])

Podemos verificar todas as variáveis criadas com o comando %whos:

[24]:
%whos
Variable   Type       Data/Info
-------------------------------
np         module     <module 'numpy' from 'C:\<...>ges\\numpy\\__init__.py'>
q          ndarray    5: 5 elems, type `float64`, 40 bytes
r          ndarray    5: 5 elems, type `int32`, 20 bytes
r1         ndarray    5: 5 elems, type `int32`, 20 bytes
v          ndarray    3: 3 elems, type `bool`, 3 bytes
x          ndarray    3: 3 elems, type `int32`, 12 bytes
y          ndarray    4: 4 elems, type `<U8`, 128 bytes
z          ndarray    5: 5 elems, type `<U11`, 220 bytes

Observe que para as funções linespace(), zeros(), e ones() não salvamos variáveis, e, por isso, elas não estão disponíveis no ambiente.

5.2. Indexação e subconjuntos de vetores

Após a criação de vetores, é possível selecionar um elemento específico (ou elementos) considerando a posição ou valor.

Crie um vetor g com os elementos [“Curso”, “Python”, “NEDUR”, 2022]:

[25]:
g = np.array(["Curso", "Python", "NEDUR", 2022, "Agosto"])

Observe que, nesse caso, todos os elementos do vetor serão salvos como strings (texto).

Em Python, a primeira posição, de uma lista, ou de um vetor, é a posição zero. Sendo assim, considerando o vetor g, podemos verificar o terceiro elemento (localizado na posição 2) com a seguinte notação:

[26]:
g[2]
[26]:
'NEDUR'

Podemos também utilizar os índices começando do final do vetor. Por exemplo, “NEDUR” está na posição 2, ou -2:

[27]:
g[-2]
[27]:
'2022'

Similarmente, podemos verificar os elementos contidos entre as posições 1 e 3, ou, dito de outro forma, selecionar o subconjunto de elementos entre as posições 1 e 3:

[28]:
g[1:4]
[28]:
array(['Python', 'NEDUR', '2022'], dtype='<U11')

Novamente, repare que o último elemento (posição 4), não foi incluído, assim como, não foi incluído o elemento de índice zero.

Podemos também, criar um novo vetor com uma seleção do anterior, atribuindo um novo nome para a variável, nesse caso n:

[29]:
n = g[1:4]
n
[29]:
array(['Python', 'NEDUR', '2022'], dtype='<U11')

No caso de vetores numéricos, podemos selecionar utilizando operadores.

Por exemplo, vamos recuperar o vetor de 0 a 100, com múltiplos de 9:

[30]:
m = np.arange(0, 100, 9)
m
[30]:
array([ 0,  9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99])

Se quisermos selecionar apenas os elementos maiores do que 20 poderíamos tentar o código:

[31]:
m > 20
[31]:
array([False, False, False,  True,  True,  True,  True,  True,  True,
        True,  True,  True])

No entando, o resultado mostra que os primeiros três números não são menores do que 20, mas não seleciona o que queremos.

Para que o comando seja compreendido, precisamos informar que queremos m > 20 dentro do vetor m. Ou seja:

[32]:
m[m > 20]
[32]:
array([27, 36, 45, 54, 63, 72, 81, 90, 99])

5.3. Operações com vetores

Assim como foi feito com as variáveis, é possível realizar operações aritméticas e lógicas com os vetores. Para tal, defina um vetor k com os seguintes elementos [2, 4, 6, 8, 10]:

[33]:
k = np.arange(2, 11, 2)
k
[33]:
array([ 2,  4,  6,  8, 10])

Multiplicar o vetor k por 2 significa multiplicar cada um dos seus elementos por 2:

[34]:
k * 2
[34]:
array([ 4,  8, 12, 16, 20])

Similarmente, dividir o vetor k por 2 significa dividir cada um dos seus elementos por 2:

[35]:
k / 2
[35]:
array([1., 2., 3., 4., 5.])

Faça o teste com K + 1 e K - 1:

[36]:
k + 1
[36]:
array([ 3,  5,  7,  9, 11])
[37]:
k - 1
[37]:
array([1, 3, 5, 7, 9])

Além das operações acima, podemos realizar operações com mais de um vetor, como somar dois vetores. Para tal, defina um vetor s conforme abaixo:

[38]:
s = np.array([1, 2, 3, 4, 5])

Em seguida, crie um novo vetor b que seja dado pela soma de k e s. Observe que o resultado será a soma elemento a elemento dos dois vetores.

[39]:
b = k + s
b
[39]:
array([ 3,  6,  9, 12, 15])

Além das operações aritméticas, operações lógicas também podem ser realizadas com os vetores. Considerando o vetor b criado acima, podemos verificar quais elementos são maiores ou iguais a 9 com:

[40]:
b >= 9
[40]:
array([False, False,  True,  True,  True])

Repare que o resultado encontrado foi True (verdadeiro) para os elementos maiores ou iguais a 9 e False (falso) caso contrário. Ou seja, a operação reporta um resultado lógico.

Como anteriormente, se o interesse for reportar os valores maiores ou iguais a 9, podemos utilizar a operação abaixo:

[41]:
b[b >= 9]
[41]:
array([ 9, 12, 15])

Se o interesse for encontrar a posição desses valores maiores ou iguais a 9, você pode utilizar a função np.where(). Nesse caso, o resultado será “3 4 5”, ou seja, os elementos maiores ou iguais a 9 são aqueles nas posições 3, 4 e 5.

[42]:
np.where(b >= 9)
[42]:
(array([2, 3, 4], dtype=int64),)

5.4. Funções com vetores

Diversas funções matemáticas e estatísticas podem ser aplicadas aos vetores numéricos, como soma, média, valor máximo, mínimo, quantis, entre outras.

A tabela abaixo apresenta algumas dessas funções:

Função

Descrição

np.sum()

Retorna a soma do vetor

np.min()

Retorna o valor mínimo do vetor

np.max()

Retorna o valor máximo do vetor

np.mean()

Retorna a média do vetor

np.median()

Retorna a mediana do vetor

np.var()

Retorna a variância do vetor

np.std()

Retorna o desvio padrão do vetor

Para praticar alguns desses operadores vamos utilizar o vetor k definido anteriomente:

[43]:
k
[43]:
array([ 2,  4,  6,  8, 10])
[44]:
np.sum(k)
[44]:
30
[45]:
np.min(k)
[45]:
2
[46]:
np.max(k)
[46]:
10
[47]:
np.mean(k)
[47]:
6.0
[48]:
np.median(k)
[48]:
6.0
[49]:
np.var(k)
[49]:
8.0
[50]:
np.std(k)
[50]:
2.8284271247461903

Essas mesmas funções e outras podem ser utilizadas tanto para vetores quanto para matrizes, que serão o tema do próximo tópico.