[Python] Comment itérer sur des lignes dans un DataFrame dans Pandas?


Answers

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
Question

J'ai un DataFrames 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 sur les lignes de l'image ci-dessus. Pour chaque ligne je veux pouvoir accéder à ses éléments (valeurs dans les cellules) par le nom des colonnes. Donc, par exemple, j'aimerais avoir quelque chose comme ça:

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

Est-il possible de le faire chez les pandas?

J'ai trouvé une question similaire . Mais cela 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.




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)

Ceci est directement comparable à pd.DataFrame.itertuples . Je vise à effectuer 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
Nous testons la mise à disposition de toutes les colonnes et la sous-sélection des 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);




Utilisez itertuples () . C'est plus rapide que iterrows () :

for row in df.itertuples():
    print "c1 :",row.c1,"c2 :",row.c2



Pour boucler toutes les lignes dans une base de dataframe et utiliser les valeurs de chaque ligne de façon pratique , les namedtuples peuvent être convertis en ndarray s. Par exemple:

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

Itérer sur les lignes:

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

résulte en:

[ 1.   0.1]
[ 2.   0.2]

Veuillez noter que si index=True , l'index est ajouté en tant que premier élément du tuple , ce qui peut être indésirable pour certaines applications.




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

DataFrame.apply()

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

df['price'] = df.apply(lambda row: valuation_formula(row['x'], row['y']), axis=1)



IMHO, la décision la plus simple

 for ind in df.index:
     print df['c1'][ind], df['c2'][ind]