Eu tenho um DataFrame
dos pandas:
import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df
Resultado:
c1 c2
0 10 100
1 11 110
2 12 120
Agora eu quero percorrer as linhas desse quadro. Para cada linha, quero poder acessar seus elementos (valores em células) pelo nome das colunas. Por exemplo:
for row in df.rows:
print row['c1'], row['c2']
É possível fazer isso em pandas?
Eu encontrei essa pergunta semelhante . Mas isso não me dá a resposta que eu preciso. Por exemplo, é sugerido lá usar:
for date, row in df.T.iteritems():
ou
for row in df.iterrows():
Mas não entendo qual é o row
objeto e como posso trabalhar com ele.
iter*
funções devem ser usadas em circunstâncias muito raras. Também relacionado .iterrows
, existem maneiras melhores de iterar sobre um DataFrame; você também pode iterar sobre uma lista de listas nesse momento. Se você estiver no ponto em que não está fazendo nada além de iterar sobre DataFrames, não há realmente nenhum benefício em usar um DataFrame (presumir que iterá-lo é a única coisa que você está fazendo com ele). Apenas meu 2c.pandas
é a opção de ler um arquivo csv, mesmo que o conjunto de dados seja pequeno. É simplesmente mais fácil a programação para manipular os dados com APIsRespostas:
DataFrame.iterrows é um gerador que gera índice e linha
fonte
431341610650
onde são lidos4.31E+11
. Existe uma maneira de preservar os tipos?itertuples
, como explicado abaixo. Veja também pandas.pydata.org/pandas-docs/stable/generated/…Resposta: NÃO * !
A iteração nos pandas é um antipadrão e é algo que você só deve fazer quando tiver esgotado todas as outras opções. Você não deve usar nenhuma função com "
iter
" em seu nome por mais de alguns milhares de linhas ou terá que se acostumar com muita espera.Deseja imprimir um DataFrame? Use
DataFrame.to_string()
.Deseja calcular alguma coisa? Nesse caso, procure métodos nesta ordem (lista modificada aqui ):
for
loop de baunilha )DataFrame.apply()
: i) Reduções que podem ser executadas em cython, ii) Iteração no espaço pythonDataFrame.itertuples()
eiteritems()
DataFrame.iterrows()
iterrows
eitertuples
(ambos recebendo muitos votos em respostas a essa pergunta) devem ser usados em circunstâncias muito raras, como a geração de objetos de linha / nametuples para processamento seqüencial, que é realmente a única coisa para a qual essas funções são úteis.Apelação à autoridade
A página de documentos na iteração tem uma enorme caixa de aviso vermelha que diz:
* Na verdade, é um pouco mais complicado do que "não".
df.iterrows()
é a resposta correta para essa pergunta, mas "vetorize suas operações" é a melhor. Admito que há circunstâncias em que a iteração não pode ser evitada (por exemplo, algumas operações em que o resultado depende do valor calculado para a linha anterior). No entanto, é preciso alguma familiaridade com a biblioteca para saber quando. Se você não tem certeza se precisa de uma solução iterativa, provavelmente não precisa. PS: Para saber mais sobre minha justificativa para escrever esta resposta, pule para o final.Mais rápido do que Looping: Vectorization , Cython
Um bom número de operações e cálculos básicos é "vetorizado" pelos pandas (por meio do NumPy ou por funções Cythonized). Isso inclui aritmética, comparações, (a maioria) reduções, remodelagem (como rotação), junções e operações de grupo por grupo. Consulte a documentação sobre Funcionalidade básica essencial para encontrar um método vetorizado adequado para o seu problema.
Se não houver, sinta-se à vontade para criar suas próprias extensões usando o cython personalizado .
Melhor coisa seguinte: lista de compreensões *
A compreensão da lista deve ser o seu próximo porto de escala se 1) não houver uma solução vetorizada disponível, 2) o desempenho for importante, mas não o suficiente para passar pelo incômodo de codificar o código e 3) você estiver tentando executar uma transformação elementar no seu código. Há uma boa quantidade de evidências para sugerir que a compreensão da lista é suficientemente rápida (e às vezes mais rápida) para muitas tarefas comuns dos pandas.
A fórmula é simples,
Se você pode encapsular sua lógica de negócios em uma função, poderá usar uma compreensão de lista que a chama. Você pode fazer coisas arbitrariamente complexas funcionarem através da simplicidade e velocidade do python bruto.
As
compreensões da Lista de Advertências pressupõem que seus dados sejam fáceis de trabalhar - o que significa que seus tipos de dados são consistentes e você não possui NaNs, mas isso nem sempre pode ser garantido.
zip(df['A'], df['B'], ...)
vez de,df[['A', 'B']].to_numpy()
pois o último implica implicitamente em transferência de dados para o tipo mais comum. Como exemplo, se A for numérico e B for string,to_numpy()
converterá toda a matriz em string, o que pode não ser o que você deseja. Felizmente,zip
pingar suas colunas juntas é a solução mais direta para isso.* YMMV pelos motivos descritos na seção Advertências acima.
Um exemplo óbvio
Vamos demonstrar a diferença com um exemplo simples de adição de duas colunas de pandas
A + B
. Como é uma operação vetorizável, será fácil contrastar o desempenho dos métodos discutidos acima.Código de benchmarking, para sua referência.
Devo mencionar, no entanto, que nem sempre é tão fácil assim. Às vezes, a resposta para "qual é o melhor método para uma operação" é "depende dos seus dados". Meu conselho é testar diferentes abordagens nos seus dados antes de escolher um.
Leitura adicional
10 minutos para pandas e funcionalidade básica essencial - Links úteis que apresentam você aos pandas e sua biblioteca de funções vetorizadas * / cthonizadas.
Melhorando o desempenho - Uma cartilha dos documentos sobre o aprimoramento das operações padrão dos pandas
Os loops de pandas são realmente ruins? Quando devo me importar? - uma descrição detalhada por mim sobre as compreensões da lista e sua adequação a várias operações (principalmente as que envolvem dados não numéricos)
Quando devo usar pandas apply () no meu código? -
apply
é lento (mas não tão lento quanto aiter*
família. Há, no entanto, situações em que se pode (ou deve) considerarapply
uma alternativa séria, especialmente em algumasGroupBy
operações).* Os métodos de string do Pandas são "vetorizados" no sentido em que são especificados na série, mas operam em cada elemento. Os mecanismos subjacentes ainda são iterativos, porque as operações de cadeia de caracteres são inerentemente difíceis de vetorizar.
Por que escrevi esta resposta
Uma tendência comum que noto de novos usuários é fazer perguntas do formulário "como posso iterar meu df para fazer o X?". Mostrando código que chama
iterrows()
enquanto faz algo dentro de um loop for. Aqui está o porquê. Um novo usuário da biblioteca que não tenha sido introduzido no conceito de vetorização provavelmente visualizará o código que resolve o problema como iterando sobre os dados para fazer alguma coisa. Sem saber como iterar em um DataFrame, a primeira coisa que eles fazem é pesquisar no Google e acabar aqui, nesta pergunta. Eles veem a resposta aceita dizendo como e fecham os olhos e executam esse código sem antes questionar se a iteração não é a coisa certa a fazer.O objetivo desta resposta é ajudar os novos usuários a entender que a iteração não é necessariamente a solução para todos os problemas, e que soluções melhores, mais rápidas e mais idiomáticas podem existir, e que vale a pena investir tempo explorando-as. Não estou tentando iniciar uma guerra de iteração x vetorização, mas quero que novos usuários sejam informados ao desenvolver soluções para seus problemas com esta biblioteca.
fonte
zip(df['A'], df['B'])
vez dedf.iterrows()
.iterrows()
e implicitamente denunciar a iteração, se e quando existirem melhores alternativas.for
os loops sozinhos são bons, mas a compreensão da lista é melhor se você estiver executando iterativamente transformações em elementos.DataFrame.values
converterá todas as colunas em um tipo de dados comum.DataFrame.to_numpy()
faz isso também. Felizmente, podemos usarzip
com qualquer número de colunas.Primeiro, considere se você realmente precisa iterar sobre as linhas em um DataFrame. Veja esta resposta para alternativas.
Se você ainda precisar iterar sobre as linhas, poderá usar os métodos abaixo. Observe algumas advertências importantes que não são mencionadas em nenhuma das outras respostas.
DataFrame.iterrows ()
DataFrame.itertuples ()
itertuples()
é suposto ser mais rápido do queiterrows()
Mas esteja ciente, de acordo com os documentos (pandas 0.24.2 no momento):
iterrows:
dtype
pode não corresponder de uma linha para outraiterrows: Não modifique linhas
Use DataFrame.apply () :
itertuples:
Consulte os documentos do pandas sobre iteração para obter mais detalhes.
fonte
for row in df[['c1','c2']].itertuples(index=True, name=None):
incluir apenas determinadas colunas no iterador da linha.getattr(row, "c1")
, você pode usar apenasrow.c1
.getattr(row, "c1")
vez derow.c1
, perderá qualquer vantagem de desempenhoitertuples
e, se realmente precisar acessar a propriedade por meio de uma string, use as linhas abaixo.numba
ecython
(os mesmos documentos dizem que "sempre vale a pena otimizar no Python primeiro"). Escrevi esta resposta para ajudar outras pessoas a evitar problemas (às vezes frustrantes), pois nenhuma das outras respostas menciona essas advertências. Enganar alguém ou dizer "é a coisa certa a fazer" nunca foi minha intenção. Eu melhorei a resposta.Você deveria usar
df.iterrows()
. Embora a iteração linha a linha não seja especialmente eficiente, pois osSeries
objetos precisam ser criados.fonte
Embora
iterrows()
seja uma boa opção, às vezesitertuples()
pode ser muito mais rápido:fonte
for a,b,c in izip(df["a"],df["b"],df["c"]:
é quase igualmente rápido.iterrows()
cada linha de dados em uma série, enquantoitertuples()
que não.df
é criada a partir de um dicionário, portanto,row[1]
pode se referir a qualquer uma das colunas. Acontece que os tempos são aproximadamente os mesmos para o número inteiro versus as colunas flutuantes.Você também pode usar
df.apply()
para iterar sobre linhas e acessar várias colunas para uma função.docs: DataFrame.apply ()
fonte
apply
não "iteratita" sobre linhas, mas aplica uma função em linhas. O código acima não iria funcionar se você realmente fazer iterações necessidade e indeces, por exemplo quando se comparam os valores em diferentes linhas (nesse caso, você não pode fazer nada, mas iteração).Você pode usar a função df.iloc da seguinte maneira:
fonte
itertuples
preserva os tipos de dados, mas se livra de qualquer nome que não goste.iterrows
faz o oposto.for i in range(df.shape[0])
possa acelerar um pouco essa abordagem, ainda é cerca de 3,5x mais lenta que a abordagem iterrows () acima para o meu aplicativo.my_iter = df.itertuples()
leva o dobro da memória e muito tempo para copiá-la. o mesmo paraiterrows()
.Eu estava procurando como iterar em linhas e colunas e terminou aqui, então:
fonte
Você pode escrever seu próprio iterador que implementa
namedtuple
Isto é diretamente comparável a
pd.DataFrame.itertuples
. Meu objetivo é executar a mesma tarefa com mais eficiência.Para o dado quadro de dados com minha função:
Ou com
pd.DataFrame.itertuples
:Um teste abrangente
Testamos a disponibilização de todas as colunas e o subconjunto delas.
fonte
intertuples
, linha laranja é uma lista de um iterador através de um bloco de rendimento.interrows
não é comparado.Como iterar eficientemente?
Se você realmente precisa iterar um quadro de dados do pandas, provavelmente desejará evitar o uso de iterrows () . Existem métodos diferentes e o usual
iterrows()
está longe de ser o melhor. itertuples () pode ser 100 vezes mais rápido.Em resumo:
df.itertuples(name=None)
. Em particular, quando você tem um número fixo de colunas e menos de 255 colunas. Ver ponto 3)df.itertuples()
exceto se suas colunas tiverem caracteres especiais, como espaços ou '-'. Ver ponto 2)itertuples()
mesmo se o seu quadro de dados tiver colunas estranhas usando o último exemplo. Ver ponto (4)iterrows()
se você não conseguir as soluções anteriores. Ver ponto 1)Métodos diferentes para iterar sobre linhas em um dataframe do pandas:
Gere um quadro de dados aleatório com um milhão de linhas e 4 colunas:
1) O habitual
iterrows()
é conveniente, mas muito lento:2) O padrão
itertuples()
já é muito mais rápido, mas não funciona com nomes de colunas comoMy Col-Name is very Strange
(você deve evitar esse método se suas colunas forem repetidas ou se um nome de coluna não puder ser simplesmente convertido em um nome de variável python) .:3) O padrão
itertuples()
usando name = None é ainda mais rápido, mas não é realmente conveniente, pois você precisa definir uma variável por coluna.4) Finalmente, o nomeado
itertuples()
é mais lento que o ponto anterior, mas você não precisa definir uma variável por coluna e funciona com nomes de colunas comoMy Col-Name is very Strange
.Resultado:
Este artigo é uma comparação muito interessante entre iterrows e itertuples
fonte
Para fazer o loop de todas as linhas em um
dataframe
você pode usar:fonte
fonte
Às vezes, um padrão útil é:
O que resulta em:
fonte
Para fazer o loop de todas as linhas em a
dataframe
e usar os valores de cada linha convenientemente ,namedtuples
pode ser convertido emndarray
s. Por exemplo:Iterando sobre as linhas:
resulta em:
Observe que, se
index=True
, o índice é adicionado como o primeiro elemento do tuplo , que podem ser indesejáveis para algumas aplicações.fonte
Existe uma maneira de iterar as linhas de lançamento ao obter um DataFrame em troca, e não uma Série. Não vejo ninguém mencionando que você pode passar o índice como uma lista para a linha ser retornada como um DataFrame:
Observe o uso de colchetes duplos. Isso retorna um DataFrame com uma única linha.
fonte
Para visualizar e modificar valores, eu usaria
iterrows()
. Em um loop for e usando a descompactação da tupla (veja o exemploi, row
:), eu uso orow
para exibir apenas o valor e o usoi
com oloc
método quando desejar modificar valores. Conforme declarado nas respostas anteriores, aqui você não deve modificar algo sobre o qual está iterando.Aqui
row
, o loop é uma cópia dessa linha, e não uma visão dela. Portanto, você NÃO deve escrever algo comorow['A'] = 'New_Value'
isso não modificará o DataFrame. No entanto, você pode usari
eloc
e especificar a trama de dados para fazer o trabalho.fonte
Sei que estou atrasado para a parte que responde, mas só quero adicionar a resposta do @ cs95 acima, que acredito que deve ser a resposta aceita. Em sua resposta, ele mostra que a vetorização de pandas supera em muito outros métodos de pandas para calcular coisas com quadros de dados.
Eu gostaria de acrescentar que, se você primeiro converter o quadro de dados em uma matriz numpy e depois usar a vetorização, é ainda mais rápido que a vetorização de quadro de dados do pandas (e isso inclui tempo para transformá-lo novamente em uma série de quadros de dados).
Se você adicionar as seguintes funções ao código de referência do @ cs95, isso se tornará bastante evidente:
fonte
Você também pode fazer a
numpy
indexação para acelerar ainda mais. Não é realmente iterativo, mas funciona muito melhor do que a iteração para certos aplicativos.Você também pode querer convertê-lo em uma matriz. Esses índices / seleções devem agir como matrizes Numpy, mas eu tive problemas e precisei transmitir
fonte
Existem muitas maneiras de iterar sobre as linhas no dataframe do pandas. Uma maneira muito simples e intuitiva é:
fonte
Este exemplo usa o iloc para isolar cada dígito no quadro de dados.
fonte
Algumas bibliotecas (por exemplo, uma biblioteca de interoperabilidade Java que eu uso) exigem que os valores sejam transmitidos em uma linha por vez, por exemplo, ao transmitir dados. Para replicar a natureza do streaming, eu transmito meus valores do quadro de dados um por um, escrevi abaixo, o que é útil de tempos em tempos.
Qual pode ser usado:
E preserva o mapeamento de valores / nome para as linhas que estão sendo iteradas. Obviamente, é muito mais lento do que usar o apply e o Cython, conforme indicado acima, mas é necessário em algumas circunstâncias.
fonte
Em resumo
Detalhes neste vídeo
Referência
fonte