53

I am iterating over a pandas dataframe using itertuples. I also want to capture the row number while iterating:

for row in df.itertuples():
    print row['name']

Expected output :

1 larry
2 barry
3 michael

1, 2, 3 are row numbers. I want to avoid using a counter and getting the row number. Is there an easy way to achieve this using pandas?

rfkortekaas
  • 6,049
  • 2
  • 27
  • 34
Sun
  • 1,855
  • 5
  • 21
  • 26
  • Refusing to use `enumerate` - a common pattern in Python for these cases - seems weird. I would use it. Otherwise `df.reset_index()` will bring a 0 based index so the row number will be the index you iterate for a given line +1 – Zeugma Apr 05 '17 at 03:28
  • 1
    You should use `iterrows` like [in this SO post](http://stackoverflow.com/a/16476974/1478290) – Cheng Apr 05 '17 at 05:00
  • @Boud where does it say they refuse to use enumerate? – lucid_dreamer Apr 16 '18 at 00:07
  • Does this answer your question? [What is the most efficient way to loop through dataframes with pandas?](https://stackoverflow.com/questions/7837722/what-is-the-most-efficient-way-to-loop-through-dataframes-with-pandas) – Abu Shoeb Jan 04 '21 at 18:16
  • 2
    @Cheng the issue with iterrows is that dtypes may not be consistently maintained across rows. This can be very problematic. – lb_so Jun 07 '21 at 23:50

3 Answers3

72

When using itertuples you get a named tuple for every row. By default, you can access the index value for that row with row.Index.

If the index value isn't what you were looking for then you can use enumerate

for i, row in enumerate(df.itertuples(), 1):
    print(i, row.name)

enumerate takes the place of an ugly counter construct

piRSquared
  • 285,575
  • 57
  • 475
  • 624
34
for row in df.itertuples():
    print(getattr(row, 'Index'), getattr(row, 'name'))
12

For column names that aren't valid Python names, use:

for i, row in enumerate(df.itertuples(index=False)):
    print(str(i) + row[df.columns.get_loc('My nasty - column / name')])

If you don't specify index=False, the column before the one named will be read.

Chris
  • 5,664
  • 6
  • 44
  • 55