[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 é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)



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);




IMHO, la décision la plus simple

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



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.




Links