Я часто переключаюсь между использованием атрибутов объекта dataframe для ссылки на столбцы, а также с использованием метода скобок.
Мне интересно, какой формат считается «наилучшей практикой», и есть ли какие-либо различия в производительности между ними (или это может потенциально варьироваться в зависимости от обстоятельств?). Я не нахожу много ресурсов по этому вопросу.
Вот упрощенный пример того, что я имею в виду: создание столбца «зеленый» со строками, имеющими значение «Истина», если столбцы «синий» и «желтый» имеют значение «Истина», в противном случае строки являются ложными.
# using brackets.
df['green'] = np.where((df['blue']==True) & (df['yellow']==True), True, False)
против.
# using periods.
df['green'] = np.where((df.blue==True) & (df.yellow == True), True, False)
Я часто использую последний, так как он выглядит чище, короче и его легче набирать. Однако я часто вижу примеры панд здесь и в других источниках, использующих оба метода.
См. также В чем разница между использованием квадратных скобок или точки для доступа к столбцу?
Между двумя нотациями нет разницы в производительности:
df.blue
использует __getattr__
для поиска в правом столбцеdf['blue']
использует __getitem__
для поиска нужного столбца (или индекса)У вас должен быть действительный идентификатор Python, если вы хотите использовать первую форму, и вы не можете использовать имя столбца, такое как shape
, size
, values
и так далее.
Вторая форма более явная и используется LocIndexer
. Это позволяет вам использовать имя столбца, например 2022
или Energy (KWH)
. Я явно предпочитаю это обозначение.
Если производительность имеет значение, не используйте where или аналогичную дорогостоящую функцию. Классическая маска подойдет. Использование timeit
может дать вам представление о затратах времени:
import pandas as pd
import numpy as np
n = 100
df = pd.DataFrame({'yellow' : np.random.randint(0, 2, n),
'blue' : np.random.randint(0, 2, n)}, dtype = np.bool8)
%timeit np.where((df['blue']==True) & (df['yellow']==True), True, False)
252 µs ± 17.3 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit np.where((df.blue==True) & (df.yellow == True), True, False)
245 µs ± 3.06 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit df['blue'] & df['yellow']
72.1 µs ± 4.6 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit df.blue & df.yellow
77.1 µs ± 1.75 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
С точки зрения производительности это вполне эквивалентно, и статически вы не можете различить два подхода. На самом деле, в дорогостоящей реализации (например, где) реальное узкое место не в том, как получить доступ к элементу.
Что касается синтаксиса, я предпочитаю использовать .loc или .iloc для доступа к элементам, так как я нахожу его более «пандовым», но это полностью на ваше усмотрение.
Самая распространенная проблема, которую я видел здесь: рассмотрим фрейм данных
df
со столбцамиdf['name']
иdf['shape']
. Сохранение 4 символов ввода приведет к тому, что В самом деле испортит вас, когда вы начнете устанавливать/изменять атрибутname
фрейма данных вместо внесения изменений в столбец'name'
или выдавать ошибки при попытке изменить поведениеdf.shape
по умолчанию. IMO всегда всегда используйте скобки для доступа к столбцу