我的数据包含两个不同的数据框:
visits <- data.frame("visit_nr", "label", "degree", "code")
category <- data.frame("label", "degree", "group", "code1", "code2, "code3")
我想基于两个数据框之间“标签”,“度”和“代码”之间的匹配,为数据框“访问”中的每次访问分配一个组。 但是,如果来自数据框“类别”的“ code2”和“ code3”也列在数据框“访问”中,则只能将来自特定“ visit_nr”的行分配给特定组。这意味着要将一行分配给某个组,需要三行具有相同的“ visit_nr”,其中“ label”; “学位”和“代码”与以下任意一项匹配:
- "label", "degree", "code1"
- "label", "degree", "code2"
- "label", "degree", "code3"
因为这些数据框都包含超过5万行,所以我想避免使用循环来完成此操作。
访问
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
类别
label | degree | group | code1 | code2 | code3
171 | 1 | 2 | 354373| 200200| 475985
171 | 1 | 3 | 354373| 200200| 998282
171 | 1 | 1 | 354373| 200200| 0
预期输出:
visit_nr | label | degree | code | Group
1601704801 | 171 | 1 | 354373 | 2
1601704801 | 171 | 1 | 200200 | 2
1601704801 | 171 | 1 | 973443 | 2
1601704801 | 171 | 1 | 475985 | 2
1601704801 | 171 | 1 | 994320 | 2
答案 0 :(得分:0)
Merge
2个表3次,然后像这样重新整理它们:
df1 <- merge(visits, category, by.x = c("label", "degree", "code"), by.y = c("label", "degree", "code1"), all.x = TRUE)
df2 <- merge(visits, category, by.x = c("label", "degree", "code"), by.y = c("label", "degree", "code2"), all.x = TRUE)
df3 <- merge(visits, category, by.x = c("label", "degree", "code"), by.y = c("label", "degree", "code3"), all.x = TRUE)
#change the column names using names(df) here to maintain consistency
df <- rbind(df1, df2, df3)
答案 1 :(得分:0)
还有另一种方法,可以将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
在comment中,OP公开了
并非数据框中的列
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
")