#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)