gpt4 book ai didi

r - 在 R 中使用 'fastmatch' 包

转载 作者:行者123 更新时间:2023-12-05 08:43:49 27 4
gpt4 key购买 nike

我必须在大约 10MM 值的向量中找到 1MM 数值的索引。我找到了包 fastmatch,但是当我使用函数 fmatch() 时,我只返回第一个匹配项的索引。

有人可以帮我使用这个函数来查找所有值,而不仅仅是第一个吗?我意识到这是一个基本问题,但在线文档非常稀少,fmatch 大大缩短了计算时间。

非常感谢!


这是一些示例数据 - 出于本练习的目的,我们将此数据框称为 A:

              DateTime     Address       Type     ID
1 2014-03-04 20:21:03 982076970 1 2752394
2 2014-03-04 20:21:07 98174238211 1 2752394
3 2014-03-04 20:21:08 76126162197 1 2752394
4 2014-03-04 20:21:16 6718053253 1 2752394
5 2014-03-04 20:21:17 98210219176 1 2752510
6 2014-03-04 20:21:20 7622877100 1 2752510
7 2014-03-04 20:21:23 2425126157 1 2752510
8 2014-03-04 20:21:23 2425126157 1 2752510
9 2014-03-04 20:21:25 701838650 1 2752394
10 2014-03-04 20:21:27 98210219176 1 2752394

我想做的是找到每个 Address 的唯一 Type 值的数量。有几百万行数据,大约有 1MM 的唯一 Address 值……平均而言,每个 Address 在数据集中出现大约 6 次。而且,虽然上面列出的 Type 值都是 1,但它们可以取 0:5 之间的任何值。我还意识到 Address 值很长,这增加了匹配所需的时间。

我尝试了以下方法:

uvals <- unique(A$Address)
utypes <- matrix(0,length(uvals),2)
utypes[,1] <- uvals

for (i in 1:length(unique(Address))) {
b <- which(uvals[i] %in% A$Address)
c <- length(unique(A$Type[b]))
utypes[i,2] <- c
}

但是,上面的代码不是很有效 - 如果我循环超过 1MM 值,我估计这将需要 10-15 个小时。

我也在循环中尝试过这个……但速度并没有快得多。

b <- which(A$Address == uvals[i])  

我知道有一种更优雅/更快的方法,我是 R 的新手,非常感谢任何帮助。

最佳答案

这可以使用 data.table 中的 unique 函数来完成,然后进行聚合。我将或多或少地使用@Chinmay 生成的示例数据来说明它:

创建示例数据:

set.seed(100L)
dat = data.frame(
address = sample(1e6L, 1e7L, TRUE),
value = sample(1:5, 1e7L, TRUE, prob=c(0.5, 0.3, 0.1, 0.07, 0.03))
)

data.table解决方案:

require(data.table) ## >= 1.9.2
dat.u = unique(setDT(dat), by=c("address", "value"))
ans = dat.u[, .N, by=address]

说明:

  • The setDT function converts a data.frame to data.table by reference (which is very fast).
  • unique function operated on a data.table evokes the unique.data.table method, which is incredibly fast compared to base:::unique. Now, we've only unique values of type for every address.
  • All that's left to do is to aggregate or group-by address and get the number of observations that are there in each group. The by=address part groups by address and .N is an in-built data.table variable that provides the number of observations for that group.

基准:

我将创建函数以将数据生成为 data.tabledata.frame 以针对 data.table 答案进行基准测试dplyr 解决方案 (a) 由 @beginneR 提出,尽管我认为那里不需要 arrange(.) 因此将跳过该部分。

## function to create data
foo <- function(type = "df") {
set.seed(100L)
dat = data.frame(
address = sample(1e6L, 1e7L, TRUE),
value = sample(1:5, 1e7L, TRUE, prob=c(0.5, 0.3, 0.1, 0.07, 0.03))
)
if (type == "dt") setDT(dat)
dat
}

## DT function
dt_sol <- function(x) {
unique(x, by=c("address", "value"))[, .N, by=address]
}

## dplyr function
dplyr_sol <- function(x) {
distinct(x) %>% group_by(address) %>% summarise(N = n_distinct(value))
}

此处报告的时间是对每个函数连续三次运行 system.time(.)

## benchmark timings in seconds
## pkg run-01 run-02 run-03 command
## data.table 2.4 2.3 2.4 system.time(ans1 <- dt_sol(foo("dt")))
## dplyr 15.3 16.3 15.7 system.time(ans2 <- dplyr_sol(foo()))

出于某种原因,dplyr 自动按分组变量对结果进行排序。因此,为了比较结果,我还将在 data.table 的结果中对它们进行排序:

system.time(setkey(ans1, address)) ## 0.102 seconds
identical(as.data.frame(ans1), as.data.frame(ans2)) ## TRUE

因此,data.table 在这里快了约 6 倍。

请注意,data.table 也支持 bit64:::integer64 - 由于您提到地址值太长,您也可以将它们存储为 integer64.

关于r - 在 R 中使用 'fastmatch' 包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23668593/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com