it-swarm.com.ru

Как перебирать строки в DataFrame в Pandas?

У меня есть DataFrame от панд:

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

Результат:

   c1   c2
0  10  100
1  11  110
2  12  120

Теперь я хочу перебрать строки этого кадра. Для каждой строки я хочу иметь возможность доступа к ее элементам (значениям в ячейках) по имени столбцов. Например:

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

Возможно ли это сделать в пандах?

Я нашел это аналогичный вопрос . Но это не дает мне ответ, который мне нужен. Например, там предлагается использовать:

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

или же

for row in df.iterrows():

Но я не понимаю, что такое объект row и как я могу с ним работать.

1254
Roman

DataFrame.iterrows - это генератор, который выдает как индекс, так и строку

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

Output: 
   10 100
   11 110
   12 120
1773
waitingkuo

Сначала рассмотрим, нужно ли вам выполнять итерацию по строкам в DataFrame. Смотрите этот ответ для альтернатив.

Если вам все еще нужно перебирать строки, вы можете использовать методы ниже. Обратите внимание на некоторые важные предупреждения , которые не упомянуты ни в одном из других ответов.

itertuples() должен быть быстрее, чем iterrows()

Но имейте в виду, согласно документам (панды 0.24.2 на данный момент):

  • iterrows: dtype может не совпадать от строки к строке

    Поскольку iterrows возвращает Series для каждой строки, он не сохраняет dtypes в строках (dtypes сохраняются в столбцах для DataFrames). Чтобы сохранить dtypes при выполнении итераций по строкам, лучше использовать itertuples (), которая возвращает именованные кортежи значений и, как правило, намного быстрее, чем iterrows ()

  • iterrows: не изменять строки

    Вы не должны изменять то, что вы повторяете. Это не гарантирует работу во всех случаях. В зависимости от типов данных итератор возвращает копию, а не представление, и запись в него не будет иметь никакого эффекта.

    Используйте DataFrame.apply () вместо:

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

    Имена столбцов будут переименованы в позиционные имена, если они являются недопустимыми идентификаторами Python, повторяются или начинаются с подчеркивания. При большом количестве столбцов (> 255) возвращаются обычные кортежи.

Смотрите pandas docs на итерации для более подробной информации.

273
viddik13

Вы должны использовать df.iterrows() . Хотя итерация строка за строкой не особенно эффективна, поскольку нужно создавать объекты Series.

184
Wes McKinney

Хотя iterrows() является хорошим вариантом, иногда itertuples() может быть намного быстрее:

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
140
e9t

Вы также можете использовать df.apply() для перебора строк и доступа к нескольким столбцам для функции.

документы: 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)
77
cheekybastard

Вы можете использовать функцию df.iloc следующим образом:

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

Как перебирать строки в DataFrame в Pandas?

Ответ: НЕ!

Итерация в pandas является анти-паттерном, и вам следует делать это только тогда, когда вы исчерпали все возможные варианты. Вам не следует использовать какую-либо функцию с именем "iter" для чего-либо более нескольких тысяч строк, иначе вам придется привыкнуть к лоту ожидания.

Вы хотите распечатать DataFrame? Используйте DataFrame.to_string() .

Вы хотите что-то вычислить? В этом случае ищите методы в следующем порядке (список изменен из здесь ):

  1. Векторизация
  2. Подпрограммы Cython
  3. Понимание списка (цикл Vanilla for)
  4. DataFrame.apply() : i) сокращения, которые могут быть выполнены в cython, ii) итерация в пространстве python
  5. DataFrame.itertuples() и iteritems()
  6. DataFrame.iterrows()

iterrows и itertuples (оба получают много голосов в ответах на этот вопрос) должны использоваться в очень редких случаях, таких как генерация объектов строк/именных имен для последовательной обработки, что действительно единственное, для чего эти функции полезны.

Обращение к власти
Страница документов на итерации имеет огромное красное окно с предупреждением:

Итерация по объектам pandas обычно выполняется медленно. Во многих случаях повторение вручную по строкам не требуется [...].


Быстрее, чем зацикливание: Векторизация , Cython

Большое количество базовых операций и вычислений "векторизовано" pandas (либо через NumPy, либо через функции Cythonized). Это включает в себя арифметику, сравнения, (большинство) сокращений, изменение формы (например, поворот), объединений и групповых операций. Просмотрите документацию по Essential Basic Functionality , чтобы найти подходящий векторизованный метод для вашей проблемы.

Если ничего не существует, не стесняйтесь писать свои собственные, используя custom расширения cython .


Следующая лучшая вещь: список понятий

Следующее понимание списка должно быть вашим следующим портом захода, если 1) нет доступного векторизованного решения, 2) производительность важна, но недостаточно важна для того, чтобы пройти через процесс кефонизации вашего кода, и 3) вы пытаетесь выполнить поэлементное преобразование в вашем коде. Существует достаточное количество доказательств , позволяющее предположить, что составление списков является достаточно быстрым (и даже иногда более быстрым) для многих распространенных pandas задач.

