我必须在大约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
Run Code Online (Sandbox Code Playgroud)
我想要做的是找到Type每个的唯一值的数量Address.有数百万行数据,大约有1MM唯一的地址值...平均而言,每个地址在数据集中出现约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
}
Run Code Online (Sandbox Code Playgroud)
但是,上面的代码效率不高 - 如果我循环超过1MM的值,我估计这需要10-15个小时.
我也在循环中试过这个......但它并没有快得多.
b <- which(A$Address == uvals[i])
Run Code Online (Sandbox Code Playgroud)
我知道有一种更优雅/更快的方式,我对R来说相当新,并且会感激任何帮助.
这可以使用unique函数in data.table,然后是聚合来完成.我将使用或多或少的@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))
)
Run Code Online (Sandbox Code Playgroud)
require(data.table) ## >= 1.9.2
dat.u = unique(setDT(dat), by=c("address", "value"))
ans = dat.u[, .N, by=address]
Run Code Online (Sandbox Code Playgroud)
- 该
setDT函数将a转换data.frame为data.table引用(速度非常快).unique在data.table上运行的函数唤起了这个unique.data.table方法,与之相比,这个方法非常快base:::unique.现在,我们只有type每个人的唯一值address.- 剩下要做的就是聚合或分组,
address并获得每组中的观察数量.在by=address通过部分基团address和.N是一个内置的data.table变量,其提供用于该组观测值的数目.
我将创建函数生成数据,data.table并data.frame以基准data.table对答案dplyr由@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))
}
Run Code Online (Sandbox Code Playgroud)
这里报告的时间是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()))
Run Code Online (Sandbox Code Playgroud)
出于某种原因,dplyr通过分组变量自动对结果进行排序.因此,为了比较结果,我还将在以下结果中对它们进行排序data.table:
system.time(setkey(ans1, address)) ## 0.102 seconds
identical(as.data.frame(ans1), as.data.frame(ans2)) ## TRUE
Run Code Online (Sandbox Code Playgroud)
所以,data.table这里要快6倍.
请注意,bit64:::integer64也支持data.table- 因为您提到地址值太长,您也可以将它们存储为integer64.