Существует альтернативный подход, который изменяет category
с широкого на длинный формат, объединяет с visits
и подсчитывает, сколько подходящих кодов можно найти:
library(data.table)
# reshape from wide to long format
lcat <- melt(setDT(category), measure.vars = patterns("^code"),
value.name = "code")
# join and count
tmp <- lcat[setDT(visits), on = .(label, degree, code), nomatch = 0L][
, .N, by = .(visit_nr, label, degree, group)][
N == 3L]
tmp[]
visit_nr label degree group N
1: 1601704801 171 1 2 3
# update join
visits[tmp, on = .(visit_nr, label, degree), Group := group, mult = "first"][]
visits[]
visit_nr label degree code Group
1: 1601704801 171 1 354373 2
2: 1601704801 171 1 200200 2
3: 1601704801 171 1 973443 2
4: 1601704801 171 1 475985 2
5: 1601704801 171 1 994320 2
EDIT
В комментарии ОП раскрыл, что
не все строки в столбцах code2
и code3
в кадре данных
category
имеют значение. Также бывает, что только code1
имеет значение
отличные от 0 и code2
и code3
имеют значение 0. В этом
В случае, если в определенном visit_nr
должен присутствовать только первый код
назначить соответствующую группу для всего visit_nr
Таким образом, простая проверка, если есть точные 3 совпадающих кода, работает для образца набора данных, но не для производственного набора данных OP.
Я полагаю, что дополнительное требование может быть покрыто двумя модификациями:
- Все строки с
code == 0
удалены из long
- Если
tmp
содержит несколько совпадений, выбирается тот, который имеет наибольшее значение N
. Если есть связи, which.max()
выбирает первую встреченную.
Итак, код становится:
library(data.table)
lcat <- melt(setDT(category), measure.vars = patterns("^code"),
value.name = "code")[code != 0]
tmp <- lcat[setDT(visits), on = .(label, degree, code), nomatch = 0L][
, .N, by = .(visit_nr, label, degree, group)][
, .SD[which.max(N)], by = .(visit_nr, label, degree)]
visits[tmp, on = .(visit_nr, label, degree), Group := group]
visits[]
visit_nr label degree code Group
1: 1601704801 171 1 354373 2
2: 1601704801 171 1 200200 2
3: 1601704801 171 1 973443 2
4: 1601704801 171 1 475985 2
5: 1601704801 171 1 994320 2
Данные
library(data.table)
visits <- fread("
visit_nr | label | degree | code | Group
1601704801 | 171 | 1 | 354373 | 0
1601704801 | 171 | 1 | 200200 | 0
1601704801 | 171 | 1 | 973443 | 0
1601704801 | 171 | 1 | 475985 | 0
1601704801 | 171 | 1 | 994320 | 0
")
category <- fread("
label | degree | group | code1 | code2 | code3
171 | 1 | 2 | 354373| 200200| 475985
171 | 1 | 3 | 354373| 200200| 998282
171 | 1 | 1 | 354373| 200200| 0
")