Я пишу некоторый код, и у меня возникли проблемы с неожиданным поведением при использовании .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 (по желанию)
Это вызывает проблемы в дальнейшем в коде, поскольку мне нужны плавающие числа для выполнения некоторых вычислений, и я, похоже, не могу найти, что мне следует делать, чтобы генерировать согласованные выходные данные.
Я думаю, ОП указывает на тот факт, что аналогичный код возвращает разные результаты.
Я понимаю. Во втором примере в индексе нет повторяющихся комбинаций.
справедливое замечание. pandas по-разному обрабатывает повторяющиеся и не повторяющиеся индексы. Вероятно, это есть в документации






В вашем втором примере нет повторяющихся комбинаций ix1/ix2, что предотвращает проблему.
Если вам всегда нужен поплавок, я бы использовал:
cols = ['ix1', 'ix2']
df.drop_duplicates(cols).set_index(cols)['value'].loc[('bar', 'foo')]
Вывод: 31.0
Вы правы, заранее добавлю элемент управления, спасибо большое! - Я просмотрю документацию, чтобы узнать, является ли это ожидаемым поведением.
Вам не совсем понятен вопрос: всегда ли вам нужен поплавок?