gpt4 book ai didi

R:具有给定坐标的快速滑动窗口

转载 作者:行者123 更新时间:2023-12-04 04:06:24 24 4
gpt4 key购买 nike

我有一个数据表,nrow大约是一两百万,ncol大约是200。

行中的每个条目都有一个与之关联的坐标。

数据的微小部分:

[1,] -2.80331471  -0.8874522 -2.34401863   -3.811584   -2.1292443
[2,] 0.03177716 0.2588624 0.82877467 1.955099 0.6321881
[3,] -1.32954665 -0.5433407 -2.19211837 -2.342554 -2.2142461
[4,] -0.60771429 -0.9758734 0.01558774 1.651459 -0.8137684

前4行的坐标:
9928202 9928251 9928288 9928319

我想要的是一个给定数据和窗口大小的函数,该函数将返回相同大小的数据表,并在每列上应用平均滑动窗口。换句话说,对于每行条目i,它将找到坐标在coords [i] -windsize和coords [i] + windsize之间的条目,并将初始值替换为该间隔内的值的平均值(每列分别) 。

速度是这里的主要问题。

这是我第一次使用这种功能。
doSlidingWindow <- function(intensities, coords, windsize) {
windHalfSize <- ceiling(windsize/2)
### whole range inds
RANGE <- integer(max(coords)+windsize)
RANGE[coords] <- c(1:length(coords)[1])

### get indeces of rows falling in each window
COORDS <- as.list(coords)
WINDOWINDS <- sapply(COORDS, function(crds){ unique(RANGE[(crds-windHalfSize):
(crds+windHalfSize)]) })

### do windowing

wind_ints <- intensities
wind_ints[] <- 0
for(i in 1:length(coords)) {
wind_ints[i,] <- apply(as.matrix(intensities[WINDOWINDS[[i]],]), 2, mean)
}
return(wind_ints)
}

最后一个for循环之前的代码非常快,它为我提供了我需要用于每个条目的索引列表。但是然后一切都崩溃了,因为我需要研磨一百万遍for循环,获取我的数据表的子集,并确保我有多于一行的内容,以便能够在apply内部一次处理所有列。

我的第二种方法是将实际值粘贴在RANGE列表中,用零填充空白,然后从zoo包中进行rollmean,每列重复一次。但这是多余的,因为rollmean将克服所有空白,最后我将仅使用原始坐标的值。

如果不使用C就可以更快地进行任何帮助,将不胜感激。

最佳答案

数据生成:

N <- 1e5 # rows
M <- 200 # columns
W <- 10 # window size

set.seed(1)
intensities <- matrix(rnorm(N*M), nrow=N, ncol=M)
coords <- 8000000 + sort(sample(1:(5*N), N))

我对基准进行了较小修改的原始功能:
doSlidingWindow <- function(intensities, coords, windsize) {
windHalfSize <- ceiling(windsize/2)
### whole range inds
RANGE <- integer(max(coords)+windsize)
RANGE[coords] <- c(1:length(coords)[1])

### get indices of rows falling in each window
### NOTE: Each elements of WINDOWINDS holds zero. Not a big problem though.
WINDOWINDS <- sapply(coords, function(crds) ret <- unique(RANGE[(crds-windHalfSize):(crds+windHalfSize)]))

### do windowing
wind_ints <- intensities
wind_ints[] <- 0
for(i in 1:length(coords)) {
# CORRECTION: When it's only one row in window there was a trouble
wind_ints[i,] <- apply(matrix(intensities[WINDOWINDS[[i]],], ncol=ncol(intensities)), 2, mean)
}
return(wind_ints)
}

可能的解决方案:

1)data.table

众所周知, data.table具有子设置的快速性,但是 this page(以及其他与滑动窗口有关的)表明,事实并非如此。的确, data.table代码很优雅,但是很慢:
require(data.table)
require(plyr)
dt <- data.table(coords, intensities)
setkey(dt, coords)
aaply(1:N, 1, function(i) dt[WINDOWINDS[[i]], sapply(.SD,mean), .SDcols=2:(M+1)])

2)foreach + doSNOW

基本例程易于并行运行,因此,我们可以从中受益:
require(doSNOW)
doSlidingWindow2 <- function(intensities, coords, windsize) {
NC <- 2 # number of nodes in cluster
cl <- makeCluster(rep("localhost", NC), type="SOCK")
registerDoSNOW(cl)

N <- ncol(intensities) # total number of columns
chunk <- ceiling(N/NC) # number of columns send to the single node

result <- foreach(i=1:NC, .combine=cbind, .export=c("doSlidingWindow")) %dopar% {
start <- (i-1)*chunk+1
end <- ifelse(i!=NC, i*chunk, N)
doSlidingWindow(intensities[,start:end], coords, windsize)
}

stopCluster(cl)
return (result)
}

基准测试显示我的双核处理器显着提高了速度:
system.time(res <- doSlidingWindow(intensities, coords, W))
# user system elapsed
# 306.259 0.204 307.770
system.time(res2 <- doSlidingWindow2(intensities, coords, W))
# user system elapsed
# 1.377 1.364 177.223
all.equal(res, res2, check.attributes=FALSE)
# [1] TRUE

3)Rcpp

是的,我知道您问“不去C”。但是,请看看。这段代码是内联的,相当简单:
require(Rcpp)
require(inline)
doSlidingWindow3 <- cxxfunction(signature(intens="matrix", crds="numeric", wsize="numeric"), plugin="Rcpp", body='
#include <vector>
Rcpp::NumericMatrix intensities(intens);
const int N = intensities.nrow();
const int M = intensities.ncol();
Rcpp::NumericMatrix wind_ints(N, M);

std::vector<int> coords = as< std::vector<int> >(crds);
int windsize = ceil(as<double>(wsize)/2);

for(int i=0; i<N; i++){
// Simple search for window range (begin:end in coords)
// Assumed that coords are non-decreasing
int begin = (i-windsize)<0?0:(i-windsize);
while(coords[begin]<(coords[i]-windsize)) ++begin;
int end = (i+windsize)>(N-1)?(N-1):(i+windsize);
while(coords[end]>(coords[i]+windsize)) --end;

for(int j=0; j<M; j++){
double result = 0.0;
for(int k=begin; k<=end; k++){
result += intensities(k,j);
}
wind_ints(i,j) = result/(end-begin+1);
}
}

return wind_ints;
')

基准:
system.time(res <- doSlidingWindow(intensities, coords, W))
# user system elapsed
# 306.259 0.204 307.770
system.time(res3 <- doSlidingWindow3(intensities, coords, W))
# user system elapsed
# 0.328 0.020 0.351
all.equal(res, res3, check.attributes=FALSE)
# [1] TRUE

我希望结果能给人以启发。虽然数据适合内存,但 Rcpp版本非常快。说,有了 N <- 1e6M <-100,我得到了:
   user  system elapsed 
2.873 0.076 2.951

自然地,R开始使用交换后,一切都会变慢。对于无法容纳在内存中的非常大的数据,您应该考虑使用 sqldfffbigmemory

关于R:具有给定坐标的快速滑动窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14192630/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com