найти значения ближайшей пары из другого фрейма данных при условии группы в r - PullRequest
0 голосов
/ 02 мая 2019

У меня есть два фрейма данных, df1 и df2:

df1 = read.table(text="group    value
    A   24163
    A   80991
    A   81014
    A   81352
    A   81353
    A   81367
    A   81368
    B   71721
    B   76038
    B   113186
    B   126732
    B   126748
    B   155556", header=T, stringsAsFactors=F)

    df2 = read.table(text="group    value
    A   30000
    A   40000
    A   81360
    B   75000
    B   90000
    B   130000", header=T, stringsAsFactors=F)

Я хочу найти ближайшую пару значений для каждого из df2$value из df1$value в той же группе.одно из них является ближайшим значением в df1$value меньше значения в df2$value, другое - ближайшим значением в значении df1 $ больше, чем значение в df2$value в той же группе.Итак, ожидаемый результат:

    df = read.table(text="group value   low high
    A   30000   24163   80991
    A   40000   24163   80991
    A   81360   81353   81367
    B   75000   71721   76038
    B   90000   76038   113186
    B   130000  126748  155556", header=T, stringsAsFactors=F)

Я бы хотел найти решение без зацикливания.

1 Ответ

0 голосов
/ 02 мая 2019

Слияние df2 с df1 на group дает все возможные комбинации -

x = merge(df2, df1, all.x = TRUE, by = "group")

Тогда совпадения могут характеризоваться разностью и направлением (выше или ниже) -

x$diff = x$value.x - x$value.y
x$type = ifelse(x$diff < 0, "high", "low")

Упорядочение по абсолютная разница и удаление дубликатов по «направлению» сохраняет только самые близкие значения «максимум» и «минимум» -

x = x[order(x$group, abs(x$diff)), ]
x = x[!duplicated(x[, c("group", "value.x", "type")]), ]

Таблица с результатами выглядит следующим образомэто -

##     group value.x value.y   diff type
##  19     A   81360   81353      7  low
##  20     A   81360   81367     -7 high
##  1      A   30000   24163   5837  low
##  8      A   40000   24163  15837  low
##  9      A   40000   80991 -40991 high
##  2      A   30000   80991 -50991 high
##  23     B   75000   76038  -1038 high
##  38     B  130000  126748   3252  low
##  22     B   75000   71721   3279  low
##  29     B   90000   76038  13962  low
##  30     B   90000  113186 -23186 high
##  39     B  130000  155556 -25556 high

Осталось сделать некоторые изменения формы и переименования, чтобы соответствовать формату ожидаемого результата df -

library(reshape2)
x = dcast(x, group + value.x ~ type, value.var = "value.y")
names(x) = gsub(".x", "", names(x))
x = x[, c("group", "value", "low", "high")]
all.equal(x, df)
## [1] TRUE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...