【问题标题】:Subset data frame in R based on matching multiple ranges for multiple variables基于匹配多个变量的多个范围,R中的子集数据框
【发布时间】:2014-10-21 00:54:33
【问题描述】:

我有一个问题似乎与之前关于 SO 的一些问题有点相似,但又完全不同,以至于我无法找到一个优雅的解决方案。

我有一组需要与理论值数据库匹配的真实数据。我想根据多组多个条件进行过滤。例如,如果我有以下理论值的data.frame,

df <- data.frame(x=c(10,13,16,22,28,30), y=c(1:6))
> df
   x y
1 10 1
2 13 2
3 16 3
4 22 4
5 28 5
6 30 6

我有以下真实数据,

realdata <- data.frame(x=c(10.05, 13.06, 22.01),y=c(1.02, 1.99, 3.96))
> realdata
      x    y
1 10.05 1.02
2 13.06 1.99
3 22.01 3.96

我可以通过以下方式轻松搜索哪些理论行与我的真实数据中的行对应:

tolerance <- .10
subset(df, x>(realdata[1,1]-tolerance) & x<(realdata[1,1]+tolerance) & 
+ y>(realdata[1,2]-tolerance) & y<(realdata[1,2]+tolerance))
subset(df, x>(realdata[2,1]-tolerance) & x<(realdata[2,1]+tolerance) & 
+ y>(realdata[2,2]-tolerance) & y<(realdata[2,2]+tolerance))
#...etc for each row of real data

但是有什么方法可以在不编写循环的情况下对我的真实数据中的所有行执行此操作?基本上,我想在给定的容差内找到与我的真实数据中的任何一行相对应的所有理论行。实际上,我的理论表和实际表有数十万个观察值,这是我经常做的事情,所以我认为速度很重要。

另外,如果有人知道一种方法来确定一个值是否在一个范围内,使用在 subset() 中工作的单个表达式,那将是锦上添花。不过,也许子集是错误的函数,在这种情况下没关系。

【问题讨论】:

  • 旁白:一般来说,您希望远离subset 而使用[,尤其是在您正在编程时

标签: r filter subset


【解决方案1】:

您可以使用outer 计算dfrealdata 之间的所有成对差异,并检查xy 是否都小于容差

tolerance <- .10

# x
xx <- abs(outer(df$x, realdata$x, "-")) < tolerance
# y
yy <- abs(outer(df$y, realdata$y, "-")) < tolerance

# if both are within the tolerance the sum of xx and yy will be 2
(mat <- xx + yy > 1)
#      [,1]  [,2]  [,3]
#[1,]  TRUE FALSE FALSE
#[2,] FALSE  TRUE FALSE
#[3,] FALSE FALSE FALSE
#[4,] FALSE FALSE  TRUE
#[5,] FALSE FALSE FALSE
#[6,] FALSE FALSE FALSE

所以mat 的第一列显示df 的哪些行在容差范围内(在本例中为第一列)。

按照realdata的行顺序返回df中的匹配行相当不雅

lapply(1:ncol(mat), function(i) df[mat[,i], ])

# return all matched data
df[row(mat)[mat], ]

【讨论】:

    【解决方案2】:

    这是一个带有矢量化测试的隐式循环:

     apply( realdata, 1, 
           function(x)  abs( x[1] - df[,1] ) < tolerance & 
                         abs( x[2] - df[,2]) <tolerance )
     #------------------------
          [,1]  [,2]  [,3]
    [1,]  TRUE FALSE FALSE
    [2,] FALSE  TRUE FALSE
    [3,] FALSE FALSE FALSE
    [4,] FALSE FALSE  TRUE
    [5,] FALSE FALSE FALSE
    [6,] FALSE FALSE FALSE
    

    这样做没有应用函数:

    > kronecker( as.matrix(df), as.matrix(realdata), function(x,y) { abs(x -y) <tolerance} )[,c(1,4)]
           [,1]  [,2]
     [1,]  TRUE  TRUE
     [2,] FALSE FALSE
     [3,] FALSE FALSE
     [4,] FALSE FALSE
     [5,]  TRUE  TRUE
     [6,] FALSE FALSE
     [7,] FALSE FALSE
     [8,] FALSE FALSE
     [9,] FALSE FALSE
    [10,] FALSE FALSE
    [11,] FALSE FALSE
    [12,]  TRUE  TRUE
    [13,] FALSE FALSE
    [14,] FALSE FALSE
    [15,] FALSE FALSE
    [16,] FALSE FALSE
    [17,] FALSE FALSE
    [18,] FALSE FALSE
    

    您可以使用 rowSums(.) == 2 合并它

    【讨论】:

      猜你喜欢
      • 2016-03-29
      • 1970-01-01
      • 2020-02-25
      • 2015-09-16
      • 1970-01-01
      • 2022-06-17
      • 2019-09-17
      • 1970-01-01
      • 2018-12-06
      相关资源
      最近更新 更多