Comment itérer sur des lignes dans une DataFrame dans Pandas?

j'ai un DataFrame de pandas:

import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df

sortie:

   c1   c2
0  10  100
1  11  110
2  12  120

maintenant je veux itérer au-dessus des lignes de ce cadre. Pour chaque ligne je veux pouvoir accéder à ses éléments (valeurs dans les cellules) par le nom des colonnes. Par exemple:

for row in df.rows:
   print row['c1'], row['c2']

est-il possible de faire cela dans les pandas?

j'ai trouvé ce question similaire . Mais il ne me donne pas la réponse dont j'ai besoin. Par exemple, il est suggéré d'utiliser:

for date, row in df.T.iteritems():

ou

for row in df.iterrows():

mais je ne comprends pas ce qu'est l'objet row et comment je peux travailler avec lui.

855
demandé sur petezurich 2013-05-10 11:04:49

14 réponses

iterrows est un générateur qui donnent à la fois l'indice et de la ligne

for index, row in df.iterrows():
   print row['c1'], row['c2']

Output: 
   10 100
   11 110
   12 120
1225
répondu waitingkuo 2018-08-13 13:57:37

pour itérer à travers la ligne de DataFrame dans pandas on peut utiliser:

itertuples() est censé être plus rapide que iterrows()

mais attention, selon les docs (pandas 0.21.1 à l'heure actuelle):

  • iterrows: dtype peut ne pas correspondre à la ligne à la ligne

    parce que iterrows retourne une série pour chaque ligne, il ne conserve pas les dtypes à travers les lignes (les dtypes sont conservés à travers les colonnes pour les images de données).

  • iterrows: Ne pas modifier les lignes

    vous devriez ne jamais modifier quelque chose que vous êtes à parcourir. Ce n'est pas garanti dans tous les cas. Selon les types de données, l'itérateur renvoie une copie et non un point de vue, et l'écriture elle n'aura aucun effet.

    Utiliser DataFrame.appliquer() au lieu de:

    new_df = df.apply(lambda x: x * 2)
    
  • itertuples:

    les noms des colonnes seront renommés en les noms de position s'il s'agit d'identificateurs Python invalides, répétés ou commençant par un underscore. Avec un grand nombre de colonnes (>255), les tuples sont retournés.

174
répondu viddik13 2017-12-17 03:54:27

alors que iterrows() est une bonne option, parfois itertuples() peut être beaucoup plus rapide:

df = pd.DataFrame({'a': randn(1000), 'b': randn(1000),'N': randint(100, 1000, (1000)), 'x': 'x'})

%timeit [row.a * 2 for idx, row in df.iterrows()]
# => 10 loops, best of 3: 50.3 ms per loop

%timeit [row[1] * 2 for row in df.itertuples()]
# => 1000 loops, best of 3: 541 µs per loop
124
répondu e9t 2016-06-01 09:00:01

vous pouvez également utiliser df.apply() pour itérer sur les lignes et accéder à plusieurs colonnes pour une fonction.

docs: DataFrame.appliquer ()

def valuation_formula(x, y):
    return x * y * 0.5

df['price'] = df.apply(lambda row: valuation_formula(row['x'], row['y']), axis=1)
67
répondu cheekybastard 2015-06-01 06:24:44

vous pouvez utiliser le df.fonction iloc comme suit:

for i in range(0, len(df)):
    print df.iloc[i]['c1'], df.iloc[i]['c2']
53
répondu PJay 2016-11-07 09:09:10

je cherchais comment itérer sur les lignes et les colonnes et a fini ici ainsi:

for i, row in df.iterrows():
    for j, column in row.iteritems():
        print(column)
16
répondu Lucas B 2018-01-17 09:41:29

Utiliser itertuples() . Il est plus rapide que iterrows () :

for row in df.itertuples():
    print "c1 :",row.c1,"c2 :",row.c2
14
répondu Nurul Akter Towhid 2017-07-27 16:32:32

pour boucler toutes les lignes dans un dataframe vous pouvez utiliser:

for x in range(len(date_example.index)):
    print date_example['Date'].iloc[x]
12
répondu Pedro Lobito 2017-04-04 20:46:53

vous pouvez écrire votre propre itérateur qui implémente namedtuple

from collections import namedtuple

def myiter(d, cols=None):
    if cols is None:
        v = d.values.tolist()
        cols = d.columns.values.tolist()
    else:
        j = [d.columns.get_loc(c) for c in cols]
        v = d.values[:, j].tolist()

    n = namedtuple('MyTuple', cols)

    for line in iter(v):
        yield n(*line)

directement comparable à pd.DataFrame.itertuples . Je vise à accomplir la même tâche avec plus d'efficacité.


pour le dataframe donné avec ma fonction:

list(myiter(df))

[MyTuple(c1=10, c2=100), MyTuple(c1=11, c2=110), MyTuple(c1=12, c2=120)]

ou avec pd.DataFrame.itertuples :

list(df.itertuples(index=False))

[Pandas(c1=10, c2=100), Pandas(c1=11, c2=110), Pandas(c1=12, c2=120)]

un test complet

On essai de faire toutes les colonnes disponibles et. les colonnes.

def iterfullA(d):
    return list(myiter(d))

def iterfullB(d):
    return list(d.itertuples(index=False))

def itersubA(d):
    return list(myiter(d, ['col3', 'col4', 'col5', 'col6', 'col7']))

def itersubB(d):
    return list(d[['col3', 'col4', 'col5', 'col6', 'col7']].itertuples(index=False))

res = pd.DataFrame(
    index=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    columns='iterfullA iterfullB itersubA itersubB'.split(),
    dtype=float
)

for i in res.index:
    d = pd.DataFrame(np.random.randint(10, size=(i, 10))).add_prefix('col')
    for j in res.columns:
        stmt = '{}(d)'.format(j)
        setp = 'from __main__ import d, {}'.format(j)
        res.at[i, j] = timeit(stmt, setp, number=100)

res.groupby(res.columns.str[4:-1], axis=1).plot(loglog=True);

enter image description here

enter image description here

12
répondu piRSquared 2017-11-07 04:29:57

IMHO, la décision la plus simple

 for ind in df.index:
     print df['c1'][ind], df['c2'][ind]
8
répondu Grag2015 2017-11-02 10:33:40

pour boucler toutes les lignes dans un dataframe et utiliser les valeurs de chaque ligne commodément , namedtuples peuvent être converties en ndarray S. Par exemple:

df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])

