使用以下代码;
c <- NULL for (a in 1:4){ b <- seq(from = a, to = a + 5) c <- rbind(c,b) } c <- rbind(c,c); rm(a,b)
结果在这个矩阵中,
> c [,1] [,2] [,3] [,4] [,5] [,6] b 1 2 3 4 5 6 b 2 3 4 5 6 7 b 3 4 5 6 7 8 b 4 5 6 7 8 9 b 1 2 3 4 5 6 b 2 3 4 5 6 7 b 3 4 5 6 7 8 b 4 5 6 7 8 9
如何为匹配特定输入的行返回行索引?
例如,搜索字词为,
z <- c(3,4,5,6,7,8)
我需要以下退回,
[1] 3 7
这将用于与时间步长列相关的相当大的测试数据数据帧,以通过累积匹配行的时间步骤来减少数据.
问题得到了别人的好评.由于我的数据集大小(9.5M行),我想出了一个有效的方法,需要几个步骤.
1)对包含时间步长的大数据帧"dc"进行排序,以便在第1列中累积.
dc <- dc[order(dc[,2],dc[,3],dc[,4],dc[,5],dc[,6],dc[,7],dc[,8]),]
2)创建具有唯一条目的新数据框(第1列除外).
dcU <- unique(dc[,2:8])
3)写入Rcpp(C++)函数以循环通过唯一数据帧,该数据帧在行相等时迭代原始数据帧累积时间,并且当识别出不相等的行时索引到下一个循环步骤.
require(Rcpp) getTsrc <- ' NumericVector getT(NumericMatrix dc, NumericMatrix dcU) { int k = 0; int n = dcU.nrow(); NumericVector tU(n); for (int i = 0; i4)将函数输入转换为矩阵.
dc1 <- as.matrix(dc) dcU1 <- as.matrix(dcU)5)运行函数并计时(返回匹配唯一数据帧的时间向量)
pt <- proc.time() t <- getT(dc1, dcU1) print(proc.time() - pt) user system elapsed 0.18 0.03 0.206)自我高五和更多的咖啡.
1> rbatt..:@jeremycg的答案肯定会有效,如果你有很多列和几行,它的速度很快.但是,如果您通过避免
apply()
在行维度上使用而拥有大量行,则可能会更快一些.这是另一种选择:
l <- unlist(apply(c, 2, list), recursive=F) logic <- mapply(function(x,y)x==y, l, z) which(.rowSums(logic, m=nrow(logic), n=ncol(logic)) == ncol(logic)) [1] 3 7它的工作原理是首先将每列转换为列表.然后,它获取每个列列表并在其中搜索相应的元素
z
.在最后一步中,您将找出哪些行具有相应匹配的所有列z
.即使最后一步是行式操作,通过使用.rowSums
(介于.
前面),我们可以指定矩阵的尺寸,并获得加速.让我们测试两种方法的时间.
功能
f1 <- function(){ which(apply(c, 1, function(x) all(x == z))) } f2 <- function(){ l <- unlist(apply(c, 2, list), recursive=F) logic <- mapply(function(x,y)x==y, l, z) which(.rowSums(logic, m=nrow(logic), n=ncol(logic)) == ncol(logic)) }有8行(示例中为暗淡):
> time <- microbenchmark(f1(), f2()) > time Unit: microseconds expr min lq mean median uq max neval cld f1() 21.147 21.8375 22.86096 22.6845 23.326 30.443 100 a f2() 42.310 43.1510 45.13735 43.7500 44.438 137.413 100 b有80行:
Unit: microseconds expr min lq mean median uq max neval cld f1() 101.046 103.859 108.7896 105.1695 108.3320 166.745 100 a f2() 93.631 96.204 104.6711 98.1245 104.7205 236.980 100 a有800行:
> time <- microbenchmark(f1(), f2()) > time Unit: microseconds expr min lq mean median uq max neval cld f1() 920.146 1011.394 1372.3512 1042.1230 1066.7610 31290.593 100 b f2() 572.222 579.626 593.9211 584.5815 593.6455 1104.316 100 a请注意,我的时序评估每个只有100个重复,虽然这些结果是重复的,但在两个方法相等之前,所需的行数有一点变化.
无论如何,我认为一旦你有100多行,我的方法可能会更快.
另外,请注意,您不能简单地转置
c
以f1()
加快速度.首先,t()
占用时间; 第二,因为你要比较z
,你只需要按列进行(转置后)比较,所以在这一点上没有什么不同.最后,我确信有更快的方法来做到这一点.我的回答只是我想到的第一件事,并且不需要安装任何软件包.如果你想使用data.table,这可能会快得多.此外,如果您有很多列,您甚至可以并行化此过程(尽管值得一提的是数据集必须是巨大的).
如果您的数据无法容忍这些时间,则可以考虑使用数据集的维度进行报告.