Repository navigation
Campo do modelo que o Arrow não tipa sai como Object na saída polars - #220
Conversation
Com entrada polars, a conversão final dos campos do modelo levantava ArrowInvalid, TypeError ou OverflowError depois de todas as chamadas quando as respostas não cabiam numa coluna tipada: Union[int, str] com número numa linha e texto em outra, tuple[int, str], Any e dict[str, Any] com tipos diferentes, lista de Enum, inteiro acima de 2**53 ao lado de float e inteiro acima do Int64. Sem checkpoint_path, as respostas se perdiam. A conversão passa a ser coluna a coluna. O Enum vai pelo valor, como no checkpoint. A coluna que o Arrow recusa sai com o tipo Object, com os objetos Python que a entrada pandas devolveria, e um aviso a nomeia. Na ida, a coluna Object é lida pelos objetos, para que a saída com uma coluna dessas possa ser retomada: no polars 0.20, o to_pandas() devolve bytes no lugar deles. A remoção das colunas de status ociosas sai de from_pandas para uma função própria. Closes #218
Revisão independente: achados abertos, PR ainda não pronto para mergeUm subagente novo revisou 1. Polars 0.20.23 a 0.20.31: valor trocado por nulo sem erro. Nessas versões, 2. Erros que escapam da captura e ainda derrubam a saída depois das chamadas. 3. A construção da coluna 4. Testes. Três mutações passam: 5. Texto. O aviso e a referência mandam converter "antes de gravar em parquet", mas CSV, IPC e JSON também recusam coluna Aceito como está. |
… a saída Com entrada polars, três casos ainda escapavam da degradação para Object: - O polars 0.20.23 a 0.20.31 converte a coluna de texto com um número e põe nulo no lugar dele, sem levantar erro. A coluna que volta com mais nulos do que tinha no pandas passa a sair Object. A Struct fica fora da comparação, porque o polars 0.20 e o 1.0 contam como nula a linha com todos os campos nulos. - O ComputeError do polars, como o do datetime com fuso +05:30, não é ValueError nem TypeError e derrubava a saída depois de todas as chamadas. Qualquer exceção da conversão leva a coluna a Object. - A coluna Object é montada por map_elements. O pl.Series com dtype=pl.Object olha o primeiro valor e levanta erro com range e dataclass no polars 0.20.0, e o array numpy de objetos que começa por texto não sai Object do 0.20.22 em diante. O Enum sai pelo valor também na coluna Object. O aviso e a referência falam em gravar em arquivo, porque CSV, IPC e JSON também recusam a coluna Object, e a referência diz que a coluna de entrada com nome de coluna adicionada não volta como entrou. Os testes novos conferem a linha para a qual o aviso aponta, o aviso único para duas colunas, o Enum em coluna Object, o nulo a mais (simulado, para não depender da versão instalada) e as colunas com nulo que continuam tipadas.
Segunda revisão independente: sem achado que bloqueie; piso do polars sobe para 1.0Os achados da primeira revisão foram corrigidos em O que confirmou. Nenhuma regressão contra a Achados, nenhum bloqueia:
A revisão também mediu que três proteções do diff (a comparação de nulos com a exceção de Decisão do dono do repositório: o extra |
…cusada Os extras polars e all passam a exigir polars>=1.0. Nesse piso, o pl.from_pandas recusa com erro a coluna de texto com valor de outro tipo, e o to_pandas() devolve os objetos de uma coluna Object. A coluna de um campo do modelo vai para Object só quando a conversão levanta erro, e a retomada lê a coluna Object pelo to_pandas() do polars. A coluna Object continua montada por map_elements: o construtor de Series troca o membro de Enum pelo valor mesmo com dtype=pl.Object. O caso que chega lá com um membro de Enum é o Enum cujo valor é membro de outro Enum, agora coberto por teste. O aviso e a referência da API dizem que o Enum fora de lista ou dict sai pelo valor também na coluna Object.
Sem o teste, mandar para Object toda coluna com nulo (float com NaN, inteiro com NA, datetime com NaT, texto com None, lista com None, coluna toda nula, dict com campo nulo) passava na suíte inteira. Os comentários de from_pandas dizem que o pânico do polars não é capturado e que só algumas versões do construtor de Series inspecionam os valores. O teste das colunas de entrada deixa de tratar Decimal à parte, que Series.equals compara desde o piso atual.
Terceira revisão independente (piso
|
O quê
Com entrada polars, a conversão final dos campos do modelo falhava depois de todas as chamadas ao provider quando as respostas não cabiam numa coluna tipada. Um campo
Union[int, str]que recebe 1 numa linha e "dois" em outra levantavaArrowInvalid: Could not convert 'dois' with type str: tried to convert to int64, e semcheckpoint_pathas respostas se perdiam. Com entrada pandas, o mesmo modelo devolve a colunaobject.A falha atinge nove formas de campo:
Enumcom valores em texto,tuple[int, str],Union[int, str],Anyedict[str, Any]com tipos diferentes,list[Union[int, str]],Union[int, float]com inteiro acima de 2**53 ao lado de float,intacima doInt64(OverflowError) edatetimecom fuso de deslocamento, como+05:30(ComputeError).Como
Object, com os objetos Python que a entrada pandas devolveria, e umUserWarningúnico nomeia essas colunas e avisa que precisam de conversão antes de ir para arquivo.Enumsai pelo valor do membro, como o checkpoint já grava, inclusive na colunaObject. Dentro de lista ou dict oEnumfica como está, e a coluna saiObject.Objecté montada pormap_elements, que guarda o que a função devolve. O construtor deSeriesinspeciona os valores mesmo comdtype=pl.Object: quando o primeiro valor não nulo é membro deEnum, troca cada valor pelo.valuee levanta erro no que não o tem.polarspassa a exigirpolars>=1.0. No 0.20 há versões que convertem a coluna de texto com um valor de outro tipo pondo nulo no lugar dele, sem erro, e versões em que oto_pandas()de uma colunaObject, pelo qual ela volta na retomada, devolve bytes ou entra em pânico. Suportá-las pedia uma comparação de nulos e uma releitura da coluna que só o job de versões mínimas exercitava.from_pandaspara_drop_idle_control_columns, sem mudança de comportamento, para a função caber no limite de complexidade do lint.docs/reference/api.mde a versão em inglês) descreve o retorno com entrada polars.Testes
Objectcom os mesmos valores da entrada pandas, e o aviso nomeia a coluna.dataframeit(); oEnumsai pelo valor, com e sem colunaObject; o membro deEnumque chega à colunaObjectfica inteiro; entradapolars.Series; retomada de uma saída com colunaObject; a coluna com nulo legítimo (NaN,pd.NA,NaT,None, lista comNone, toda nula) continua tipada e sem aviso.codex(1175 e 1170), cobertura de ramos combinada em 100%, e versões mínimas com polars 1.0.0, pandas 2.1.2 e pyarrow 10 (1178 passam).ruff,ty,vulture,deptryemkdocs buildpassam.Closes #218