Поиск по условию
Есть DataFrame:
price name
1 12.00100 'a'
2 12.00200 'h'
3 12.00300 'k'
4 12.00400 'o'
5 12.00500 'f'
6 12.00600 'y'
7 12.00700 'c'
8 12.00800 'y'
В индекс обычный int32, столбец price - float64, name - object или str.
Задача:
По условию, получить значение из столбца name, пример:
Допустим у нас есть значение 12,00122, мы должны найти, между какими значениями оно находиться. Очевидно, что оно находиться между строкой 1 и 2:
price name
1 12.00100 'a' <-
12.00122 <---------
2 12.00200 'h' <-
3 12.00300 'k'
4 12.00400 'o'
5 12.00500 'f'
6 12.00600 'y'
7 12.00700 'c'
8 12.00800 'y'
Перейдем к коду*:
df[
(df['price'] >= 12,10022) & (df['price'] <= 12,00022 + 0.00100),
inclusive='left'
]
* шаг цены в колонке price заранее известен и составляет 0,00100
Так как нам в итоге необходимо значение из колонки name, добавляем:
df[
(df['price'] >= 12,10022) & (df['price'] <= 12,00022 + 0.00100),
inclusive='left'
]['name']
И так как нам необходимо первое найденное значение, а функция нам вернет несколько (в данном случае 2шт) и мы это и прописали в условии inclusive='left', добавляем:
df[
(df['price'] >= 12,10022) & (df['price'] <= 12,00022 + 0.00100),
inclusive='left'
]['name'].values[0]
Собственно все работает хорошо, но очень долго, самое плохое, что значениях в колонке price не могут быть уменьшены знаки после запятой, что ускорило бы процесс поиска. В оригинальном датафрейме всего лишь 3к строк, но поиск составляет кучу времени.
Я так же испробовал другие варианты:
query-df.query('price > 12.00022 and price < 12.00022 + 0.00100')['name'].values[0]- дольше чем поиск описанный выше в 3 раза!!!between-df['price'].between(12.00022, 1200022 + 0.00100), inclusive='left')['name'].values[0]- самый быстрый поиск
Предложите пожалуйста свой вариант, может необходим совсем другой подход к решению данной задачи.
Ответы (1 шт):
Поскольку шаг известен и известно начальное значение с индексом 0, то вычислить место числа можно путем целочисленного деления на шаг.
df = pd.DataFrame({'price': [12.001, 12.002, 12.003, 12.004, 12.005, 12.006, 12.007, 12.008],
'name': ['a', 'h', 'k', 'o', 'f', 'y', 'c', 'y']})
print(df)
step = 0.001
num = 12.004012
idx = int((num - df.at[0, 'price']) // step)
print(f'Значение {num} находится между индексами {idx} и {idx + 1}')
price name
0 12.001 a
1 12.002 h
2 12.003 k
3 12.004 o
4 12.005 f
5 12.006 y
6 12.007 c
7 12.008 y
Значение 12.004012 находится между индексами 3 и 4