Панды сливаются рядом с входом

#python #pandas

Вопрос:

Панды merge_asof не оправдывают ожиданий….пример ниже:

 left = pd.DataFrame({'a': [5, 10], 'left_val': ['b', 'c']})

right = pd.DataFrame({'a': [3, 7], 'right_val': [6, 7]})

pd.merge_asof(left, right, on='a', direction='nearest')
 

Это дает:

       a left_val  right_val
0   5        b          6
1  10        c          7
 

Мои ожидания:

       a left_val  right_val
0   5        b          6
1   5        b          7
2  10        c          7
 

данные 3 и 7 равноудалены от 5…so мои ожидания.
Есть ли способ добиться этого?

ПРАВКА: В любом случае, чтобы достичь этого в подобных пандах, кроме как по состоянию на.

Комментарии:

1. asof выбирает ближайший/ближайший, а не диапазон. вы можете ознакомиться с документами для получения более подробной информации. вы, вероятно, имеете в виду неэквивалентные соединения, что не является тем, что делает asof

2. 3 ближе, чем 7, поэтому алгоритм выбирает строку для 3. двоичный поиск может помочь. В Pandas еще нет ни одной существующей функции для неэквивалентных соединений

3. взгляните на документы, чтобы понять обоснование.

4. @sammywemmy прав, но вы можете сделать это вручную. Проверьте мой ответ, если он соответствует вашим потребностям.

Ответ №1:

Используйте pd.merge с how='cross' для создания всех комбинаций из левого и правого фреймов данных и вычисления расстояния между a и a_right .

 out = pd.merge(left, right, how='cross', suffixes=('', '_right'))
out['dist'] = out['a'].sub(out['a_right']).abs()
 

В этот момент:

 >>> out
    a left_val  a_right  right_val  dist
0   5        b        3          6     2  # dist == dist.min() / group 5
1   5        b        7          7     2  # dist == dist.min() / group 5
2  10        c        3          6     7  # dist > dist.min()  / group 10
3  10        c        7          7     3  # dist == dist.min() / group 10
 

Держите ряды там, где dist == dist.min() :

 >>> out.loc[out.groupby('a')['dist'].apply(lambda d: d == d.min()),
            ['a', 'left_val', 'right_val']]

    a left_val  right_val
0   5        b          6
1   5        b          7
3  10        c          7