Pandas: Qual é a maneira mais eficiente de iterar no DataFrame do Pandas linha por linha?

Criado em 12 jun. 2015  ·  6Comentários  ·  Fonte: pandas-dev/pandas

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.

Usage Question

Comentários muito úteis

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

Todos 6 comentários

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.

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

Questões relacionadas

songololo picture songololo  ·  3Comentários

mfmain picture mfmain  ·  3Comentários

BDannowitz picture BDannowitz  ·  3Comentários

matthiasroder picture matthiasroder  ·  3Comentários

amelio-vazquez-reina picture amelio-vazquez-reina  ·  3Comentários