在 R 中处理大型数据集
Posted
技术标签:
【中文标题】在 R 中处理大型数据集【英文标题】:Processing Large Data Sets in R 【发布时间】:2020-05-21 21:09:28 【问题描述】:我有一个约 5 毫米行的企业数据集,其中包含联系信息(ID(int)、Email(text)、BusinessPhone(text)、WorkPhone(text)、CellPhone(text))——其中超过 300 万行包含重复数据。但这些骗子并不完全是骗子 - 例如,可能有多个行中的电话号码具有不同的电子邮件地址。
我想让每一行都有唯一的信息,这样我的数据文件中就没有重复的电话号码或电子邮件。我计划通过新列将列聚合到列表中来做到这一点。此列(我们称为 ROWID)应该是包含该行中出现的 1 个或多个联系人数据点(Email、BusinessPhone、WorkPhone、CellPhone)的所有 ID 的串联。
我编写了适用于小样本量的代码,但我不知道如何对其进行缩放。
注意:缺少电话号码的行(3 列中的任何一个)有一个“NA”文本占位符。 行示例:
before:
ID Email BusinessPhone WorkPhone CellPhone
1 test@mail.com 5555555555 NA 9998887777
2 NA 5555555555 873998898 NA
Desired After:
ID Email BusinessPhone WorkPhone CellPhone ROWIDs
1 test@mail.com 5555555555 NA 9998887777 1,2
2 NA 5555555555 873998898 NA 1,2
library(foreach)
library(doParallel)
registerDoParallel(cores = detectCores())
getDoParWorkers() # (4)
#################### GET MATCHING ROW IDs ######################################################
d = ID(int), Email(char), BusinessPhone(char), WorkPhone(char), CellPhone(char), ROWIDs(all values are '0', col is character vector)
row = function(d)
foreach(i = 1:nrow(d),.packages = c('dplyr','data.table','tidyverse')) %dopar%
# 1. IDENTIFY LIST OF ROW IDS THAT CONTAIN CONTACT DATA FROM THE GIVEN ROW:
rowIDList = d[(emailp == emailp[i] & emailp != '') |
(BusinessPhone %in% c(BusinessPhone[i],WorkPhone[i],CellPhone[i]) & BusinessPhone != 0) |
(WorkPhone %in% c(BusinessPhone[i],WorkPhone[i],CellPhone[i]) & WorkPhone != 0) |
(CellPhone %in% c(BusinessPhone[i],WorkPhone[i],CellPhone[i]) & CellPhone != 0),
paste(ID, sep = ',')] %>% as.integer()
# 2. GET THE ROW IDS INTO CHARACTER FORM TO LIST THEM IN THE NEW COLUMN:
rowIDs = paste(rowIDList, collapse = ',') %>% as.character()
# 3. EDIT THE NEW COLUMN FOR THE SUBSET OF ROWS THAT CONTAIN DATA FROM THE ROW IN THE LOOP ITERATION:
d[ID %in% rowIDList,
try := rep(rowIDs,
length(rowIDList))]
对于 1000 行的随机样本,system.time 如下: 用户:0.75 系统:0.12 经过:1.35
这在 5,000 行时呈指数增长: 用户:12.55 系统:1.50 经过:16.72
还有 10,000: 用户:50.97 系统:16.77 经过:71.88
这距离我开始的地方还有很长的路要走,但这是我目前的技能所能承受的。感谢您提供任何帮助或指导。
【问题讨论】:
您不应该将数据分成多个表吗?一个包含不变数据(例如 ID、出生日期)、一个用于邮件(ID、邮件)、一个用于业务电话(ID、电话号码)等。作为一个关系数据集,用于识别具有 ID 的个人并从中获取信息其他表 即使我这样做了,我仍然需要合并重复的行并为每一行分配一个 rowID。 我们的想法是为每个人找到一个唯一标识符,并使用它将所有表格链接在一起。这样,每个表都包含唯一值,但您不会丢失任何内容并限制重复,因为两个不同的邮件并不意味着重复所有其他字段。最后你将如何处理这些数据?这将告知您需要如何格式化它们 @Gallarus,我很欣赏关于数据库最佳实践的输入,但我有一个凌乱的文件,我需要在做出决定之前对其进行重复数据删除。 好的,我想我误解了你的问题。你能提供你想要的输入数据和结果的例子吗?像 10 行杂乱无章的数据,以及你最终应该拥有的东西。 【参考方案1】:不确定这对于您的数据集是否足够快,您可以使用 igraph
来识别指向同一个人的 id 集群:
library(igraph)
edges <- melt(DT[, (names(DT)) := lapply(.SD, as.character)], id.vars="ID", na.rm=TRUE)[,
if (.N > 1L) transpose(combn(ID, 2L, simplify=FALSE)), value][, (1) := NULL]
g <- graph_from_data_frame(edges, FALSE)
mem <- setDT(stack(clusters(g)$membership))[, ROWIDs := toString(ind), values]
DT[mem, on=.(ID=ind), ROWIDs := ROWIDs]
DT
输出:
ID Email BusinessPhone WorkPhone CellPhone ROWIDs
1: 1 test@mail.com 5 <NA> 7 1, 2
2: 2 <NA> 5 6 <NA> 1, 2
3: 3 aaaa@mail.com <NA> <NA> <NA> 3, 4
4: 4 aaaa@mail.com <NA> 1 <NA> 3, 4
5: 5 bbbb@mail.com <NA> 3 <NA> 5, 6
6: 6 <NA> <NA> 3 <NA> 5, 6
7: 7 cccc@mail.com <NA> <NA> 4 7, 8
8: 8 <NA> <NA> <NA> 4 7, 8
数据:
library(data.table)
DT <- fread("
ID Email BusinessPhone WorkPhone CellPhone
1 test@mail.com 5 NA 7
2 NA 5 6 NA
3 aaaa@mail.com NA NA NA
4 aaaa@mail.com NA 1 NA
5 bbbb@mail.com NA 3 NA
6 NA NA 3 NA
7 cccc@mail.com NA NA 4
8 NA NA NA 4
")
【讨论】:
以上是关于在 R 中处理大型数据集的主要内容,如果未能解决你的问题,请参考以下文章
如何在 R/Python 中迭代/循环一个大型(>2GB)JSON 数据集? [复制]