поиск почти идентичных строк между фреймами данных

#r #dataframe #vectorization

#r #фрейм данных #векторизация

Вопрос:

У меня есть следующие два фрейма данных:

 df1 = data_frame(x = c(1128.4, 1101.2), y = c(124.5, 325.2)

df2 = data_frame(x = c(1128.7, 1100.5, 1527.8, 1347.5), y = c(83.2, 124.2, 
370.3, 325.5))
 

Я хотел бы найти строки в df1 , которые почти идентичны (разница в 1% в любом направлении) строкам в df2 , очень эффективным способом, чтобы иметь возможность делать это для сотен строк по df1 сравнению с гораздо большим df2 .

Ожидаемый результат будет, например, список:

 L$x = c(1,2)
L$y = c(2,4)
 

чтобы указать похожие строки в каждом столбце.

Если бы задание состояло в том, чтобы найти полностью идентичные строки, я бы использовал left_join , конечно, где меньший df1 будет слева.

Есть ли эффективный способ сделать это? (В общем, я хотел бы добиться этого и для нескольких столбцов).

Ответ №1:

с data.table помощью этого вы получите самое быстрое решение:

 library(data.table)
df1 = data.table(x = c(1128.4, 1101.2))
df2 = data.table(x = c(1128.7, 1100.5, 1527.8, 1347.5))

setkey(df2,x)
df2[,y := x]
df2[J(df1$x),roll = "nearest"][abs(x-y)/y < 0.01]

        x      y
1: 1128.4 1128.7
2: 1101.2 1100.5
 

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

1. Я не являюсь пользователем data.table; не могли бы вы объяснить логику того, почему (x-y) / y будет работать, а abs(x-y) / y — нет? Я ожидал бы обратного

Ответ №2:

Я не считаю, что это самый эффективный метод, но один из способов — использовать Map передачу df1 и df2 . Затем для каждого значения в df1 мы выбираем минимальный индекс абсолютной разницы в соответствующем значении в df2 .

 Map(function(x, y) sapply(x, function(i) which.min(abs(i - y))), df1, df2)

#$x
#[1] 1 2

#$y
#[1] 2 4
 

Для проверки условия 1%

 Map(function(x, y) sapply(x, function(i) {
    inds = abs(i - y)
    if (any(inds/y <= 0.01)) which.min(inds) else NA
}), df1, df2)