Pandas .loc возвращает серию или плавает непоследовательно

Я пишу некоторый код, и у меня возникли проблемы с неожиданным поведением при использовании .loc в DataFrame pandas, в зависимости от длины самого фрейма данных. Буду признателен за некоторые указания о том, что происходит и как избежать получения противоречивых результатов.

Прежде всего, я работаю с Python 3.11 и pandas версии 2.2.2. Проблема в том, что в зависимости от длины кадра данных .loc вернет серию из одного элемента или объект float64. Ниже реплика с придуманным мною фиктивным примером.

Во-первых, при рассмотрении более длинного кадра данных с мультииндексом возвращается серия с .loc.

df = pd.DataFrame.from_dict(
    {'ix1': ['asd', 'asd', 'asd', 'qwe', 'qwe', 'qwe', 'qwe', 'asd', 'qwe', 'asd', 'asd', 'qwe', 'asd', 'asd', 'asd', 'asd', 'qwe', 'qwe', 'qwe', 'qwe', 'asd', 'qwe', 'qwe', 'asd', 'qwe', 'qwe', 'qwe', 'asd', 'asd', 'asd', 'bar', 'qwe', 'qwe', 'asd', 'qwe', 'asd'],
     'ix2': ['sdf', 'bar', 'rty', 'fgh', 'cvb', 'cvb', 'vbn', 'bnm', 'jkl', 'ewq', 'uio', 'uio', 'wer', 'dsa', 'vbn', 'cxz', 'sdf', 'iuo', 'bar', 'bvc', 'fgh', 'rty', 'gfd', 'cvb', 'wer', 'bnm', 'ewq', 'tre', 'uyt', 'jhg', 'foo', 'dsa', 'mnb', 'jkl', 'iuy', 'lkj'],
     'value': [float(i) for i in range(1, 37)]})

>>> df[['ix1', 'ix2', 'value']].set_index(['ix1', 'ix2']).loc[('bar', 'foo'), 'value']
# <input>:1: PerformanceWarning: indexing past lexsort depth may impact performance.
# ix1  ix2
# bar  foo   31.00
# Name: value, dtype: float64

возвращает PerformanceWarning, поскольку индекс не отсортирован и серия имеет значение float64 (нежелательно)

Более короткий фрейм данных, та же структура, тот же индекс, та же выполняемая строка кода, возвращает вставленное число float64.

df = pd.DataFrame.from_dict(
    {'ix1': ['foo', 'foo', 'foo', 'foo', 'foo', 'foo', 'foo', 'bar'],
     'ix2': ['tyu', 'fgh', 'vbn', 'jkl', 'foo', 'asd', 'qwe', 'foo'],
     'value': [float(i) for i in range(1, 9)]})

>>> df[['ix1', 'ix2', 'value']].set_index(['ix1', 'ix2']).loc[('bar', 'foo'), 'value']
# np.float64(8.0)

Просто возвращает float64 (по желанию)

Это вызывает проблемы в дальнейшем в коде, поскольку мне нужны плавающие числа для выполнения некоторых вычислений, и я, похоже, не могу найти, что мне следует делать, чтобы генерировать согласованные выходные данные.

Вам не совсем понятен вопрос: всегда ли вам нужен поплавок?

mozway 23.08.2024 15:44

Я думаю, ОП указывает на тот факт, что аналогичный код возвращает разные результаты.

sammywemmy 23.08.2024 15:45

Я понимаю. Во втором примере в индексе нет повторяющихся комбинаций.

mozway 23.08.2024 15:47

справедливое замечание. pandas по-разному обрабатывает повторяющиеся и не повторяющиеся индексы. Вероятно, это есть в документации

sammywemmy 23.08.2024 15:49
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
4
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашем втором примере нет повторяющихся комбинаций ix1/ix2, что предотвращает проблему.

Если вам всегда нужен поплавок, я бы использовал:

cols = ['ix1', 'ix2']
df.drop_duplicates(cols).set_index(cols)['value'].loc[('bar', 'foo')]

Вывод: 31.0

Вы правы, заранее добавлю элемент управления, спасибо большое! - Я просмотрю документацию, чтобы узнать, является ли это ожидаемым поведением.

Dasi 23.08.2024 16:01

Другие вопросы по теме