У меня есть «DataFrame» от Pandas:
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» и как я могу с ним работать.
DataFrame.iterrows - это генератор, который дает как индекс, так и строку
import pandas as pd
import numpy as np
df = pd.DataFrame([{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}])
& Лт;!- >
for index, row in df.iterrows():
print(row['c1'], row['c2'])
Output:
10 100
11 110
12 120
Сначала подумайте, нужно ли вам iterate над строками в DataFrame. См. Этот ответ для альтернатив.
Если вам все еще нужно перерезать строки, вы можете использовать методы ниже. Обратите внимание на некоторые важные предостережения , которые не упоминаются ни в одном из других ответов.
для индекса строка в df.iterrows ():
строка печати ["c1"], строка ["c2"]
для строки в df.itertuples (index = True, name = 'Pandas'):
print getattr (row, "c1"), getattr (row, "c2")
itertuples ()
должен быть быстрее, чем iterrows ()
Но имейте в виду, согласно документам (панды 0.24.2 на данный момент):
dtype
может не совпадать из строки в строкуПоскольку итерроуз возвращает серию для каждой строки, он не сохраняет dtypes по строкам (dtypes сохраняются в столбцах для DataFrames). Чтобы сохранить dtypes при итерации над строками, лучше использовать itertuples (), который возвращает namedtuples значений и который обычно намного быстрее, чем iterrows ()
Вы должны никогда не изменять то, что вы повторяете. Это не гарантируется для работы во всех случаях. В зависимости от типов данных итератор возвращает копию, а не представление, и запись в нее не будет иметь никакого эффекта.
Вместо этого используйте DataFrame.apply ():
new_df = df.apply (лямбда x: x * 2)
Имена столбцов будут переименованы в позиционные имена, если они являются недействительными идентификаторами Python, повторяются или начинаются с подчеркивания. При большом количестве столбцов (> 255) возвращаются обычные кортежи.
См. Pandas docs on итерации для получения более подробной информации.
Как перебирать строки в DataFrame в Pandas?
Итерация в пандах - это анти-узор, и это то, что вы должны хотеть делать только тогда, когда исчерпали все возможные варианты. Вам не следует рассматривать возможность использования какой-либо функции с «iter» в ее имени для чего-либо более чем нескольких тысяч строк, иначе вам придется привыкнуть к лоту ожидания.
Хотите распечатать DataFrame? Используйте DataFrame.to_string ()
.
Вы хотите что-то вычислить? В этом случае поиск методов в этом порядке (список изменен с здесь):
for
)DataFrame.apply ()
: i) & nbsp; Сокращения, которые могут быть выполнены в cython, ii) Итерация в пространстве питона
5. DataFrame.itertuples ()
и [`iteritems () ](https://pandems.pydataDataFrame.iterrows ()
iterrows
и itertuples
(оба получают много голосов в ответах на этот вопрос) следует использовать в очень редких случаях, таких как создание объектов строк / nametuples для последовательной обработки, что действительно является единственной вещью, для которой эти функции полезны.
Обращение к власти Страница документов на итерации имеет огромное красное предупреждающее поле, в котором говорится:
Итерация через объекты панд, как правило, медленная. Во многих случаях итерация вручную по строкам не требуется [...].
Большое количество основных операций и вычислений «векторизируется» пандами (либо через NumPy, либо через Cythonized функции). Это включает в себя арифметику, сравнения, (большинство) сокращений, изменение формы (например, поворот), соединения и групповые операции. Просмотрите документацию по Основная базовая функциональность, чтобы найти подходящий векторизованный метод для вашей проблемы.
Если их нет, не стесняйтесь писать свои собственные с помощью пользовательских расширений cython. ).
Список понятий должен стать вашим следующим портом захода, если 1) нет доступного векторизованного решения, 2) важна производительность, но она недостаточно важна, чтобы справиться с трудностями при шифровании вашего кода, и 3) вы пытаетесь выполнить элементное преобразование на ваш код. Существует хорошее количество доказательств, чтобы предположить, что состав списка достаточно быстрый (и даже иногда быстрее) для многих распространенных задач панд.
Формула проста
# 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]
Если вы можете заключить свою бизнес-логику в функцию, вы можете использовать понимание списка, которое вызывает ее. Вы можете заставить произвольно сложные вещи работать благодаря простоте и скорости сырого питона.
Давайте продемонстрируем разницу простым примером добавления двух столбцов панд A + B
. Это векторизованный оператон, поэтому будет легко сопоставить производительность методов, рассмотренных выше.
Закладка кода, для вашей ссылки.
Я должен упомянуть, однако, что это не всегда так сухо. Иногда ответ «какой метод лучше для операции» - «это зависит от ваших данных». Мой совет - проверить различные подходы к вашим данным, прежде чем остановиться на них.
10 минут до панд и [Essential Basic Functionality](https://pandas.pydata.org/pandas-docs/stable/getting_started/bas youxy vector.
Повышение производительности - учебник для начинающих из документов по улучшению стандартных операций панд
https://stackoverflow.com/questions/54028199/for-loops-with-pandas-when-should-i-care - подробная запись мной о списках и их пригодности для различных операций (в основном, с не числовыми данные)
https://stackoverflow.com/questions/54432583/when-should-i-ever-want-to-use-pandas-apply-in-my-code - «применить» происходит медленно (но теперь так же медленно, как iter *
семейство. Однако существуют ситуации, когда можно (или следует) рассматривать «применять» в качестве альтернативы серии, особенно в некоторых операциях «GroupBy»).
* Строковые методы панд «векторизированы» в том смысле, что они указаны в серии, но работают с каждым элементом. Базовые механизмы все еще итеративны, потому что строковые операции по своей природе трудно векторизовать.& Лт; / sub >
Вы должны использовать df.iterrows ()
. Хотя итерация построчно не особенно эффективна, поскольку необходимо создавать объекты серии.
Хотя 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
Вы также можете использовать df.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)
Вы можете написать свой собственный итератор, который реализует 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);
for ind in df.index:
print df['c1'][ind], df['c2'][ind]
Чтобы зацикливать все строки в dataframe
, вы можете использовать:
for x in range(len(date_example.index)):
print date_example['Date'].iloc[x]
Иногда полезный шаблон:
# 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}
Чтобы зациклить все строки в значениях dataframe
и каждой строки удобно , namedtuples
можно преобразовать в ndarray
s. Например:
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
, индекс добавляется в качестве первого элемента кортежа , что может быть нежелательным для некоторых приложений.
Для просмотра и изменения значений я бы использовал iterrows ()
. В цикле for и с помощью распаковки кортежей (см. Пример: i, строка
) я использую row
только для просмотра значения и использую i
с методом loc
, когда хочу изменить значения ,. Как указывалось в предыдущих ответах, здесь вы не должны изменять то, что вы повторяете.
для i ряд в df.iterrows ():
if row ['A'] == 'Old_Value':
df.loc [i, 'A'] = 'New_value'
Здесь row
в цикле является копией этой строки, а не ее представлением. Поэтому вы НЕ должны писать что-то вроде row ['A'] = 'New_Value'
, это не изменит DataFrame. Однако вы можете использовать i
и loc
и указать DataFrame для выполнения работы.
Есть способ перебить броски строк при получении взамен DataFrame, а не Series. Я не вижу, чтобы кто-то упоминал, что вы можете передать индекс как список для строки, которая будет возвращена как DataFrame:
for i in range(len(df)):
row = df.iloc[[i]]
Обратите внимание на использование двойных скобок. Это возвращает DataFrame с одной строкой.
Вы также можете сделать 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
Есть так много способов перебить строки в рамке данных pandas. Один очень простой и интуитивный способ:
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]])
В этом примере используется 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])