Eu preciso escrever uma função que detectará se a entrada contém pelo menos um valor que não é numérico. Se um valor não numérico for encontrado, levantarei um erro (porque o cálculo deve retornar apenas um valor numérico). O número de dimensões da matriz de entrada não é conhecido com antecedência - a função deve fornecer o valor correto independentemente de ndim. Como complicação extra, a entrada pode ser um único float numpy.float64
ou mesmo algo estranho como um array de dimensão zero.
A maneira óbvia de resolver isso é escrever uma função recursiva que itera sobre cada objeto iterável na matriz até encontrar um não iterável. Vai aplicar onumpy.isnan()
função a todos os objetos não iteráveis. Se pelo menos um valor não numérico for encontrado, a função retornará False imediatamente. Caso contrário, se todos os valores no iterável forem numéricos, ele eventualmente retornará True.
Isso funciona muito bem, mas é muito lento e espero que o NumPy tenha uma maneira muito melhor de fazer isso. Qual alternativa é mais rápida e entorpecente?
Aqui está minha maquete:
def contains_nan( myarray ):
"""
@param myarray : An n-dimensional array or a single float
@type myarray : numpy.ndarray, numpy.array, float
@returns: bool
Returns true if myarray is numeric or only contains numeric values.
Returns false if at least one non-numeric value exists
Not-A-Number is given by the numpy.isnan() function.
"""
return True
contains_nan
parece suspeita: "Retorna falso se houver pelo menos um valor não numérico". Eu teria esperadocontains_nan
retornarTrue
se a matriz contivesse NaN.array(['None', 'None'], dtype=object)
? Essa entrada deve apenas gerar uma exceção?float('nan') in x
. Não funciona.Respostas:
Isso deve ser mais rápido do que iterar e funcionará independentemente da forma.
Editar: 30x mais rápido:
Resultados:
Bônus: funciona bem para tipos NumPy sem matriz:
fonte
float('nan') in x
não funciona? Eu tentei e python retornaFalse
ondex = [1,2,3,float('nan')]
.numpy.any
um genexp apenas retorna o genexp; você não está realmente fazendo o cálculo que pensa que está. Nunca chamenumpy.any
um genexp.np.isfinite
vez denp.isnan
detectar estouros numéricos, instabilidade, etc.Se infinito for um valor possível, eu usaria numpy.isfinite
Se o resultado acima for
True
, entãomyarray
não contém nenhum valornumpy.nan
,numpy.inf
ou-numpy.inf
.numpy.nan
estará OK comnumpy.inf
valores, por exemplo:fonte
float('nan') in x
não funciona? Eu tentei e python retornaFalse
ondex = [1,2,3,float('nan')]
.nan
s não são considerados iguais um ao outro. Experimentefloat('nan') == float('nan')
.Pfft! Microssegundos! Nunca resolva um problema em microssegundos que pode ser resolvido em nanossegundos.
Observe que a resposta aceita:
Uma solução melhor é retornar True imediatamente quando NAN for encontrado:
e funciona para n-dimensões:
Compare isso com a solução nativa numpy:
O método de saída antecipada é de 3 ordens ou aumento de magnitude (em alguns casos). Nada mal para uma anotação simples.
fonte
Com numpy 1.3 ou svn você pode fazer isso
O tratamento de nans nas comparações não era consistente nas versões anteriores.
fonte
float('nan') in x
não funciona? Eu tentei e python retornaFalse
ondex = [1,2,3,float('nan')]
.float("nan")==float("nan")
darFalse
(embora seja viável provavelmente deva retornar NAN ou Nenhum). Da mesma forma, estranheza com NAN e boolen NULL é verdadeira em muitas linguagens, incluindo SQL (onde NULL = NULL nunca é verdadeiro).(np.where(np.isnan(A)))[0].shape[0]
será maior do que0
seA
contiver pelo menos um elemento denan
,A
pode ser umn x m
matriz.Exemplo:
fonte