Eu tentei a função df.iterrows()
mas seu desempenho é horrível. O que não é surpreendente, visto que iterrows()
retorna Series
com o esquema completo e metadados, não apenas os valores (que são tudo o que eu preciso).
O segundo método que tentei é for row in df.values
, que é significativamente mais rápido. No entanto, recentemente percebi que df.values
não é o armazenamento de dados interno do DataFrame, porque df.values
converte todos os dtypes
em um dtype
. Por exemplo, uma das minhas colunas tem dtipo int64
mas o dtipo de df.values
é todo float64
. Portanto, suspeito que df.values
realmente cria outra cópia dos dados internos.
Além disso, outro requisito é que a iteração da linha deve retornar uma lista de valores que preservam os dtype
originais dos dados.
Em Python, iterar nas linhas será (muito) mais lento do que fazer operações vetorizadas.
Os tipos estão sendo convertidos em seu segundo método porque é assim que matrizes numpy (que é o que df.values
é) funcionam. DataFrames são baseados em colunas, então você pode ter um único DataFrame com vários dtypes. Depois de iterar por meio de linhas, tudo deve ser atualizado para um tipo mais geral que contém tudo. No seu caso, os ints vão para float64
.
Se você descrever seu problema com um exemplo de trabalho mínimo, podemos ajudá-lo a vetorizá-lo. Você também pode ter sorte no StackOverflow com a tag pandas.
Basicamente, quero fazer o seguinte:
row_handler = RowHandler(sample_df) # learn how to handle row from sample data
transformed_data = []
for row in df.values:
transformed_data.append(row_handler.handle(row))
return transformed_data
Não sou proprietário da classe RowHandler
e, portanto, só posso operar linha por linha.
Outro exemplo semelhante é no aprendizado de máquina, onde você pode ter um modelo que tem API de previsão apenas no nível da linha.
Ainda um pouco vago demais para ser útil. Mas se RowHandler
estiver realmente fora de seu controle, você estará sem sorte. FWIW todas as APIs do scikit-learn operam em matrizes (portanto, várias linhas).
Não vejo como pode ser mais claro. Sim, RowHandler
está fora do meu controle. O que você quer dizer com sem sorte? Minha pergunta é sobre a maneira mais eficiente de iterar nas linhas, mantendo o dtype
de cada elemento intacto. Você está sugerindo df.iterrows()
ou algo mais?
sklearn
é uma exceção, não a norma, que opera nativamente nos PDs DataFrame
. Poucas bibliotecas de aprendizado de máquina têm APIs que operam em DataFrame
.
Acho que df.itertuples()
é o que você está procurando - é muito mais rápido do que iterrows:
In [10]: x = pd.DataFrame({'x': range(10000)})
In [11]: %timeit list(x.iterrows())
1 loops, best of 3: 383 ms per loop
In [12]: %timeit list(x.itertuples())
1000 loops, best of 3: 1.39 ms per loop
Obrigado @shoyer! Isso é o que eu preciso.
Comentários muito úteis
Acho que
df.itertuples()
é o que você está procurando - é muito mais rápido do que iterrows: