当前位置:  开发笔记 > 编程语言 > 正文

返回其元素(列)都与引用向量匹配的行的索引

如何解决《返回其元素(列)都与引用向量匹配的行的索引》经验,为你挑选了1个好方法。

使用以下代码;

  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; i

4)将函数输入转换为矩阵.

  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.20 

6)自我高五和更多的咖啡.



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多行,我的方法可能会更快.

另外,请注意,您不能简单地转置cf1()加快速度.首先,t()占用时间; 第二,因为你要比较z,你只需要按列进行(转置后)比较,所以在这一点上没有什么不同.

最后,我确信有更快的方法来做到这一点.我的回答只是我想到的第一件事,并且不需要安装任何软件包.如果你想使用data.table,这可能会快得多.此外,如果您有很多列,您甚至可以并行化此过程(尽管值得一提的是数据集必须是巨大的).

如果您的数据无法容忍这些时间,则可以考虑使用数据集的维度进行报告.

推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有