Возвратите подмножество на основе логического сравнения с вводом df - PullRequest
2 голосов
/ 03 июля 2019

Используя R, я пытаюсь вернуть одну строку для каждого идентификатора, фильтруя цели в df_filter или следующем наименьшем целом числе на основе фильтра.

original df:

df:
id   year       
1    2019    
1    2018   
1    2005   
1    2004    
2    2018   
2    2017   
3    1998  
3    1997
3    1996
3    1995

фильтр:

df_filter:
id   year       
1    2017  
2    2018
3    2000

кадр данных результата должен выглядеть следующим образом:

dfnew:
id   year
1    2005
2    2017
3    1998

Ответы [ 2 ]

2 голосов
/ 03 июля 2019

Мы можем использовать data.table

library(data.table)
setDT(df)[df_filter, on = .(id)][year != i.year, 
      .(year = year[which(year  < i.year)[1]]), id]
#   id year
#1:  1 2005
#2:  2 2017
#3:  3 1998

Или использовать non-equi join

setDT(df)[, year1 := year][df_filter, .(id, year), 
         on = .(id, year1 < year), mult = 'first']
#    id year
#1:  1 2005
#2:  2 2017
#3:  3 1998

Или без присвоения (:=) в исходном наборе данных

setDT(df)[, .(year1 = year, year, id)][df_filter, .(id, year),
        on = .(id, year1 < year), mult = 'first']

Или, как прокомментировал @thelatemail

setDT(df)[df_filter, on=.(id, year < year), .(yearM = max(x.year)),
          by=.EACHI][, .(id, year = yearM)]

Или используя tidyverse с fuzzyjoin

library(tidyverse)
library(fuzzyjoin)
fuzzy_left_join(df, df_filter, by = c("id", "year"),
       match_fun = list(`==`, `<`)) %>% 
  group_by(id = id.x) %>%
  summarise(year = year.x[which(year.x < year.y)[1]])
# A tibble: 3 x 2
#     id year
#  <int> <int>
#1     1  2005
#2     2  2017
#3     3  1998

data

df <- structure(list(id = c(1L, 1L, 1L, 1L, 2L, 2L, 3L, 3L, 3L, 3L), 
    year = c(2019L, 2018L, 2005L, 2004L, 2018L, 2017L, 1998L, 
    1997L, 1996L, 1995L)), class = "data.frame", row.names = c(NA, 
-10L))
df_filter <- structure(list(id = 1:3, year = c(2017L, 2018L, 2000L)), 
   class = "data.frame", row.names = c(NA, -3L))
2 голосов
/ 03 июля 2019

Используя dplyr, мы можем left_join df и df_filter by id, group_by id, arrange year в порядке убывания и выбрать первую строку при разнице между двумя годами меньше 0.

library(dplyr)

left_join(df, df_filter, by = "id") %>%
   arrange(desc(year.x)) %>%
   group_by(id) %>%
   slice(which.max((year.x - year.y[1L]) < 0L)) %>%
   select(year.x)


#     id year.x
#   <int>  <int>
#1     1   2005
#2     2   2017
#3     3   1998
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...