Формула проста,

# iterating over one column - `f` is some function that processes your data
result = [f(x) for x in df['col']]
# iterating over two columns, use `Zip`
result = [f(x, y) for x, y in Zip(df['col1'], df['col2'])]
# iterating over multiple columns
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].values]

Если вы можете инкапсулировать свою бизнес-логику в функцию, вы можете использовать понимание списка, которое ее вызывает. Вы можете заставить произвольно сложные вещи работать благодаря простоте и скорости необработанного Python.


Очевидный пример

Продемонстрируем разницу на простом примере добавления двух столбцов pandas A + B. Это векторизованный оперон, поэтому будет легко сравнить производительность методов, описанных выше.

enter image description here

контрольный код, для вашей справки.

Я должен отметить, однако, что это не всегда так сухо. Иногда ответ "что является лучшим методом для операции" - "это зависит от ваших данных". Мой совет - проверить различные подходы к вашим данным, прежде чем остановиться на одном.


Рекомендации

* Pandas строковые методы "векторизованы" в том смысле, что они указаны в серии, но работают с каждым элементом. Базовые механизмы все еще итеративны, потому что строковые операции по своей природе трудно векторизовать.

53
cs95

Я искал Как перебирать строки и столбцы и закончил вот так:

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

Вы можете написать свой собственный итератор, который реализует 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)

Это прямо сопоставимо с pd.DataFrame.itertuples. Я стремлюсь выполнить ту же задачу с большей эффективностью.


Для данного кадра данных с моей функцией:

list(myiter(df))

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

Или с pd.DataFrame.itertuples:

list(df.itertuples(index=False))

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

Комплексный тест
Мы тестируем доступность всех столбцов и подмножество столбцов.

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

15
piRSquared

Чтобы зациклить все строки в dataframe, вы можете использовать:

for x in range(len(date_example.index)):
    print date_example['Date'].iloc[x]
13
Pedro Lobito
 for ind in df.index:
     print df['c1'][ind], df['c2'][ind]
12
Grag2015

Иногда полезный шаблон:

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

Что приводит к:

{'col1':1.0, 'col2':0.1}
{'col1':2.0, 'col2':0.2}
7
Zach

Чтобы зациклить все строки в значениях dataframe и использовать каждой строки удобно, namedtuples можно преобразовать в ndarrays. Например:

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

Итерация по строкам:

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

результаты в:

[ 1.   0.1]
[ 2.   0.2]

Обратите внимание, что если index=True, индекс добавляется как первый элемент кортежа, что может быть нежелательно для некоторых приложений.

6
KutalmisB

Вы также можете выполнять индексирование numpy для еще большего ускорения. На самом деле это не итерация, но она работает намного лучше, чем итерация для определенных приложений.

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

Вы также можете привести его к массиву. Предполагается, что эти индексы/выборки уже действуют как массивы Numpy, но я столкнулся с проблемами и должен был разыграть

np.asarray(all)
imgs[:] = cv2.resize(imgs[:], (224,224) ) #resize every image in an hdf5 file
1
James L.

Зачем все усложнять?

Просто.

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']
1
Justin Malinchak

В этом примере iloc используется для выделения каждой цифры в кадре данных.

import pandas as pd

 a = [1, 2, 3, 4]
 b = [5, 6, 7, 8]

 mjr = pd.DataFrame({'a':a, 'b':b})

 size = mjr.shape

 for i in range(size[0]):
     for j in range(size[1]):
         print(mjr.iloc[i, j])
1
mjr2000

Существует так много способов перебора строк в pandas dataframe. Один очень простой и интуитивно понятный способ:

df=pd.DataFrame({'A':[1,2,3], 'B':[4,5,6],'C':[7,8,9]})
print(df)
for i in range(df.shape[0]):
    # For printing the second column
    print(df.iloc[i,1])
    # For printing more than one columns
    print(df.iloc[i,[0,2]])
1
shubham ranjan

И для просмотра, и для изменения значений я бы использовал iterrows(). В цикле for и с помощью распаковки Tuple (см. Пример: i, row) я использую row только для просмотра значения и использую i с методом loc, когда я хочу изменить значения. Как указано в предыдущих ответах, здесь вы не должны изменять то, что вы повторяете.

for i, row in df.iterrows():
    if row['A'] == 'Old_Value':
        df.loc[i,'A'] = 'New_value'  

Здесь row в цикле является копией этой строки, а не ее представлением. Следовательно, вы НЕ должны писать что-то вроде row['A'] = 'New_Value', это не изменит DataFrame. Однако вы можете использовать i и loc и указать DataFrame для выполнения этой работы.

0
HKRC