Não podemos fazer muita ciência de dados apenas com o NumPy. Mas ele fornece a base para todas as bibliotecas ou módulos de alto nível para ciência de dados. É essencial para o manejo eficiente dos arrays e álgebra linear.
Para usar o NumPy, nós, é claro, temos de importar primeiro o respectivo módulo.import numpy as np
Como podemos ver, estamos definindo também um alias (apelido) aqui, desse modo podemos endereçar ao NumPy escrevendo apenas np.
Para criar um array NumPy, usamos apenas a respectiva função array( ) e passamos uma lista para ela.
a = np.array([10, 20, 30]) b = np.array([1, 57, 4, 9])
Agora podemos acessar os valores da mesma maneira que faríamos com uma lista.
print(a[0]) print(b[2])
Os arrays que criamos são arrays unidimensionais. Com NumPy, podemos criar grandes arrays multi-dimensionais que têm a mesma estrutura de uma matriz
a = np.array([
[10, 20, 30],
[40, 50, 60]
])
print(a)
Aqui, passamos duas listas dentro de uma lista como parâmetros. Isto cria uma matriz 2x3. quando imprimirmos o array, temos o seguinte resultado:
[[10 20 30]
[40 50 60]]
Desde que agora temos duas dimensões, precisamos também endereçar dois índices, para acessar um elemento específico.
print(a[1][2])
Neste caso, endereçamos a segunda linha (índice 1) e o terceiro elemento ou coluna (índice 2). Portanto, nosso resultado é 60.
Podemos estender este princípio tanto quanto quisermos. Por exemplo, vamos criar um array muito maior.
Aqui temos uma matriz 3x3x4 e lentamente, mas com certeza, torna-se um pouco irritante e não podemos realmente entender a estrutura do array. Este é especialmente o caso quando entramos na quarta ou mais dimensões, pois somente percebemos três dimensões na nossa vida diária.
Podemos imaginar este array tridimensional como um cubo. Temos três linhas, quatro colunas e três páginas ou camadas. Tais visualizações falham em dimensões superiores.
Outra coisa útil a mencionar é o parâmetro dtype. Significa tipo de dados e nos permite especificar quais tipos de dados nossos valores são. Neste caso especificamos float e daí nossos valores foram armazenados como números de pontos flutuantes com notação respectiva.
Em vez de preencher manualmente nossos arrays com valores, podemos também usar funções pré-definidas em certos casos. A única coisa que precisamos especificar é a função desejada e a forma do array.
Usando a função full, por exemplo, podemos preencher um array com uma certa forma e com o mesmo número. Neste caso criamos uma matriz 3x5x4, que é preenchida com o número 7.
Para os casos que queremos arrays preenchidos com 0 e 1, nós também temos funções específicas: zeros( ) e ones( ):
Aqui criamos um array 3x3 preenchido com 0 e um array quadrimensional preenchido com 1.
Outras opções serão para criar um array vazio ou um que seja preenchido com números aleatórios. Para tanto, usamos as respectivas funções do NumPy mais uma vez, a empty( ) e a random.randon( ):
A função empty cria um array sem os valores iniciais por completo (aqui foi preenchida com um número muitíssimo pequeno). Isto a torna um pouco mais rápida, mas também perigosa de usar, pois o usuário precisa inicializar manualmente todos os valores.
Quando se usa a função random, certifique-se que você está se referindo ao módulo np.random. Você precisa escrevê-lo duas vezes porque caso contrário você está chamando a biblioteca e não apenas a função.
Em vez de apenas preencher arrays com os mesmos valores, podemos preencher criando sequências de valores, especificando os limites. Para isso, podemos usar duas diferentes funções, chamadas arange( ) e linspace( ).
A função arange( ) cria uma lista de valores que vão de um mínimo a um máximo. O tamanho do passo tem de ser especificado nos parâmetros.
No exemplo acima, criamos uma contagem de 10 a 45 adicionando sempre 5.
Usando o linspace( ) podemos também criar uma lista de um mínimo a um máximo. Mas, ao invés de especificar o tamanho do passo, especificamos a quantia de valores que queremos ter na nossa lista. Todos eles serão distribuídos uniformemente e terão a mesma distância de seus vizinhos.
Aqui, criamos uma lista que varia de 0 a 100 e contém 11 elementos. Isto se ajusta suavemente com a diferença de 10 entre todos números.
É claro, se escolhermos parâmetros diferentes, os números não serão essa “beleza”.
Existe um valor especial no NumPy que representa valores que não são números. É o chamado NaN e significa Not a Number. Basicamente usamos ele como marcador de posição para espaços vazios. Ele pode ser visto como um valor que indica que algo está faltando naquele lugar.
Quando importamos pacotes de bigdata para dentro de nossa aplicação, muitas vezes existirão perdas de dados. Em vez disso apenas definimos estes valores para zero, ou algo ainda, podemos defini-los a NaN e depois filtrá-los como dados fora do dataset.
Arrays NumPy têm certos atributos que podemos acessá-los e que fornece informação sobre a estrutura dele.
ATRIBUTOS DO ARRAY NUMPY |
|
---|---|
ATRIBUTO |
DESCRIÇÃO |
a.shape | Retorna a forma do array, p. ex., (3,3) ou (3,4,7) |
a.ndim | Retorna quantas dimensões tem o nosso array |
a.size | Retorna a quantidade de elementos que tem o array |
a.dtype | Retorna o tipo de dado dos valores no array |
Agora que sabemos como criar um array e quais atributos ele tem, vamos dar uma olhada em como trabalhar com arrays. Para isso, começaremos com operações matemáticas básicas.
Outro Exemplo:
Quando realizamos operações aritméticas básicas como adição, subtração, multiplicação e divisão de uma array por um escalar, podemos aplicar a operação em cada um dos elementos do array.
Como você pode ver, quando multiplicamos o array por dois, multiplicamos cada valor único nele por dois. Isto é o caso para adição, subtração e divisão. Mas, o que acontece quando aplicamos estas operações entre dois arrays?
A fim de aplicar estas operações entre dois arrays, precisamos tomar cuidado com a forma. Eles não precisam ser os mesmos, mas deve haver uma maneira razoável de realizar as operações. Aplicamos então, novamente as operações em cada elemento do array.
Por exemplo, observe a e b. Eles têm diferentes formas, mas quando adicionamos os dois, eles compartilham no mínimo as quantidades de colunas.
Como eles se igualam em colunas, podemos dizer que adicionamos as colunas individuais, mesmo que a quantidade de linhas sejam diferentes.
O mesmo também pode ser feito com a e c onde as linhas se igualam e as colunas diferem.
E, é claro, ele também funciona, quando as formas se igualam exatamente. O único problema é quando as formas diferirem muito e não existir maneira razoável de realizar as operações. Nestes casos, obtemos um ValueErrors.
Outra coisa que o módulo NumPy oferece são as funções matemáticas que podemos aplicar a cada valor num array.
FUNÇÕES MATEMÁTICAS ARRAY NUMPY |
|
---|---|
FUNÇÃO |
DESCRIÇÃO |
np.sin(a) | Retorna o seno de cada valor |
np.cos(a) | Retorna o cosseno de cada valor |
np.tan(a) | Retorna a tangente de cada valor |
np.log(a) | Retorna o logaritmo de cada valor |
np.sqrt(a) | Retorna a raiz quadrada de cada valor |
Agora vamos entrar na estatística. O NumPy nos oferece algo assim chamado de funções agregadas que podemos usar para obter uma estatística chave de todos os valores.
FUNÇÕES AGREGADAS NUMPY |
|
---|---|
FUNÇÃO |
DESCRIÇÃO |
a.sum( ) | Retorna a soma de todos os valores no array |
a.min( ) | Retorna o valor mais baixo do array |
a.max( ) | Retorna o valor mais alto do array |
a.mean( ) | Retorna a média aritmética de todos os valores no array |
np.median() | Retorna o valor da mediana do array |
np.std( ) | Retorna o desvio padrão dos valores no array |
O NumPy nos oferece numerosas maneiras que podemos manipular os dados dos nossos arrays. Aqui vamos dar uma olhada rápida nas funções e categorias de funções mais importantes.
Se você quiser apenas mudar, no entanto um único valor, você pode apenas usar a indexação básica de listas.
Um dos mais importantes e úteis tipos de funções são as funções de manipulação de forma. Estas permitem-nos reestruturar nossos arrays sem mudar seus valores.
FUNÇÕES MANIPULAÇÃO DE FORMA |
|
---|---|
FUNÇÃO |
DESCRIÇÃO |
a.reshape(x,y) | Retorna um array com os mesmos valores estruturados numa forma diferente |
a.flatten( ) | Retorna uma cópia unidimensional achatada do array |
a.ravel( ) | Faz o mesmo que a flatten, mas funciona com o array real ao invés de uma cópia |
a.transpose( ) | Retorna um array com os mesmos valores, mas com as dimensões trocadas |
np.swapaxes() | Retorna um array com os mesmos valores, mas dois eixos trocados |
np.flat | Não é uma função, mas um iterador para versões achatadas do array |
Existe mais de um elemento que está relacionado à forma, mas não é uma função. Ele é chamado flat e ele é um iterador para a versão unidimensional achatada do array. Flat não é chamável mas podemos iterar com ele em laços for ou índice.
Usamos as funções de união quando combinamos múltiplos arrays num novo array.
FUNÇÕES DE UNIÃO |
|
---|---|
FUNÇÃO |
DESCRIÇÃO |
a.concatenate(a,b) | Junta múltiplos arrays ao longo de um eixo existente |
a.stack(a, b) | Junta múltiplos arrays ao longo de um novo eixo |
a.hstack(a, b) | Empilha os arrays horizontalmente (em colunas) |
a.vstack(a, b) | Empilha os arrays verticalmente (em linhas) |
No que segue, você pode ver a diferença entre concatenar e empilhar:
O que a função concatenate( ) faz é, ela junta os arrays apenas anexando um no outro. A função stack( ), por outro lado, cria um eixo adicional que separa os dois arrays iniciais.
Nós não somente juntamos e combinamos arrays mas também separamos eles novamente. Isto é feito usando a função split( ) para separar os arrays em múltiplos sub arrays.
FUNÇÕES SPLITTING |
|
---|---|
FUNÇÃO |
DESCRIÇÃO |
np.split(a, x) | Separa um array em múltiplos arrays |
np.hsplit(a, x) | Separa um array em múltiplos arrays horizontalmente (em colunas) |
a.vstack(a, x) | Separa um array em múltiplos arrays verticalmente (em linhas) |
Quando separamos uma lista com a função split, precisamos especificar em quantas seções queremos separar nosso array.
As últimas funções de manipulação que iremos observar são aquelas que permitem-nos adicionar e remover itens.
ADICIONANDO E REMOVENDO FUNÇÕES |
|
---|---|
FUNÇÃO |
DESCRIÇÃO |
np.resize(a, (x,y)) | Retorna uma versão redimensionada do array e preenche os espaços vazios por cópias repetidas de a |
np.append(a, [...]) | Anexa valores no final do array |
np.insert(a, x, ...) | Insere um valor no índice x do array |
np.delete(a, x, y) | Deleta eixos do array |
Agora por fim, mas não menos importante, iremos falar sobre o carregamento e salvamento de arrays NumPy. Para isto, podemos usar um formato integrado NumPy ou arquivos CSV.
Basicamente, estamos apenas serializando o objeto de modo que podemos usá-lo mais tarde. Isto é feito usando a função save( ).
Note que você não tem de usar o arquivo terminando em npy. Neste exemplo, apenas usamos por clareza. Você pode escolher o que quiser.
Agora, para carregar o array no nosso script novamente, precisaremos da função load( ).
Como já mencionado, podemos também salvar nosso array Numpy em arquivos CSV, que são apenas arquivos de texto separados por vírgulas. Para isso, usamos a função savetxt( ).
Nosso array está agora armazenado num arquivo CSV que é muito útil, porque ele pode então também ser lido por outras aplicações e scripts.
A fim de ler este arquivo CSV voltemos ao nosso script, usamos a função loadtxt( ).
Se você quiser ler um arquivo CSV que usa outro separador diferente daquele um (vírgula), podemos especificar um certo delimitador.
Agora ele usa ponto e vírgula como separador quando da leitura do arquivo. O mesmo pode ser também feito com a função de salvamento ou escrita.