gpt4 book ai didi

r - 使用 2 个数据帧在 R 中进行有效的子集化

转载 作者:行者123 更新时间:2023-12-03 15:12:46 25 4
gpt4 key购买 nike

我在一个数据帧中有一个大的时间序列 full ,在不同的数据帧中有一个时间戳列表 test 。我需要使用 full 中时间戳周围的数据点对 test 进行子集化。我的第一直觉(作为 R 菜鸟)是写下面的,这是错误的

subs <- subset(full,(full$dt>test$dt-i) & (full$dt<test$dt+i))

查看结果我意识到 R 正在同时循环遍历两个向量,给出错误的结果。我的选择是编写一个如下所示的循环:
subs<-data.frame()
for (j in test$dt)
subs <- rbind(subs,subset(full,full$dt>(j-i) & full$dt<(j+i)))

我觉得可能有更好的方法来做循环, this article 恳求我们尽可能避免 R 循环。另一个原因是我可能会遇到性能问题,因为这将是优化算法的核心。任何来自大师的建议将不胜感激。

编辑:

这是一些可重现的代码,显示了错误的方法以及有效但可能更好的方法。
#create a times series
full <- data.frame(seq(1:200),rnorm(200,0,1))
colnames(full)<-c("dt","val")

#my smaller array of points of interest
test <- data.frame(seq(5,200,by=23))
colnames(test)<-c("dt")

# my range around the points of interset
i<-3

#the wrong approach
subs <- subset(full,(full$dt>test$dt-i) & (full$dt<test$dt+i))

#this works, but not sure this is the best way to go about it
subs<-data.frame()
for (j in test$dt)
subs <- rbind(subs,subset(full,full$dt>(j-i) & full$dt<(j+i)))

编辑:
我更新了这些值以更好地反射(reflect)我的用例,并且我看到 @mrdwab 的解决方案出人意料地大幅领先。

我正在使用@mrdwab 的基准代码,初始化如下:
set.seed(1)

full <- data.frame(
dt = 1:15000000,
val = floor(rnorm(15000000,0,1))
)


test <- data.frame(dt = floor(runif(24,1,15000000)))

i <- 500

基准是:
       test replications elapsed relative
2 mrdwab 2 1.31 1.00000
3 spacedman 2 69.06 52.71756
1 andrie 2 93.68 71.51145
4 original 2 114.24 87.20611

完全出乎意料。头脑=吹。有人可以在这个黑暗的角落里照亮一些光线并阐明正在发生的事情。

重要提示:正如@mrdwab 在下面指出的,他的解决方案仅在向量为整数时才有效。如果没有,@spacedman 有正确的解决方案

最佳答案

我不知道它是否更有效率,但我认为你也可以做这样的事情来得到你想要的:

subs <- apply(test, 1, function(x) c((x-2):(x+2)))
full[which(full$dt %in% subs), ]

我不得不将您的“3”调整为“2”,因为 x 将包含在两种方式中。

基准测试(只是为了好玩)

@Spacedman 带路!

一、需要的数据和功能。
## Data
set.seed(1)

full <- data.frame(
dt = 1:200,
val = rnorm(200,0,1)
)

test <- data.frame(dt = seq(5,200,by=23))

i <- 3

## Spacedman's functions
cf = function(l,u){force(l);force(u);function(x){x>l & x<u}}
OR = function(f1,f2){force(f1);force(f2);function(x){f1(x)|f2(x)}}
funs = mapply(cf,test$dt-i,test$dt+i)
anyF = Reduce(OR,funs)

二是对标。
## Benchmarking
require(rbenchmark)
benchmark(andrie = do.call(rbind,
lapply(test$dt,
function(j) full[full$dt > (j-i) &
full$dt < (j+i), ])),
mrdwab = {subs <- apply(test, 1,
function(x) c((x-(i-1)):(x+(i-1))))
full[which(full$dt %in% subs), ]},
spacedman = full[anyF(full$dt),],
original = {subs <- data.frame()
for (j in test$dt)
subs <- rbind(subs,
subset(full, full$dt > (j-i) &
full$dt < (j+i)))},
columns = c("test", "replications", "elapsed", "relative"),
order = "relative")
# test replications elapsed relative
# 3 spacedman 100 0.064 1.000000
# 2 mrdwab 100 0.105 1.640625
# 1 andrie 100 0.520 8.125000
# 4 original 100 1.080 16.875000

关于r - 使用 2 个数据帧在 R 中进行有效的子集化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12137194/

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