Mais tipos de dados
Tipos “maiores” ganham em operações de tipos misturados:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
np.array([1, 2, 3]) + 1.5
[/pastacode]
Atribuição nunca muda o tipo:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
a = np.array([1, 2, 3])
a.dtype
a[0] = 1.9 # <-- float é truncado para inteiro
a
[/pastacode]
Conversões forçadas:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
a = np.array([1.7, 1.2, 1.6])
b = a.astype(int) # <-- truncagem para inteiro
b
[/pastacode]
Arredondamento:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
a = np.array([1.2, 1.5, 1.6, 2.5, 3.5, 4.5])
b = np.around(a)
b # ainda ponto flutuante
c = np.around(a).astype(int)
c
[/pastacode]
Tamanhos de tipos de dados diferentes
Inteiros (com sinal):
int8 | 8 bits |
int16 | 16 bits |
int32 | 32 bits (mesmo que int em uma plataforma 32 bits |
int64 | 64 bits (mesmo que int em uma plataforma 64 bits |
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
np.array([1], dtype=int).dtype
np.iinfo(np.int32).max, 2**31 - 1
np.iinfo(np.int64).max, 2**63 - 1
[/pastacode]
Inteiros sem sinal:
uint8 | 8 bits |
uint16 | 16 bits |
uint32 | 32 bits |
uint64 | 64 bits |
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
np.iinfo(np.uint32).max, 2**32 - 1
np.iinfo(np.uint64).max, 2**64 - 1
[/pastacode]
Pontos flutuante:
float16 | 16 bits |
float32 | 32 bits |
float64 | 64 bits (mesmo que float) |
float96 | 96 bits, independente da plataforma (mesmo que np.longdouble) |
float128 | 128 bits, independente da plataforma (mesmo que np.longdouble) |
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
np.finfo(np.float32).eps
np.finfo(np.float64).eps
np.float32(1e-8) + np.float32(1) == 1
np.float64(1e-8) + np.float64(1) == 1
[/pastacode]
Tipos de dados pequenos
Se você não sabe se você precisa de tipos de dados espaciais é porque você provavelmente não precisa.
Comparação utilizando float32 ao invés de float64:
- Metade do tamanho na memória e no disco;
- Metade da largura de banda da memória requerida (pode ser mais rápido em algumas operações):
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
import time
a = np.zeros((1e6,), dtype=np.float64)
b = np.zeros((1e6,), dtype=np.float32)
tempo = time.time()
a*a
print time.time() - tempo
tempo = time.time()
b*b
print time.time() - tempo
[/pastacode]
- Mas: grandes erros de arredondamento, as vezes, em lugares surpreendentes.
Tipos de dados estruturados
sensor_code | string de 4 caracteres |
position | float |
value | float |
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
amostra = np.zeros((6,), dtype=[('sensor_code', 'S4'),
('position', float), ('value', float)])
print amostra.ndim
print amostra.shape
print amostra.dtype.names
amostra[:] = [('ALFA', 1, 0.37), ('BETA', 1, 0.11), ('TAU', 1, 0.13),
('ALFA', 1.5, 0.37), ('ALFA', 3, 0.11), ('TAU', 1.2, 0.13)]
print amostra
[/pastacode]
Acesso aos campos funciona pela indexação com nomes do campo:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
amostra['sensor_code']
amostra['value']
amostra[0]
amostra[0]['sensor_code'] = 'TAU'
amostra[0]
[/pastacode]
Múltiplos campos ao mesmo tempo:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
samples[['position', 'value']]
[/pastacode]
A indexação sofisticada funciona, como usual:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
samples[samples['sensor_code'] == 'ALFA']
[/pastacode]
Observação: existem um monte de outras sintaxes para a construção de arrays estruturadas, veja aqui e aqui.
maskedarray: lidando com (propagação de) dados perdidos
Para pontos flutuantes pode-se usar os NaN, mas máscaras funcionam para todos os tipos:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
x = np.ma.array([1, 2, 3, 4], mask=[0, 1, 0, 1])
x
y = np.ma.array([1, 2, 3, 4], mask=[0, 1, 1, 1])
x + y
[/pastacode]
Mascarando versões de funções comuns:
[pastacode lang=”python” message=”” highlight=”” provider=”manual”]
np.ma.sqrt([1, -1, 2, -2])
[/pastacode]
Observação: Existe outro array siblings útil.