[英]R function to failback in a left_join?
我有20多個不同的數據表,其數據由相同的編碼系統(北美工業分類系統,NAICS)索引,我想加入一個表。
問題是每個表中有不同級別的詳細信息,當我加入時,我希望通過使編碼系統的層次結構失敗來找到最佳匹配,直到找到匹配為止。
常規的left_join
不起作用,因為不會總是有完全匹配。 我已經看過了fuzzyjoin
包,但它有點過頭了。
我想從一個代碼表開始:
t_master
# A tibble: 360 x 1
NAICS17
<chr>
1 311111
2 311119
3 311211
4 311212
5 311213
6 311221
7 311224
8 311225
9 311230
10 311313
# ... with 350 more rows
t_master <- structure(list(NAICS17 = c(311111L, 311119L, 311211L, 311212L,
311213L, 311221L, 311224L, 311225L, 311230L, 311313L)), row.names = c(NA,
-10L), class = "data.frame")
然后遍歷所有其他表,找到每個表中最佳可用匹配,然后加入所有變量。 有時這很簡單,因為有完全匹配(t_asm中的311111和311119將連接到t_master中的311111和311119):
t_asm
# A tibble: 8,167 x 3
NAICS17 CEXBLD CEXMCH
<chr> <chr> <chr>
1 31-33 16806796 96986337
2 311 2099542 9063451
3 3111 92429 517196
4 31111 92429 517196
5 311111 49756 225494
6 311119 42673 291702
7 3112 192911 1016770
8 31121 75310 267693
9 31121M 75310 267693
10 31122 94339 546407
# ... with 8,157 more rows
t_asm <- structure(list(NAICS17 = c("31-33", "311", "3111", "31111", "311111",
"311119", "3112", "31121", "31121M", "31122"), CEXBLD = c("16806796",
"2099542", "92429", "92429", "49756", "42673", "192911", "75310",
"75310", "94339"), CEXMCH = c("96986337", "9063451", "517196",
"517196", "225494", "291702", "1016770", "267693", "267693",
"546407")), row.names = c(NA, -10L), class = c("tbl_df", "tbl",
"data.frame"))
但有時我希望它尋找最佳匹配,即使它不那么詳細(來自t_brdis_2015的311將加入t_master中的311111和311119)
t_brdis_2015
# A tibble: 90 x 3
NAICS17 rdcost_total rdcost_wage
<chr> <chr> <chr>
1 0 355821 204170
2 31 236132 129375
3 32 236132 129375
4 33 236132 129375
5 311 4838 2945
6 312 1002 532
7 313 748 481
8 314 748 481
9 315 748 481
10 316 748 481
# ... with 80 more rows
t_brdis_2015 <- structure(list(NAICS17 = c("0", "31", "32", "33", "311", "312",
"313", "314", "315", "316"), rdcost_total = c("355821", "236132",
"236132", "236132", "4838", "1002", "748", "748", "748", "748"
), rdcost_wage = c("204170", "129375", "129375", "129375", "2945",
"532", "481", "481", "481", "481")), class = c("tbl_df", "tbl",
"data.frame"), row.names = c(NA, -10L))
這將是一個左連接,我希望所有t_master的觀察結果與其他數據表的一個觀察結果相結合。
失敗的方法是(以311111為例):
謝謝,如果有任何不清楚的地方,請告訴我。
我會做一系列更新連接:
library(data.table)
ncs = seq_len(max(nchar(t_master$NAICS17)))
nms = copy(names(t_asm))
xnms = sprintf("x.%s", nms)
tnms = replace(nms, nms == "NAICS17", "m")
t_asm2 <- data.table(t_asm)
out = data.table(t_master)
out[, NAICS17 := as.character(NAICS17)]
out[, m := NA_character_]
for (nc in rev(ncs)){
out[is.na(m), target := substr(NAICS17, 1, nc)]
out[is.na(m),
(tnms) := t_asm2[.SD, on=.(NAICS17 = target), mget(xnms)][]
]
if (!anyNA(out$m)) break
}
out[, target := NULL][]
NAICS17 m CEXBLD CEXMCH
1: 311111 311111 49756 225494
2: 311119 311119 42673 291702
3: 311211 31121 75310 267693
4: 311212 31121 75310 267693
5: 311213 31121 75310 267693
6: 311221 31122 94339 546407
7: 311224 31122 94339 546407
8: 311225 31122 94339 546407
9: 311230 3112 192911 1016770
10: 311313 311 2099542 9063451
m
是匹配的值; target
是我們在循環的當前迭代中嘗試匹配的值。 迭代從最長的代碼開始向后工作。 (看看正在迭代的rev(ncs)
。)
通過過濾到is.na(m)
,我們將跳過在早期迭代中匹配的行。 測試anyNA(out$m)
允許我們在每行匹配時提前退出。
copy
只是一種避免問題的措施, 為什么data.table通過引用更新名稱(DT),即使我分配給另一個變量?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.