Question Comment itérer sur des lignes dans un DataFrame dans Pandas?


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é 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 que le row objet est et comment je peux travailler avec.


758
2018-05-10 07:04


origine


Réponses:


iterrows est un générateur qui donne à la fois l'index et la rangée

In [18]: for index, row in df.iterrows():
   ....:     print row['c1'], row['c2']
   ....:     
10 100
11 110
12 120

1092
2018-05-10 07:07



Pour parcourir la rangée de DataFrame dans les pandas, on peut utiliser:

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

Mais sachez, selon les docs (pandas 0.21.1 pour le moment):

  • iterrows: dtype peut ne pas correspondre d'une ligne à l'autre

    Parce que iterrows renvoie une série pour chaque ligne, ne conserve pas dtypes à travers les lignes (dtypes sont conservés à travers les colonnes pour DataFrames).

  • Iterrows: Ne pas modifier les lignes

    Vous devriez ne jamais modifier quelque chose que vous êtes en train de répéter. Ce n'est pas garanti de fonctionner dans tous les cas. Selon les types de données, l'itérateur renvoie une copie et non une vue, et l'écriture n'a aucun effet.

    Utilisation DataFrame.apply () au lieu:

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

    Les noms de colonnes seront renommés en noms de position s'ils sont des identifiants Python non valides, répétés ou commencent par un trait de soulignement. Avec un grand nombre de colonnes (> 255), les tuples réguliers sont retournés.


140
2017-12-07 16:41



Tandis 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

115
2017-09-20 13:52



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

docs: 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)

61
2018-06-01 06:24



Vous pouvez utiliser la fonction df.iloc comme suit:

for i in range(0, len(df)):
    print df.iloc[i]['c1'], df.iloc[i]['c2']

42
2017-09-07 12:56



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

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

13
2017-07-27 16:32



je cherchais Comment itérer sur les lignes et les colonnes et terminé ici:

for i, row in df.iterrows():
    for j, column in row.iteritems():
        print(column)

11
2018-01-17 09:41



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]

10
2018-03-11 22:44



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

enter image description here

enter image description here


10
2017-11-07 04:15



IMHO, la décision la plus simple

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

6
2017-11-02 10:33