Я пробовал функцию df.iterrows()
но ее производительность ужасна. Что неудивительно, учитывая, что iterrows()
возвращает Series
с полной схемой и метаданными, а не только значениями (которые мне нужны).
Второй метод, который я пробовал, - это for row in df.values
, который значительно быстрее. Однако недавно я понял, что df.values
не является внутренним хранилищем данных DataFrame, потому что df.values
преобразует все dtypes
в общий dtype
. Например, один из моих столбцов имеет dtype int64
но dtype для df.values
равен float64
. Поэтому я подозреваю, что df.values
самом деле создает еще одну копию внутренних данных.
Кроме того, еще одно требование состоит в том, что итерация строки должна возвращать список значений, сохраняющих исходный dtype
данных.
В Python перебор строк будет (намного) медленнее, чем выполнение векторизованных операций.
Типы преобразуются в вашем втором методе, потому что так работают массивы numpy (что и есть df.values
). DataFrames основаны на столбцах, поэтому у вас может быть один DataFrame с несколькими dtypes. Как только вы выполняете итерацию по строкам, все должно быть приведено к более общему типу, который содержит все. В вашем случае целые числа идут в float64
.
Если вы опишете свою проблему на минимальном рабочем примере, мы сможем помочь вам векторизовать ее. Вам также может повезти в StackOverflow с тегом pandas.
По сути, я хочу сделать следующее:
row_handler = RowHandler(sample_df) # learn how to handle row from sample data
transformed_data = []
for row in df.values:
transformed_data.append(row_handler.handle(row))
return transformed_data
Я не владею классом RowHandler
и, следовательно, могу работать только построчно.
Другой похожий пример - машинное обучение, где у вас может быть модель, которая имеет API прогнозирования только на уровне строки.
Все еще слишком расплывчато, чтобы быть полезным. Но если RowHandler
действительно выходит из-под вашего контроля, вам не повезло. FWIW: все API-интерфейсы scikit-learn работают с массивами (то есть с несколькими строками).
Не понимаю, как это может быть яснее. Да, RowHandler
вне моего контроля. Что вы имеете в виду под невезением? Мой вопрос заключается в наиболее эффективном способе перебора строк, сохраняя при этом dtype
каждого элемента. Вы предлагаете df.iterrows()
или что-то еще?
sklearn
- это исключение, а не норма, которое изначально работает с DataFrame
PD. Не во многих библиотеках машинного обучения есть API, которые работают с DataFrame
.
Я думаю, что df.itertuples()
- это то, что вы ищете - это намного быстрее, чем iterrows:
In [10]: x = pd.DataFrame({'x': range(10000)})
In [11]: %timeit list(x.iterrows())
1 loops, best of 3: 383 ms per loop
In [12]: %timeit list(x.itertuples())
1000 loops, best of 3: 1.39 ms per loop
Спасибо @shoyer! Это то что мне нужно.
Самый полезный комментарий
Я думаю, что
df.itertuples()
- это то, что вы ищете - это намного быстрее, чем iterrows: