Лучшие практики для индексации с пандами - PullRequest
0 голосов
/ 03 июня 2018

Я хочу выбрать строки на основе маски, idx.Я могу придумать две разные возможности: либо iloc, либо просто скобки.Я показал две возможности (на фрейме данных df) ниже.Они оба одинаково жизнеспособны?

idx = (df["timestamp"] >= 5) & (df["timestamp"] <= 10)
idx = idx.values
hr = df["hr"].iloc[idx]
timestamps = df["timestamp"].iloc[idx]

или следующие:

idx = (df["timestamp"] >= 5) & (df["timestamp"] <= 10)
hr = df["hr"][idx]
timestamps = df["timestamp"][idx]

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Не смешивайте индексирование __getitem__ и (i) loc.Используйте один или другой.Я предпочитаю (i) loc, когда вы осуществляете доступ по индексу, и __getitem__, когда вы осуществляете доступ по столбцу или используете логическое индексирование.

Вот некоторые обычно плохие методы индексации и соответствующие исправления.

df.iloc[idx].loc[:, column]  
df.iloc[idx][column]      
df[column][idx]           
df[column].iloc[idx]      

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

Правильным решением для всех этих версий является df.iloc[idx, df.columns.get_loc(column)] Обратите внимание, что idx - это массив целочисленных индексов, а column - строковая метка.Аналогично для loc.

Если у вас есть массив логических значений, используйте взамен loc, например: df.loc[boolean_idx, column]

Кроме того, все в порядке: df[column] и df[boolean_mask]

Существуют правила для индексации одной строки или одного столбца.В зависимости от того, как это будет сделано, вы получите либо Series, либо DataFrame.Итак, если вы хотите проиндексировать сотую строку из DataFrame df как срез DataFrame, вам нужно сделать:

df.iloc[[100], :]  # `:` selects every column

А не

df.iloc[100, :]

И аналогично дляИндексирование на основе столбцов.

Наконец, если вы хотите проиндексировать один скаляр, используйте at или iat.


OTOH, для вашего требования я бы предложил третью альтернативу:

ts = df.loc[df.timestamp.between(5, 10), 'timestamp']

Или, если вы все подмножество,

df = df[df.timestamp.between(5, 10)]
0 голосов
/ 03 июня 2018

Нет, они не одинаковы.Один использует прямой синтаксис, в то время как другой полагается на цепную индексацию.

Важными моментами являются:

  • pd.DataFrame.iloc используется в основном для целочисленной индексации на основе позиции.
  • pd.DataFrame.loc чаще всего используется с метками или логическими массивами.
  • Цепная индексация, т. Е. Через df[x][y], явно не рекомендуется и никогда не требуется.
  • idx.values возвращает представление массива numpy серии idx.Это не может кормить .iloc и не является обязательным для подачи .loc, что может принимать idx напрямую.

Ниже приведены два примера, которые будут работать.В любом из примеров вы можете использовать похожий синтаксис для маскирования кадра данных или серии.Например, df['hr'].loc[mask] будет работать так же, как и df.loc[mask].

iloc

Здесь мы используем numpy.where для извлечения целочисленных индексов True элементов в логическом ряду.iloc принимает булевы массивы, но, на мой взгляд, это менее очевидно;«i» означает целое число.

idx = (df['timestamp'] >= 5) & (df['timestamp'] <= 10)
mask = np.where(idx)[0]
df = df.iloc[mask]

loc

Использование loc более естественно, когда мы уже запрашиваем определенные серии.

mask = (df['timestamp'] >= 5) & (df['timestamp'] <= 10)
df = df.loc[mask]
  • Когда вы маскируете только строки, вы можете вообще пропустить аксессор loc и использовать df[mask].
  • Если вы маскируете по строкам и фильтруете по столбцу, вы можете использовать df.loc[mask, 'col_name']

Индексирование и выбор данных является основополагающим для pandas: нет никакой замены для чтения официальной документации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...