Поиск по условию

Есть 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к строк, но поиск составляет кучу времени.

Я так же испробовал другие варианты:

  1. query - df.query('price > 12.00022 and price < 12.00022 + 0.00100')['name'].values[0] - дольше чем поиск описанный выше в 3 раза!!!

  2. 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
→ Ссылка