大数据在不同行和列中的多个匹配
Multiple matches in different row and columns for large data
我在两个不同的 table 中遇到多个匹配问题(100 万行 * 15;3000 * 20)可能会变得更大(1000 万行)。
我的解决方案有效,但我想尽可能快地制作脚本,因为我可能必须将它用于更大的数据帧。我正在使用 r 包 data.table.
考虑两个无法删除行的示例 table:
table 1 - ToMach 列等于 FALSE 表示关联标签不存在于 table2 中,此步骤将要执行的匹配减少两个数量级:
set.seed(99)
table1 <- data.table(Tag = sample(paste0("tag_",1:3), 5, replace = T))
table1[ , ToMatch := ifelse(Tag == "tag_1", F, T)]
table1
Tag ToMatch
1: tag_2 TRUE
2: tag_1 FALSE
3: tag_3 TRUE
4: tag_3 TRUE
5: tag_2 TRUE
table2:
set.seed(99)
table2 <- data.table(center = sample(paste0("tag_",2:8), 5, replace = T),
north = sample(paste0("tag_",2:8), 5, replace = T),
south = sample(paste0("tag_",2:8), 5, replace = T))
> table2
center north south
1: tag_6 tag_8 tag_5
2: tag_2 tag_6 tag_5
3: tag_6 tag_4 tag_3
4: tag_8 tag_4 tag_6
5: tag_5 tag_3 tag_6
我的objective是在table2中找到table1的标签所在的行(可以在以上各列的任意一列)。我将输出视为列表:
输出:
Tag ToMatch output
1: tag_2 TRUE 2
2: tag_1 FALSE NA
3: tag_3 TRUE 3,5
4: tag_3 TRUE 3,5
5: tag_2 TRUE 2
我的解决方案:
要评估 table 1 的哪些行
match.index <- which(table1$ToMatch == T)
> match.index
[1] 1 3 4 5
汇集来自 table 的所有标签 2. 使用 t
(tag_6 tag_8 tag_5 tag_2 tag_6 tag_5 ...
)
维护行顺序
all.tags <- as.vector(t(table2))
> all.tags
[1] "tag_6" "tag_8" "tag_5" "tag_2" "tag_6" "tag_5" "tag_6"
[8] "tag_4" "tag_3" "tag_8" "tag_4" "tag_6" "tag_5" "tag_3"
[15] "tag_6"
预定义一个空列表
list.results <- as.list(rep(as.numeric(NA), dim(table1)[1]))
循环:
for (i in 1:length(match.index)) {
list.results[[ match.index[i] ]] <- ceiling(
grep(table1[match.index[i], Tag], all.tags)
/3)
}
# dividing the index of all.tags found with grep by 3 (the original
# number of columns in table2) and rounding up to the closest integer
# (ceiling) return the index of the original table 2 where the tag
# is located
最终输出:
> table1[ , output := list.results]
> table1
Tag ToMatch output
1: tag_2 TRUE 2
2: tag_1 FALSE NA
3: tag_3 TRUE 3,5
4: tag_3 TRUE 3,5
5: tag_2 TRUE 2
您对加快此代码有什么建议吗?
提前致谢
这里有一些基本的 R 代码可以解决这个问题:
table1 <- within(table1, {
output <- NA
output[ToMatch] <- sapply(Tag[ToMatch], function(x)
paste(which(x == table2, arr.ind=TRUE)[,1], collapse=","))
})
哪个returns
表 1
Tag ToMatch output
1: tag_2 TRUE 2
2: tag_1 FALSE NA
3: tag_3 TRUE 5,3
4: tag_3 TRUE 5,3
5: tag_2 TRUE 2
这是一个简短的描述。 within
允许在对象(通常是数据框)内引用并减少了一些输入的需要。首先,分配输出 NA。然后,对于要匹配的输出的每个元素(使用 ToMatch),使用 which
和 arr.ind=TRUE 参数找到匹配每个元素的行。 paste
每个元素的结果合并到“,”上。
上面代码的data.table
模拟是
table1[, output := NA_character_][as.logical(ToMatch),
output := sapply(Tag, function(x) paste(which(x == table2, arr.ind=TRUE)[,1],
collapse=","))][]
Tag ToMatch output
1: tag_2 TRUE 2
2: tag_1 FALSE NA
3: tag_3 TRUE 5,3
4: tag_3 TRUE 5,3
5: tag_2 TRUE 2
第一个 []
为感兴趣的元素创建 NA 向量和第二个子集,并用所需值填充 NA 向量。此 "filling in" 部分代码与上面的代码相同。
难点主要在于table2
的广泛代表性。一旦它被融化,剩下的就很简单了:
melt(table2[, id := .I], id = 'id')[
table1, on = c(value = 'Tag'), .(list(if(ToMatch) id)), by = .EACHI]
# value V1
#1: tag_2 2
#2: tag_1 NULL
#3: tag_3 5,3
#4: tag_3 5,3
#5: tag_2 2
如果您有很多重复项 - 事先将您的数据唯一化:
melt(table2[, id := .I], id = 'id')[
unique(table1), on = c(value = 'Tag'), .(list(if(ToMatch) id)), by = .EACHI][
table1, on = c(value = 'Tag')]
我在两个不同的 table 中遇到多个匹配问题(100 万行 * 15;3000 * 20)可能会变得更大(1000 万行)。
我的解决方案有效,但我想尽可能快地制作脚本,因为我可能必须将它用于更大的数据帧。我正在使用 r 包 data.table.
考虑两个无法删除行的示例 table:
table 1 - ToMach 列等于 FALSE 表示关联标签不存在于 table2 中,此步骤将要执行的匹配减少两个数量级:
set.seed(99)
table1 <- data.table(Tag = sample(paste0("tag_",1:3), 5, replace = T))
table1[ , ToMatch := ifelse(Tag == "tag_1", F, T)]
table1
Tag ToMatch
1: tag_2 TRUE
2: tag_1 FALSE
3: tag_3 TRUE
4: tag_3 TRUE
5: tag_2 TRUE
table2:
set.seed(99)
table2 <- data.table(center = sample(paste0("tag_",2:8), 5, replace = T),
north = sample(paste0("tag_",2:8), 5, replace = T),
south = sample(paste0("tag_",2:8), 5, replace = T))
> table2
center north south
1: tag_6 tag_8 tag_5
2: tag_2 tag_6 tag_5
3: tag_6 tag_4 tag_3
4: tag_8 tag_4 tag_6
5: tag_5 tag_3 tag_6
我的objective是在table2中找到table1的标签所在的行(可以在以上各列的任意一列)。我将输出视为列表:
输出:
Tag ToMatch output
1: tag_2 TRUE 2
2: tag_1 FALSE NA
3: tag_3 TRUE 3,5
4: tag_3 TRUE 3,5
5: tag_2 TRUE 2
我的解决方案:
要评估 table 1 的哪些行
match.index <- which(table1$ToMatch == T)
> match.index
[1] 1 3 4 5
汇集来自 table 的所有标签 2. 使用 t
(tag_6 tag_8 tag_5 tag_2 tag_6 tag_5 ...
)
all.tags <- as.vector(t(table2))
> all.tags
[1] "tag_6" "tag_8" "tag_5" "tag_2" "tag_6" "tag_5" "tag_6"
[8] "tag_4" "tag_3" "tag_8" "tag_4" "tag_6" "tag_5" "tag_3"
[15] "tag_6"
预定义一个空列表
list.results <- as.list(rep(as.numeric(NA), dim(table1)[1]))
循环:
for (i in 1:length(match.index)) {
list.results[[ match.index[i] ]] <- ceiling(
grep(table1[match.index[i], Tag], all.tags)
/3)
}
# dividing the index of all.tags found with grep by 3 (the original
# number of columns in table2) and rounding up to the closest integer
# (ceiling) return the index of the original table 2 where the tag
# is located
最终输出:
> table1[ , output := list.results]
> table1
Tag ToMatch output
1: tag_2 TRUE 2
2: tag_1 FALSE NA
3: tag_3 TRUE 3,5
4: tag_3 TRUE 3,5
5: tag_2 TRUE 2
您对加快此代码有什么建议吗?
提前致谢
这里有一些基本的 R 代码可以解决这个问题:
table1 <- within(table1, {
output <- NA
output[ToMatch] <- sapply(Tag[ToMatch], function(x)
paste(which(x == table2, arr.ind=TRUE)[,1], collapse=","))
})
哪个returns
表 1
Tag ToMatch output
1: tag_2 TRUE 2
2: tag_1 FALSE NA
3: tag_3 TRUE 5,3
4: tag_3 TRUE 5,3
5: tag_2 TRUE 2
这是一个简短的描述。 within
允许在对象(通常是数据框)内引用并减少了一些输入的需要。首先,分配输出 NA。然后,对于要匹配的输出的每个元素(使用 ToMatch),使用 which
和 arr.ind=TRUE 参数找到匹配每个元素的行。 paste
每个元素的结果合并到“,”上。
上面代码的data.table
模拟是
table1[, output := NA_character_][as.logical(ToMatch),
output := sapply(Tag, function(x) paste(which(x == table2, arr.ind=TRUE)[,1],
collapse=","))][]
Tag ToMatch output
1: tag_2 TRUE 2
2: tag_1 FALSE NA
3: tag_3 TRUE 5,3
4: tag_3 TRUE 5,3
5: tag_2 TRUE 2
第一个 []
为感兴趣的元素创建 NA 向量和第二个子集,并用所需值填充 NA 向量。此 "filling in" 部分代码与上面的代码相同。
难点主要在于table2
的广泛代表性。一旦它被融化,剩下的就很简单了:
melt(table2[, id := .I], id = 'id')[
table1, on = c(value = 'Tag'), .(list(if(ToMatch) id)), by = .EACHI]
# value V1
#1: tag_2 2
#2: tag_1 NULL
#3: tag_3 5,3
#4: tag_3 5,3
#5: tag_2 2
如果您有很多重复项 - 事先将您的数据唯一化:
melt(table2[, id := .I], id = 'id')[
unique(table1), on = c(value = 'Tag'), .(list(if(ToMatch) id)), by = .EACHI][
table1, on = c(value = 'Tag')]