Объединить фреймы данных на основе координат, не имеющих общих столбцов

ВХОД :

df1

Pg  x0      y0      x1      y1      Text
1   521.3   745.92  537.348 754.097 word1
1   538.982 745.92  580.247 754.097 word2
1   527.978 735.253 572.996 747.727 word3
2   268.985 732.36  341.59  746.636 word4
2   344.443 732.36  390.175 746.636 word5

df2

Pg  x0      y0      x1      y1      Text                T   R   C
1   507.6   730.8   593.76  754.8   word1 word2 word3   1   1   2
2   334.56  732.36  401.34  746.636 word5               2   3   1

Ожидаемый ВЫХОД:

Pg  x0      y0      x1      y1      Text    T   R   C
1   521.3   745.92  537.348 754.097 word1   1   1   2
1   538.982 745.92  580.247 754.097 word2   1   1   2
1   527.978 735.253 572.996 747.727 word3   1   1   2
2   268.985 732.36  341.59  746.636 word4           
2   344.443 732.36  390.175 746.636 word5   2   3   1

Мне нужно найти, какие все слова в df1 присутствуют в df2 на основе координат (перекрытия) и подхода на основе не текст. После этого мне нужно скопировать значения столбцов [T, R, C] из df2 в df1.

Например: первая строка df2 имеет координаты, которые перекрывают координаты word1, word2, word3 df1. Перекрытие здесь означает, что bbox (x0, y0, x1, y1) строки в df1 должен находиться внутри bbox (x0, y0, x1, y1) определенной строки df2.

Мой подход:

Я повторяю каждую строку в df2, а затем сравниваю координату каждой строки из df1, чтобы найти любые перекрытия, а затем объединяю фреймы данных.

for i, r in df2.iterrows():
    df1.loc[
                (df1.x0 >= r.x0) &
                (df1.y0 >= r.y0) &
                (df1.x1 <= r.x1) &
                (df1.y1 <= r.y1) , 'flag'] = 1

    df1.loc[df.flag == 1, ['T', 'R', 'C']] = r.T, r.R, r.C

Проблема в том, что весь процесс работает должным образом, но требует много времени для выполнения. Для запуска df1 = 20 000 строк и df2 = 3500 строк требуется около 90 seconds.

Можете ли вы опубликовать свой рабочий код, объединяющий фреймы данных, чтобы мы могли дать конкретные рекомендации по его улучшению?

Michael 12.11.2018 16:03
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
65
1

Ответы 1

Можно использовать apply и маскировку. Пример:

def compare(row):
    mask = df2[
        (df2['x0'] <= row['x0']) &
        (df2['x1'] >= row['x1']) &
        (df2['y0'] <= row['y0']) &
        (df2['y1'] >= row['y1'])
    ]
    if mask.empty:
        return row
    row['T'] = mask['T'].tolist()[0]
    row['R'] = mask['R'].tolist()[0]
    row['C'] = mask['C'].tolist()[0]

return row

result = df1.apply(compare, axis=1)

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