#python #pandas
Вопрос:
df = pd.DataFrame({
'Product': ['Umbrella', 'Matress', 'Badminton',
'Shuttle', 'Sofa', 'Football'],
'MRP': [1200, 1500, 1600, 352, 5000, 500],
'Discount': [0, 10, 0, 10, 20, 40]
})
# Print the dataframe
print(df)
df.loc[df.MRP >= 1500, "Discount"] = -1
print(df)
Я хочу понять, как loc
это работает. Цель loc
состоит в том, чтобы получить строку с помощью поиска по меткам. Но в приведенном выше коде, похоже, выполняется итерация по каждой строке и вставка -1 в новый столбец, где логическое значение истинно? Выполняет ли он поиск по меткам?
Комментарии:
1. Вместо того, чтобы гадать, распечатайте
df.MRP >= 1500
2. Я ни о чем не догадываюсь — я хочу понять, как работает loc, когда он предназначен для поиска по значению индекса, а не по позиции
3. Он выполняет поиск по значению индекса, когда это возможно, и логическому, когда нет. Это задокументировано довольно тщательно. Вы читали документы для
loc
этого ?
Ответ №1:
Единственной «реальной» индексацией в фрейме данных являются позиционные индексы (0 индексированных значений, соответствующих базовым структурам).
loc
Поэтому всегда приходится «Преобразовывать ключ на основе потенциальной метки в позиционный индексатор». _get_setitem_indexer.
Выходя из — под капюшона, документы о пандах.DataFrame.loc явно разрешает:
- Одна метка, например, 5 или «a» (обратите внимание, что 5 интерпретируется как метка индекса, а не как целочисленная позиция вдоль индекса).
- Список или массив меток, например [‘a’, ‘b’, ‘c’].
- Объект среза с метками, например «a»:»f».
- Логический массив той же длины, что и разрезаемая ось, например [True, False, True].
- Выравниваемый логический ряд. Индекс ключа будет выровнен перед маскировкой.
- Выравниваемый Индекс. Входным будет индекс возвращенного выбора.
- Вызываемая функция с одним аргументом (вызывающий ряд или фрейм данных), которая возвращает допустимые выходные данные для индексирования (один из вышеперечисленных).
Преимущество loc
заключается в том, что он чрезвычайно гибок, особенно с точки зрения возможности увязывать это с другими операциями:
Видеть:
df.groupby('Discount')['MRP'].agg(sum)
Discount
0 2800
10 1852
20 5000
40 500
Name: MRP, dtype: int64
Фильтрация этого с Series.loc
помощью может быть записана как:
df.groupby('Discount')['MRP'].agg(sum).loc[lambda s: s >= 1500]
Discount
0 2800
10 1852
20 5000
Name: MRP, dtype: int64
Еще одним огромным преимуществом loc
является его способность индексировать оба измерения:
df.loc[df['MRP'] >= 1500, ['Product', 'Discount']] = np.nan
Product MRP Discount
0 Umbrella 1200 0.0
1 NaN 1500 NaN
2 NaN 1600 NaN
3 Shuttle 352 10.0
4 NaN 5000 NaN
5 Football 500 40.0
TLDR; Сила loc
заключается в его способности преобразовывать различные входные данные в позиционные входные данные, в то время как недостатком являются накладные расходы на эти преобразования.
Ответ №2:
Первая строка документации для DataFrame.loc
государств:
Доступ к группе строк и столбцов осуществляется с помощью меток или логического массива.
.loc[]
в основном основан на метках, но также может использоваться с логическим массивом
Давайте взглянем на это выражение df.MRP >= 1500
. Это логический ряд с тем же индексом, что и фрейм данных:
>>> df.MRP >= 1500
0 False
1 True
2 True
3 False
4 True
5 False
Name: MRP, dtype: bool
Так что очевидно, что по крайней мере есть возможность сопоставить этикетки. Что происходит, когда вы удаляете этикетки?
>>> df.loc[(df.MRP >= 1500).to_numpy(), "Discount"]
1 10
2 0
4 20
Name: Discount, dtype: int64
Поэтому .loc
будет использоваться порядок кадра данных, когда метки недоступны. В этом есть смысл. Но использует ли он порядок или метки, когда метки не совпадают?
Сделайте серию, похожую df.MRP >= 1500
, но не по порядку, чтобы увидеть, что будет выбрано:
>>> ind1 = pd.Series([True, True, True, False, False, False], index=[1, 2, 4, 0, 3, 5])
>>> df.loc[ind1, "Discount"]
1 10
2 0
4 20
Name: Discount, dtype: int64
Так ясно, когда происходит сопоставление доступных меток. Когда он недоступен, вместо него используется заказ:
>>> df.loc[ind1.to_numpy(), "Discount"]
0 0
1 10
2 0
Name: Discount, dtype: int64
Еще один интересный момент заключается в том, что метки выражения индекса должны быть надмножеством, а не подмножеством индекса фрейма данных. Например, если вы сократите ind
на один элемент, вот что произойдет:
>>> ind2 = pd.Series([True, True, True, False, False], index=[1, 2, 4, 0, 3])
>>> df.loc[ind2, "Discount"]
...
IndexingError: Unalignable boolean Series provided as indexer (index of the boolean Series and of the indexed object do not match).
и
>>> df.loc[ind2.to_numpy(), "Discount"]
...
IndexError: Boolean index has wrong length: 5 instead of 6
Однако добавление дополнительного элемента при сопоставлении меток допустимо:
>>> ind3 = pd.Series([True, True, True, False, False, False, True], index=[1, 2, 4, 0, 3, 5, 6])
>>> df.loc[ind3, "Discount"]
1 10
2 0
4 20
Name: Discount, dtype: int64
Обратите внимание , что элемент в индексе 6
, которого нет в кадре данных, игнорируется в выходных данных.
И, конечно, без меток более длинные массивы также неприемлемы:
>>> df.loc[ind3.to_numpy(), "Discount"]
...
IndexError: Boolean index has wrong length: 7 instead of 6