Хорошо тогда! Давайте разделим вашу проблему на две части. Первая часть состоит в том, чтобы выполнить указанное объединение по дате, а вторая часть имеет множество результатов, распределенных по столбцам, а не по строкам.
Часть 1 Хотя data.table
может помочь, советую в пользу использования sqldf
, который позволяет вам использовать синтаксис SQL, который является гораздо более читабельным, интуитивно понятным и масштабируемым, если вы хотите изменить свои логические условия или сделать их более сложными.
library(data.table)
library(sqldf)
setDT(df1)
setDT(df2)
result <- sqldf("
select
df2.*,
df1.Drugname,
case
when df1.ID is null then NULL
when df2.DATE_RESULT between df1.Startdate and df1.Enddate then 'Drugname'
else 'Neardrug'
end as situation
from df2
left join df1
on df1.ID = df2.id
and df2.DATE_RESULT between df1.Startdate and date(df1.Enddate, '+7 days')
")
print(result)
ID DATE_RESULT v1 v2 Drugname situation
1 111xxx 2007-11-28 NA 165 <NA> <NA>
2 111xxx 2009-07-08 NA 105 LAMISIL CREME 10MG/G Drugname
3 111xxx 2009-07-08 NA 105 TERBINAFINE TABL 250MG Drugname
4 222xxx 2009-08-24 NA 125 <NA> <NA>
5 222xxx 2012-03-27 66 20 MAGNESIUM HYD KAUWT 724MG Neardrug
Как видите, запрос уже возвращает столбец с именем situation
, который может быть «Drugname» или «Neardrug».
Part 2 Теперь вы хотите распространить результаты много строк для одного и того же идентификатора, чтобы стать столбцами. Идеальный формат - хранить их как есть, в кадре данных строк и столбцов, без повторяющихся столбцов. Это называется форматом tidy
, и это то, что обычно используется несколькими библиотеками R в качестве стандарта, что имеет несколько преимуществ.
Таким образом, мы можем рассматривать формат в виде столбца как форматирование для распечатки, чтобы сделать это более читабельно. Есть и другие проблемы. Если у вас слишком много столбцов, а их содержимое слишком длинное, управление может оказаться затруднительным. Но давайте сделаем это.
Чтобы сделать это, нам сначала нужно создать имена последовательности для ситуаций 'Drugname' в 'Drugname1', 'Drugname2', et c. То же самое для 'Neardrug' -> 'Neardrug1', 'Neardrug2', et c.
library(dplyr)
sequenced_result <- result %>%
arrange(ID, DATE_RESULT, situation, Drugname) %>%
group_by(ID, situation) %>%
mutate(sequencing = row_number()) %>%
mutate(colname = ifelse(is.na(situation), "Drugname1", paste0(situation, sequencing))) %>%
ungroup()
print(sequenced_result)
ID DATE_RESULT v1 v2 Drugname situation sequencing colname
<chr> <chr> <dbl> <dbl> <chr> <chr> <int> <chr>
1 111xxx 2007-11-28 NA 165 NA NA 1 Drugname1
2 111xxx 2009-07-08 NA 105 LAMISIL CREME 10MG/G Drugname 1 Drugname1
3 111xxx 2009-07-08 NA 105 TERBINAFINE TABL 250MG Drugname 2 Drugname2
4 222xxx 2009-08-24 NA 125 NA NA 1 Drugname1
5 222xxx 2012-03-27 66 20 MAGNESIUM HYD KAUWT 724MG Neardrug 1 Neardrug1
Мы почти у цели. Теперь все, что нам нужно сделать, это переместить значения строк в столбцы, выполнив операцию pivot .
library(tidyr)
formatted_result <- sequenced_result %>%
select(-c(situation, sequencing)) %>%
pivot_wider(names_from = colname, values_from = Drugname)
print(formatted_result)
# A tibble: 4 x 7
ID DATE_RESULT v1 v2 Drugname1 Drugname2 Neardrug1
<chr> <chr> <dbl> <dbl> <chr> <chr> <chr>
1 111xxx 2007-11-28 NA 165 NA NA NA
2 111xxx 2009-07-08 NA 105 LAMISIL CREME 10MG/G TERBINAFINE TABL 250MG NA
3 222xxx 2009-08-24 NA 125 NA NA NA
4 222xxx 2012-03-27 66 20 NA NA MAGNESIUM HYD KAUWT 724~
В качестве завершающего штриха, если хотите, вы можете показать только первый слово каждого названия препарата.
library(stringr)
formatted_result_short <- sequenced_result %>%
select(-c(situation, sequencing)) %>%
mutate(Drugname = word(Drugname)) %>%
pivot_wider(names_from = colname, values_from = Drugname)
print(formatted_result_short)
ID DATE_RESULT v1 v2 Drugname1 Drugname2 Neardrug1
<chr> <chr> <dbl> <dbl> <chr> <chr> <chr>
1 111xxx 2007-11-28 NA 165 NA NA NA
2 111xxx 2009-07-08 NA 105 LAMISIL TERBINAFINE NA
3 222xxx 2009-08-24 NA 125 NA NA NA
4 222xxx 2012-03-27 66 20 NA NA MAGNESIUM