В R, как я могу найти значение в одном столбце на основе интервала в соседних столбцах, который включает значения, которые я хочу сопоставить? - PullRequest
2 голосов
/ 07 мая 2019

В R у меня есть справочная таблица (датафрейм) с тремя столбцами.Ниже приведен пример:

reftable <- data.frame(
  X_lower = c(0, 101, 181, 231, 280, 300, 340, 390, 500), 
  X_upper = c(100, 180, 230, 279, 299, 339, 389, 499, 600), 
  Percentile = c(2, 3, 4, 6, 8, 11, 15, 20, 25))

# X_lower     X_upper     Percentile
# 0           100         2
# 101         180         3
# 181         230         4
# etc.

У меня есть отдельный фрейм данных, scores, с конкретными значениями для X, и я хочу использовать справочную таблицу для поиска процентильного ранга, связанного с каждым значением.

scores <- data.frame(
  X = c(58, 127, 175, 245, 300, 90, 405, 284, 330), 
  PercRank = NA))

# X        PercRank
# 58       ?
# 127      ?
# 175      ?
# 245      ?
# etc.

Я пытался использовать match или findInterval, но не могу найти решение.Я искал существующие вопросы.Если об этом уже спрашивали, я не должен искать правильные условия поиска.

Ответы [ 3 ]

2 голосов
/ 07 мая 2019

1) sqldf Можно использовать левое соединение SQL:

library(sqldf)

scores$PercRank <- NULL

sqldf("select s.X, r.Percentile as PercRank
  from scores as s
  left join reftable as r on s.X between r.X_lower and r.X_upper")

дает:

    X PercRank
1  58        2
2 127        3
3 175        3
4 245        6
5 300       11
6  90        2
7 405       20
8 284        8
9 330       11

2) findInterval Базовая альтернатива - findInterval:

transform(scores, percRank = with(reftable, Percentile[ findInterval(X, X_lower) ]))
1 голос
/ 07 мая 2019

Вы можете попробовать:

scores$PercRank=sapply(scores$X,function(x){
  i = which(reftable$X_upper>x)[1]
  reftable$Percentile[i]
})

> scores
    X PercRank
1  58        2
2 127        3
3 175        3
4 245        6
5 300       11
6  90        2
7 405       20
8 284        8
9 330       11

Поскольку заказывается reftable, вам нужно проверить только первое верхнее значение, большее, чем ваше X.

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

1) Опция будет foverlaps с data.table

library(data.table)
scores$PercRank <- foverlaps(scores1, reftable)[order(rn)]$Percentile
scores$rn <- NULL
scores
#     X PercRank
#1  58        2
#2 127        3
#3 175        3
#4 245        6
#5 300       11
#6  90        2
#7 405       20
#8 284        8
#9 330       11

2) Или используйте неэквивалентное объединение

setDT(scores)[reftable, PercRank := Percentile, on = .(X >= X_lower, X <= X_upper)]
scores
#     X PercRank
#1:  58        2
#2: 127        3
#3: 175        3
#4: 245        6
#5: 300       11
#6:  90        2
#7: 405       20
#8: 284        8
#9: 330       11

3) Или с fuzzyjoin

library(fuzzyjoin)
library(dplyr)
fuzzy_left_join(scores, reftable, by = c("X" = "X_lower", "X" = "X_upper"),
        match_fun = list(`>=`, `<=`)) %>% 
      select(X, Percentile)
#     X Percentile
#1  58          2
#2 127          3
#3 175          3
#4 245          6
#5 300         11
#6  90          2
#7 405         20
#8 284          8
#9 330         11

данные

scores <- data.frame(
     X = c(58, 127, 175, 245, 300, 90, 405, 284, 330))
scores$rn <- seq_len(nrow(scores))
scores1 <- data.table(X_lower = scores$X, X_upper = scores$X, rn = scores$rn)
setkeyv(scores1, c("X_lower", "X_upper"))
setkeyv(reftable, c("X_lower", "X_upper"))
...