我有2个数据表。输入和数据表如下:
DT1
email custtype
1: abc@yahoo.com subs
2: eli@gmail.com subs
3: tod@hotmail.com subs
dt1 = setDT(structure(list(email = c("abc@yahoo.com", "eli@gmail.com", "tod@hotmail.com"
), custtype = c("subs", "subs", "subs")), .Names = c("email",
"custtype"), class = c("data.table", "data.frame"), row.names = c(NA,
-3L)))
DT2
emails range
1: sam@live.com orange
2: tod@hotmail.com orange
3: ver@live.com orange
4: yahoo@yah.com orange
dt2 = setDT(structure(list(emails = structure(1:4, .Label = c("sam@live.com",
"tod@hotmail.com", "ver@live.com", "yahoo@yah.com"), class = "factor"),
range = structure(c(1L, 1L, 1L, 1L), .Label = "orange", class = "factor")), .Names = c("emails",
"range"), class = c("data.table", "data.frame"), row.names = c(NA,
-4L)))
我正在尝试将dt1中的电子邮件与dt2中的电子邮件进行匹配,然后尝试更新dt1中的custtype列。到目前为止我已经尝试了
dt1[match(email,dt2$emails), custtype:="some value"]
这样做是因为它更改了找到匹配项的索引处的值,而不是根据找到匹配项的电子邮件地址更改它。
结果数据表应如下所示。找到匹配项的电子邮件,相应的custtype应使用提供的值进行更新:
email custtype
1: abc@yahoo.com subs
2: eli@gmail.com subs
3: tod@hotmail.com some value
答案 0 :(得分:3)
你试过了:
dt1[match(email,dt2$emails), custtype:="some value"]
match()
所做的是找到dt2
的行号,然后将其作为索引传递给dt1
。这没有任何意义。
您的想法是直接使用dt2
索引dt1
。
> dt1
email custtype
1: abc@yahoo.com subs
2: eli@gmail.com subs
3: tod@hotmail.com subs
> dt1[dt2, on=c(email="emails"), custtype:="some value"]
> dt1
email custtype
1: abc@yahoo.com subs
2: eli@gmail.com subs
3: tod@hotmail.com some value
这似乎是你想写的结果。
FAQ 2.14解释了A[B]
语法背后的想法。
答案 1 :(得分:1)
另一种data.table
方法是加入两个表:
dt2[dt1, on = c(emails = "email"), mult = "first"][!is.na(range), custtype := "some value"][, range := NULL][]
dt2[dt1, on = c(emails = "email"), mult = "first"]
是一个右连接,它返回dt1
的所有行:
emails range custtype
1: abc@yahoo.com NA subs
2: eli@gmail.com NA subs
3: tod@hotmail.com orange subs
mult = "first"
可防止不必要的重复项,以防dt2
中有多个条目使用相同的电子邮件地址,但range
的值不同。
custtype
只有匹配的电子邮件地址才会在range
列中包含非NA条目。
[!is.na(range), custtype := "some value"]
仅在已找到匹配项的行中使用此选项更改custtype
。
range
列不再需要range
列。它被删除
[, range := NULL]
由于最后一项操作是通过引用更新 最终
[]
确保打印结果。
答案 2 :(得分:0)
找到使用它的解决方案。但仍在寻找更优雅的解决方案。
dt1[which(match(email, dt2$emails) > 0), custtype := "some value"]