Itération sur les lignes:

for row in df.itertuples(index=False, name='Pandas'):
    print np.asarray(row)

résultats dans:

[ 1.   0.1]
[ 2.   0.2]

veuillez noter que si index=True , l'indice est ajouté comme premier élément du tuple , qui peut être être indésirable pour certaines applications.

4
répondu KutalmisB 2018-04-24 08:48:05

Ajouter aux réponses ci-dessus, parfois un modèle utile est:

# Borrowing @KutalmisB df example
df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])
# The to_dict call results in a list of dicts
# where each row_dict is a dictionary with k:v pairs of columns:value for that row
for row_dict in df.to_dict(orient='records'):
    print(row_dict)

qui se traduit par:

{'col1':1.0, 'col2':0.1}
{'col1':2.0, 'col2':0.2}
3
répondu Zach 2018-06-27 18:48:28

pourquoi compliquer les choses?

Simple.

import pandas as pd
import numpy as np

# Here is an example dataframe
df_existing = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))

for idx,row in df_existing.iterrows():
    print row['A'],row['B'],row['C'],row['D']
2
répondu Justin Malinchak 2018-07-10 15:05:42

vous pouvez également faire numpy indexation pour des vitesses encore plus grandes. Ce n'est pas vraiment itératif mais fonctionne beaucoup mieux que l'itération pour certaines applications.

subset = row['c1'][0:5]
all = row['c1'][:]

vous pouvez aussi vouloir le lancer à un tableau. Ces index / sélections sont censés agir déjà comme des tableaux vides, mais j'ai rencontré des problèmes et j'ai dû lancer

np.asarray(all)
imgs[:] = cv2.resize(imgs[:], (224,224) ) #resize every image in an hdf5 file
1
répondu James L. 2017-12-01 18:22:38