这是使用data.table
Arun优雅回答的替代方法。我决定后,因为它包含了额外的两个方面是你的问题的重要考虑因素:
浮点比较:比较,看是否有浮点值处于区间需要考虑廿四的计算间隔时出现错误。这是比较实数的浮点表示的一般问题。在R的上下文中参见this和this。下面在函数in.interval
中实现该比较。
多个匹配:如果间隔重叠,则您的间隔匹配条件可能会导致多个匹配。以下假定,您只需要第一次匹配(关于每个txt.import.matrix
矩阵增加的行)。这在功能match.interval
中实现,并在后面的注释中进行了解释。如果你想得到符合你的标准的区域的平均值,就需要其他逻辑。
为了找到从txt.import.matrix
在一个矩阵中的匹配列(个),在矩阵reduced.list.pre.filtering
每一行,下面的代码向量化的比较函数在所有列举的双行中的reduced.list.pre.filtering
和之间的空间中的应用程序矩阵从txt.import.matrix
。从功能上来说,这与Arun使用data.table
的non-equi
连接的解决方案相同;但是,non-equi
联接功能更为通用,而且即使在此应用程序中,data.table
实现最有可能针对内存使用情况和速度进行更好的优化。
in.interval <- function(x, center, deviation, tol = .Machine$double.eps^0.5) {
return (abs(x-center) <= (deviation + tol))
}
match.interval <- function(r, t) {
r.rt <- rep(r[,1], each=nrow(t))
t.rt <- rep(t[,2], times=nrow(r))
r.mz <- rep(r[,2], each=nrow(t))
t.mz <- rep(t[,4], times=nrow(r)) ## 1.
ind <- which(in.interval(r.rt, t.rt, 0.02) &
in.interval(r.mz, t.mz, 0.0002))
r.ind <- floor((ind - 1)/nrow(t)) + 1 ## 2.
dup <- duplicated(r.ind)
r.ind <- r.ind[!dup]
t.ind <- ind[!dup] - (r.ind - 1)*nrow(t) ## 3.
return(cbind(r.ind,t.ind))
}
get.area.matched <- function(r, t) {
match.ind <- match.interval(r, t)
area <- rep(NA,nrow(r))
area[match.ind[,1]] <- t[match.ind[,2], 3] ## 4.
return(area)
}
res <- cbind(reduced.list.pre.filtering,
do.call(cbind,lapply(txt.import.matrix,
get.area.matched,
r=reduced.list.pre.filtering))) ## 5.
colnames(res) <- c(colnames(reduced.list.pre.filtering),
sapply(seq_len(length(txt.import.matrix)),
function(i) {return(paste0("Area.[",i,"]"))})) ## 6.
print(res)
## RT. m.z. Area.[1] Area.[2]
##[1,] 1.01 358.9777 2820.1 7820.1
##[2,] 1.07 368.4238 NA 8271.8
##[3,] 2.05 284.3295 6674.0 12674.0
##[4,] 2.03 922.0092 5856.3 NA
##[5,] 3.03 261.1299 27814.6 NA
##[6,] 3.56 869.4558 NA NA
注:
该部分构造数据,以使比较函数在所有列举的对reduced.list.pre.filtering
和从txt.import.matrix
基质之间的行的空间应用的矢量化。要构建的数据是四个数组,它们是比较标准中使用的两列的重复(或展开式),其中reduced.list.pre.filtering
在来自txt.import.matrix
的每个矩阵的行维中以及在比较中使用的两列的重复标准,来自txt.import.matrix
的每个矩阵的行维数为reduced.list.pre.filtering
。这里,术语数组是指二维矩阵或一维矢量。将得到的四个阵列是:
r.rt
是reduced.list.pre.filtering
的RT.
列的复制(即,r[,1]
)中的t
t.rt
行维度是矩阵的RT.
柱的从txt.import.matrix
(复制即,t[,2]
)中的r
r.mz
行维度是reduced.list.pre.filtering
(即r[,2]
的m.z.
列在行维度复制)
t.mz
是txt.import.matrix
的矩阵的m.z.
列的复制。 t[,4]
)在r
行维度是什么重要的是,为这些数组的索引枚举所有的行对在r
和t
以同样的方式。具体而言,将这些阵列视为尺寸为M
,N
的2-D矩阵,其中M=nrow(t)
和N=nrow(r)
,行索引对应于t
的行,列索引对应于r
的行。因此,i
列(4个阵列中的每一个)的阵列值(在全部四个阵列上)是在r
和i
的第j
行之间的比较标准中使用的值第t
行。此复制过程的实现使用R功能rep
。例如,在计算r.rt
,rep
中使用each=M
,其具有将其数组输入r[,1]
作为行向量并复制该行M
行以形成M
行的效果。结果是,对应于r
中的行的每个列具有来自r
的对应行的RT.
值,并且该值对于r.rt
(该列)的所有行都是相同的,其中每个行对应于行在t
。这意味着在将r
中的该行与t
中的任何行进行比较时,将使用r
中该行的值RT.
。相反,在计算t.rt
,rep
时使用times=N
,其具有将其阵列输入作为列向量处理并复制该列以形成N
列的效果。结果是,对应于t
中的行的t.rt
中的每一行具有来自t
的对应行的RT.
值,并且该值对于t.rt
的所有列(该行的)是相同的,每个列对应于一排在r
。这意味着在将t
中的该行与r
中的任何行进行比较时,将使用t
中该行中的值RT.
。类似地,r.mz
和t.mz
的计算分别使用来自r
和t
的m.z.
列。
这执行导致M
通过N
逻辑矩阵其中i
行和第j
个柱是TRUE
如果r
的j
第一行的第i
行标准匹配的矢量比较t
,并FALSE
否则。的which()
输出是数组索引的阵列,以该逻辑比较结果矩阵,其中其元件是TRUE
。我们希望这些数组索引转换为比较结果矩阵指回r
和t
行的行和列索引。下一行从数组索引中提取列索引。注意,变量名是r.ind
以表示这些对应于r
行。我们提取这首先是因为它是在r
检测多个匹配的行很重要。
这部分处理r
中给定行的t
可能的多个匹配。多个匹配将在r.ind
中显示为重复值。如上所述,这里的逻辑仅在t
的行数增加方面保持第一次匹配。函数duplicated
返回数组中重复值的所有索引。因此,删除这些元素将做我们想要的。代码首先删除它们从r.ind
,那么它从ind
删除它们,最后计算列索引比较结果矩阵,其对应于t
的行中,使用修剪ind
和r.ind
。什么是match.interval
返回是一个矩阵,它的行被匹配的一对行索引的与它的第一列为行索引到r
和其第二列是列指数来t
。
的get.area.matched
功能只需使用结果从match.ind
来提取t
的Area
所有比赛。请注意,返回的结果是一个(列)向量,其长度等于r
中的行数并初始化为NA
。在r
这样行已在t
敌不过有一个返回的NA
Area
。
这使用lapply
超过列表txt.import.matrix
返回匹配结果Area
应用功能get.area.matched
和附加到reduced.list.pre.filtering
为列向量。同样,相应的列名也被附加并设置在结果res
中。
编辑:使用foreach
包
事后替代的实施,更好地实现使用foreach
包矢量化的比较。在本实施方式中,foreach
和magrittr
包需要
require("magrittr") ## for %>%
require("foreach")
然后用于矢量化的比较
r.rt <- rep(r[,1], each=nrow(t))
t.rt <- rep(t[,2], times=nrow(r))
r.mz <- rep(r[,2], each=nrow(t))
t.mz <- rep(t[,4], times=nrow(r)) # 1.
ind <- which(in.interval(r.rt, t.rt, 0.02) &
in.interval(r.mz, t.mz, 0.0002))
在match.interval
代码可以通过
ind <- foreach(r.row = 1:nrow(r), .combine=cbind) %:%
foreach(t.row = 1:nrow(t)) %do%
match.criterion(r.row, t.row, r, t) %>%
as.logical(.) %>% which(.)
代替其中match.criterion
定义as
match.criterion <- function(r.row, t.row, r, t) {
return(in.interval(r[r.row,1], t[t.row,2], 0.02) &
in.interval(r[r.row,2], t[t.row,4], 0.0002))
}
这更容易解析并反映正在执行的内容。请注意,嵌套的foreach
与cbind
结合返回的内容也是逻辑矩阵。最后,也可以使用foreach
执行的get.area.matched
函数在列表txt.import.matrix
应用:
res <- foreach(i = 1:length(txt.import.matrix), .combine=cbind) %do%
get.area.matched(reduced.list.pre.filtering, txt.import.matrix[[i]]) %>%
cbind(reduced.list.pre.filtering,.)
使用foreach
完整的代码如下:
require("magrittr")
require("foreach")
in.interval <- function(x, center, deviation, tol = .Machine$double.eps^0.5) {
return (abs(x-center) <= (deviation + tol))
}
match.criterion <- function(r.row, t.row, r, t) {
return(in.interval(r[r.row,1], t[t.row,2], 0.02) &
in.interval(r[r.row,2], t[t.row,4], 0.0002))
}
match.interval <- function(r, t) {
ind <- foreach(r.row = 1:nrow(r), .combine=cbind) %:%
foreach(t.row = 1:nrow(t)) %do%
match.criterion(r.row, t.row, r, t) %>%
as.logical(.) %>% which(.)
# which returns 1-D indices (row-major),
# convert these to 2-D indices in (row,col)
r.ind <- floor((ind - 1)/nrow(t)) + 1 ## 2.
# detect duplicates in r.ind and remove them from ind
dup <- duplicated(r.ind)
r.ind <- r.ind[!dup]
t.ind <- ind[!dup] - (r.ind - 1)*nrow(t) ## 3.
return(cbind(r.ind,t.ind))
}
get.area.matched <- function(r, t) {
match.ind <- match.interval(r, t)
area <- rep(NA,nrow(r))
area[match.ind[,1]] <- t[match.ind[,2], 3]
return(area)
}
res <- foreach(i = 1:length(txt.import.matrix), .combine=cbind) %do%
get.area.matched(reduced.list.pre.filtering, txt.import.matrix[[i]]) %>%
cbind(reduced.list.pre.filtering,.)
colnames(res) <- c(colnames(reduced.list.pre.filtering),
sapply(seq_len(length(txt.import.matrix)),
function(i) {return(paste0("Area.[",i,"]"))}))
希望这有助于。
谢谢爱超!事实上,你的代码对我来说有点复杂,但尝试理解它却是一个很好的挑战。它运行得非常好,我得到了我想要的输出。是的,它帮助了很多! – Vanbell
@Vanbell:谢谢。我仍在编辑帖子。明天再来看看,希望它会更清晰。当然,如果您有任何问题,请留下评论。再次,我想我应该发布指出我认为重要的问题的两个可能方面。 – aichao
好的,我在等你的帖子。我的事情,我会问你一些问题,因为它太容易复制和过去;) – Vanbell