Numpy: `np.diff` foi quebrado para ndarrays booleanos em 1.13.0

Criado em 14 jun. 2017  ·  29Comentários  ·  Fonte: numpy/numpy

Deve modificar a docstring de acordo, gerar um erro significativo ou (de preferência) fazê-lo funcionar ocultando alguma lógica por baixo do capô.

Traceback:

In [11]: x = np.array([[True, True], [False, False]])

In [12]: np.diff(x)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-59225436601c> in <module>()
----> 1 np.diff(x)

/usr/lib/python3.6/site-packages/numpy/lib/function_base.py in diff(a, n, axis)
   1924         return diff(a[slice1]-a[slice2], n-1, axis=axis)
   1925     else:
-> 1926         return a[slice1]-a[slice2]
   1927 
   1928 

TypeError: numpy boolean subtract, the `-` operator, is deprecated, use the bitwise_xor, the `^` operator, or the logical_xor function instead.

In [13]: np.__version__
Out[13]: '1.13.0'

xref https://github.com/scikit-image/scikit-image/issues/2681

06 - Regression numpy.lib good first issue

Comentários muito úteis

Bem - eu posso ver o argumento de pureza para não permitir, mas me parece que é razoável esperar que diff funcione em booleanos, e não é de se surpreender que a imagem do scikit estivesse fazendo isso. Então, eu teria pensado que uma filial em bool era o melhor caminho.

Todos 29 comentários

Parece uma solução fácil. A função diff é puro Python e reside aqui:

https://github.com/numpy/numpy/blob/master/numpy/lib/function_base.py#L1835

Você provavelmente desejaria ramificar em a.dtype == bool , e dada a observação sobre booleanos na docstring, use ^ (ou != ) em vez de - para manter compatibilidade com versões anteriores.

Parece-me que se - está obsoleto, então diff é perfeitamente razoável para não permitir também.

Bem - eu posso ver o argumento de pureza para não permitir, mas me parece que é razoável esperar que diff funcione em booleanos, e não é de se surpreender que a imagem do scikit estivesse fazendo isso. Então, eu teria pensado que uma filial em bool era o melhor caminho.

Eu votaria em manter a funcionalidade. Se todos concordarmos, enviarei um patch ainda hoje ou amanhã.

PS Você poderia, por favor, apontar-me a discussão onde a justificativa para descontinuar -= foi dada?

Se diff está obsoleto em booleanos, então a docstring precisa ser atualizada para refletir isso. E provavelmente ainda desejaríamos ramificar em bool para gerar mais um erro de contexto?

Parece-me que podemos querer um tipo np.uint1 que se comporte como um inteiro e não um booleano, no qual np.diff e - podem ser definidos.

Meu voto seria evitar que o usuário tivesse que parar e depurar um erro em np.diff(some_bools) ; primeiro - quebra a compatibilidade com versões anteriores e, segundo, o comportamento desejado é útil e claramente definido.

primeiro - quebra a compatibilidade com versões anteriores e, segundo, o comportamento desejado é útil e claramente definido.

Ambos os argumentos se aplicam a np.subtract também, não é? Talvez essa discussão deva ser revisitada

Sim, eles fazem, e se você pensar instintivamente em diff como uma implementação de subtract então você provavelmente deseja um erro. Minha convicção é que as pessoas pensam em diff de uma maneira ligeiramente diferente de subtract , de modo que concordariam que subtrair bools não faz sentido, enquanto pegar diff de bools faz - significando 'este valor é diferente do anterior'.

"este valor é diferente do anterior" soa como uma operação digna de seu próprio nome que generaliza para todos os dtypes, ao invés de soletrá-lo np.diff(x).astype(bool) .

Talvez ufunc.pairwise(x, axis=...) , implementado como ufunc(x[:-1], x[1:]) ignorando o argumento do eixo? Isso tornaria a função desejada np.not_equal.pairwise .

Embora pairwise possa implicar no comportamento que outer já tem ...

Claro, isso também pode ser uma boa ideia - mas eu ainda argumentaria que seria mais gentil (praticidade supera pureza) perdoar essa maneira de pensar de bools e np.diff .

O operador de subtração para booleanos está obsoleto há algum tempo, desde 1.9 eu acredito, a imagem scikit não tem prestado atenção. Prestar atenção também é uma boa ideia;) Acho que um nome diferente seria apropriado, xdiff ou algo parecido.

Dito isso, ter diff handle booleanos para compatibilidade com versões anteriores é provavelmente uma boa ideia.

É um pouco injusto culpar a imagem do scikit aqui - não consigo ver nenhum aviso de suspensão de uso do numpy 1.12.1 e:

In [4]: np.diff([True, False])
Out[4]: array([ True], dtype=bool)

não consigo ver nenhum aviso de suspensão de uso para numpy 1.12.1 e

Isso porque, por padrão, DeprecationWarning não é exibido. Adicione um import warnings; warnings.simplefilter('always') e você o verá

In [1]: import warnings

In [2]: warnings.simplefilter('always')

In [3]: np.diff([True, False])
/home/charris/.local/lib/python2.7/site-packages/numpy/lib/function_base.py:1175: DeprecationWarning: numpy boolean subtract, the `-` operator, is deprecated, use the bitwise_xor, the `^` operator, or the logical_xor function instead.
  return a[slice1]-a[slice2]
Out[3]: array([ True], dtype=bool)

In [4]: np.__version__
Out[4]: '1.10.4'

Outra coisa que devemos fazer é adicionar um teste para diff usando um array booleano, seja para assert_raises ou para validar o resultado.

Como a solução parece ser controversa (acho que estou com Matthew nisso, embora não me importe muito de qualquer maneira), enviei um e-mail para a lista para que todos tenham uma palavra a dizer.

Eu também sou do tipo pureza batida prática aqui, especialmente porque isso costumava funcionar. De alguma forma, como @ matthew-brett, há uma confusão "diff" é "diferença / difere" em minha mente, e certamente usei np.diff como uma maneira rápida de encontrar lugares onde os valores mudaram.

ps @jaimefrio - Não vi nenhuma mensagem na lista de discussão (numerosa discussão).

1 para praticidade.

E definitivamente -1 para uma nova função. Se for útil, coloque-o em diff . O namespace já é muito grande.

Sim, percebi que não consegui encontrar meu e-mail nos arquivos para vinculá-lo aqui. Mas há um e-mail na minha pasta enviada para [email protected] às 18:00 CET. Talvez o servidor esteja com problemas novamente? Ou esses problemas já foram corrigidos para sempre?

Endereço errado, mudou;) [email protected] .

Ah, isso explicaria ...

Aqui está um link para o e-mail, reenviado para o endereço correto, para referência futura:

https://mail.python.org/pipermail/numpy-discussion/2017-June/076877.html

Isso não parece nada bom - https://github.com/scipy/scipy/issues/7493 .

Alguém quer fazer um PR adicionando suporte para matrizes booleanas ao diff?

@charris eu faço. Estamos todos de acordo com isso?

@soupault acho que é o consenso.

Isso também se aplica a np.gradient . Podemos consertar isso também? (pode dobrar em # 9411)

Digite ping na pergunta de @eric-wieser. Devemos corrigir np.gradient também?

Pessoalmente, não vejo muito sentido em suportar gradientes de matrizes bool.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

inducer picture inducer  ·  3Comentários

Kreol64 picture Kreol64  ·  3Comentários

thouis picture thouis  ·  4Comentários

keithbriggs picture keithbriggs  ·  3Comentários

MorBilly picture MorBilly  ·  4Comentários