匹配和更新R数据表中的列

时间:2016-10-10 20:20:52

标签: r data.table match

我有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

3 个答案:

答案 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"]