Как получить значение, если дата из одного набора данных находится в пределах периода времени в другом наборе данных для каждого идентификатора в R? - PullRequest
2 голосов
/ 05 февраля 2020

Предположим, у меня есть два набора данных, A и B. Для набора данных A он имеет идентификатор, дату и процент. Для набора данных B он имеет идентификатор, date_1, date_2, Int. Если дата в наборе данных A находится в пределах диапазона date_1 и date_2 в наборе данных B; затем я хочу извлечь значение Int в B в столбец Интерес в A. Вот пример кода, который я запускаю. Но получил сообщение об ошибке

"Error in if (subset_A[j, ]$date >= subset_B[k, ]$date_1 & subset_A[j,  : 
  argument is of length zero"

.

A <- data.frame("ID" = c(1,1,1,2,2,3), "date" = c("1900-01-01","1900-11-01","1902-01-01","1903-01-01","1905-01-01","1900-01-01"), "Interest" = c(NA,NA,NA,NA,NA,NA), stringsAsFactors = FALSE)
A$date<-as.Date(A$date)
B <- data.frame("ID" = c(1,1,2,2,2,5), 
                "date_1" = c("1900-01-01","1900-02-01","1900-01-01","1901-02-01","1901-03-01","1900-01-01"),
                "date_2" = c("1900-01-03","1903-01-01","1901-01-01","1901-03-01","1904-03-01","1903-01-01"),
                "Int" = c(1,2,1,3,3,1))
B$date_1 <- as.Date(B$date_1)
B$date_2 <- as.Date(B$date_2)

В R:

IDlist = unique(A$ID)
Table=NULL
for (i in 1:length(IDlist)){
  subset_B <-subset(B, ID == IDlist[i])
  subset_A <-subset(A, ID == IDlist[i])
  for (j in 1:nrow(subset_A)){
    for (k in 1:nrow(subset_B)){
      if(subset_A[j,]$date >=  subset_B[k,]$date_1&
         subset_A[j,]$date <=  subset_B[k,]$date_2&
         !is.na(subset_B[k,]$date_1) & 
         !is.na(subset_B[k,]$date_2))
        subset_A[j,]$Interest <- subset_B[k,]$Int
      Table=rbind(Table,
                  subset_A)
    }
  } 
}

Я хочу получить кадр данных A с последним столбцом, вставленным как c (1,2,2,3, NA NA). Не уверен, почему для l oop не работает. Спасибо!

Ответы [ 3 ]

5 голосов
/ 05 февраля 2020

При data.table неэквивалентном объединении и обновление в объединении становится

library(data.table)
setDT(A)[, Interest := NULL][
  setDT(B), on = .(ID, date >= date_1, date <= date_2), Interest := Int][]
   ID       date Interest
1:  1 1900-01-01        1
2:  1 1900-11-01        2
3:  1 1902-01-01        2
4:  2 1903-01-01        3
5:  2 1905-01-01       NA
6:  3 1900-01-01       NA

Обратите внимание, что столбец Interest необходимо было удалить из A до объединения update , так как он был инициализирован с NA, который имеет тип логический, в то время как значения замены имеют тип double и векторный столбец может содержать данные только одного типа.

3 голосов
/ 05 февраля 2020

1) Используя SQL, это можно выразить непосредственно:

library(sqldf)
sqldf("select A.*, B.Int from A 
  left join B on A.ID = B.ID and A.date between B.date_1 and B.date_2")

, давая:

  ID       date Interest Int
1  1 1900-01-01       NA   1
2  1 1900-11-01       NA   2
3  1 1902-01-01       NA   2
4  2 1903-01-01       NA   3
5  2 1905-01-01       NA  NA
6  3 1900-01-01       NA  NA

2) Если Вы действительно хотите использовать al oop, затем l oop через строки A и для каждого получить соответствующий элемент в B:

Table <- A
for(i in 1:nrow(A)) {
  ix <- which(A$ID[i] == B$ID & A$date[i] >= B$date_1 & A$date[i] <= B$date_2)[1]
  Table$Int[i] <- B$Int[ix]
}
Table

, давая:

  ID       date Interest Int
1  1 1900-01-01       NA   1
2  1 1900-11-01       NA   2
3  1 1902-01-01       NA   2
4  2 1903-01-01       NA   3
5  2 1905-01-01       NA  NA
6  3 1900-01-01       NA  NA
2 голосов
/ 05 февраля 2020

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

library(fuzzyjoin)
library(dplyr)
fuzzy_left_join(A, B, by = c('ID', 'date' = 'date_1', 'date' = 'date_2'),
           match_fun = list(`==`, `>=`, `<=`)) %>%
   transmute(ID = ID.x, date, Interest = Int)
#   ID       date Interest
#1  1 1900-01-01        1
#2  1 1900-11-01        2
#3  1 1902-01-01        2
#4  2 1903-01-01        3
#5  2 1905-01-01       NA
#6  3 1900-01-01       NA
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...