Ранг, соответствующий следующей доступной дате из другого кадра данных - PullRequest
0 голосов
/ 14 января 2020

Может ли кто-нибудь помочь мне с приведенным ниже требованием?

DF1:

 Item       Day            Rank
  A     2020-01-12
  A     2020-01-13
  B     2020-01-13

DF2:

  Item        Day            Rank
   A       2020-01-10         1
   A       2020-01-11         2
   A       2020-01-14         3
   B       2020-01-14         4
   B       2020-01-17         5

Если у нас есть День в DF1, которого нет в DF2 я хочу получить ранг для даты DF1 со следующей даты, соответствующей дате в DF2. Здесь 2020-01-12 в DF1 не имеет никакого ранга, поэтому он должен искать из DF2 следующую дату, которая является 2020-01-13, и соответствующий ранг должен появиться в качестве выходных данных.

Final Output ( DF1):

 Item       Day            Rank
  A     2020-01-12          3
  A     2020-01-13          3
  B     2020-01-13          4

Ответы [ 3 ]

1 голос
/ 14 января 2020

Мы можем использовать fuzzy_join

library(dplyr)
fuzzyjoin::fuzzy_left_join(df1, df2, by = c("Item" = "Item", "Day" = "Day"), 
           match_fun = list(`==`, `<=`)) %>%
   group_by(Item.x, Day.x) %>%
   slice(1L) %>%
   mutate(Rank.x = coalesce(as.integer(Rank.x), Rank.y)) %>%
   select(-ends_with("y")) %>%
   rename_all(~names(df1))

#  Item       Day         Rank
#  <fct>     <date>     <int>
#1   A     2020-01-12     3
#2   A     2020-01-13     3
#3   B     2020-01-13     4
1 голос
/ 14 января 2020

Вы можете использовать findInterval как:

DF1$Rank <- DF2$Rank[findInterval(DF1$Day, c(0,DF2$Day), left.open = TRUE)]
DF1
#         Day Rank
#1 2020-01-12    3
#2 2020-01-15    5

В случае, если DF2 не отсортировано:

i <- order(DF2$Day)
j <- findInterval(DF1$Day, c(0,DF2$Day[i]), left.open = TRUE)
DF1$Rank <- DF2$Rank[i[j]]

Или в случае DF2 $ Ранг равен 1:nrow(DF2), а DF2 отсортировано.

DF1$Rank <- findInterval(DF1$Day, c(0,DF2$Day), left.open = TRUE)

Данные:

DF1 <- data.frame(Day=as.Date(c("2020-01-12", "2020-01-15")), Rank=NA)
DF2 <- data.frame(Day=as.Date(c("2020-01-10", "2020-01-11", "2020-01-13"
  , "2020-01-14", "2020-01-17")), Rank=1:5)

Для обновленного Вопроса :

DF1 <- data.frame(Item=c("A","A","B"), Day=as.Date(c("2020-01-12", "2020-01-13", "2020-01-13")), Rank=NA)
DF2 <- data.frame(Item=c(rep("A",3),rep("B",2)), Day=as.Date(c("2020-01-10", "2020-01-11", "2020-01-14", "2020-01-14", "2020-01-17")), Rank=1:5)

DF1$Rank <- unlist(sapply(unique(DF1$Item), function(i) {DF2$Rank[DF2$Item==i][findInterval(DF1$Day[DF1$Item==i], c(0,DF2$Day[DF2$Item==i]), left.open = TRUE)]}))
DF1
#  Item        Day Rank
#1    A 2020-01-12    3
#2    A 2020-01-13    3
#3    B 2020-01-13    4

Также взгляните на Соедините один фрейм данных с другим по членству в диапазоне

1 голос
/ 14 января 2020

Вот базовое решение R (при условии, что ваш столбец Day в DF1 и DF2 уже имеет класс Date)

DF1 <- do.call(rbind,
               c(make.row.names = F,
                 lapply(split(DF1,DF1$Item), function(v) {
                   z <- subset(DF2,Item == unique(v$Item))
                   v <- within(v, Rank <- findInterval(Day, z$Day)+ min(z$Rank))
                   }
                   )
                 )
               )

, такой что

> DF1
  Item        Day Rank
1    A 2020-01-12    3
2    A 2020-01-13    3
3    B 2020-01-13    4

ДАННЫЕ

DF1 <- structure(list(Item = c("A", "A", "B"), Day = structure(c(18273, 
18274, 18274), class = "Date"), Rank = c(NA, NA, NA)), row.names = c(NA, 
-3L), class = "data.frame")

DF2 <- structure(list(Item = c("A", "A", "A", "B", "B"), Day = structure(c(18271, 
18272, 18275, 18275, 18278), class = "Date"), Rank = 1:5), row.names = c(NA, 
-5L), class = "data.frame")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...