我遇到的问题似乎与之前提出的一些问题类似,但有些不同,以至于我无法找到优雅的解决方案。
我有一组需要与理论值数据库匹配的真实数据。我想基于多组多个条件进行过滤。例如,如果我有以下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()内部工作的单个表达式来确定值是否在一个范围内的方法,那将是锦上添花。也许子集是使用的错误功能,但在这种情况下没关系。
答案 0 :(得分:0)
您可以使用outer
来计算df
和realdata
之间的所有成对差异,并检查x
和y
是否小于容差
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
lapply(1:ncol(mat), function(i) df[mat[,i], ])
# return all matched data
df[row(mat)[mat], ]
答案 1 :(得分:0)
这是一个带矢量化测试的隐式循环:
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
合并它