我有一个dataframe与日期/时间(时间序列),地点(分组变量)和价值。我已经确定了不同的“浪涌”的开始时间-定义为在15分钟内>=2的值的变化。对于每一个浪涌时间,我尝试的日期/时间的值福尔斯到(或低于)的浪涌开始(即浪涌结束)。
我可以通过使用递归循环函数('find.next.smaller'来自这个问题-In a dataframe, find the index of the next smaller value for each element of a column)来实现这一点。这在较小的 Dataframe 上工作得很好,但不是一个大的。我收到错误消息“错误:C堆栈使用量15925584太接近极限”。看过其他类似的问题(例如,Error: C stack usage is too close to the limit),我不认为这是一个无限递归函数的问题,而是一个内存问题。但是我不知道如何使用shell(或powershell)来做到这一点。我想知道是否有其他方法?通过调整我的记忆或下面的功能?
一些示例代码:
###df formatting
library(dplyr)
df <- data.frame("Date_time" =seq(from=as.POSIXct("2022-01-01 00:00") , by= 15*60, to=as.POSIXct("2022-01-01 07:00")),
"Site" = rep(c("Site A", "Site B"), each = 29),
"Value" = c(10,10.1,10.2,10.3,12.5,14.8,12.4,11.3,10.3,10.1,10.2,10.5,10.4,10.3,14.7,10.1,
16.7,16.3,16.4,14.2,10.2,10.1,10.3,10.2,11.7,13.2,13.2,11.1,11.4,
rep(10.3,times=29)))
df <- df %>% group_by(Site) %>% mutate(Lead_Value = lead(Value))
df$Surge_start <- NA
df[which(df$Lead_Value - df$Value >=2),"Surge_start"] <-
paste("Surge",seq(1,length(which(df$Lead_Value - df$Value >=2)),1),sep="")
###Applying the 'find.next.smaller' function
find.next.smaller <- function(ini = 1, vec) {
if(length(vec) == 1) NA
else c(ini + min(which(vec[1] >= vec[-1])),
find.next.smaller(ini + 1, vec[-1]))
} # the recursive function will go element by element through the vector and find out
# the index of the next smaller value.
df$Date_time <- as.character(df$Date_time)
Output <- df %>% group_by(Site) %>% mutate(Surge_end = ifelse(grepl("Surge",Surge_start),Date_time[find.next.smaller(1, Value)],NA))
###This works fine
df2 <- do.call("rbind", replicate(1000, df, simplify = FALSE))
Output2 <- df2 %>% group_by(Site) %>% mutate(Surge_end = ifelse(grepl("Surge",Surge_start),Date_time[find.next.smaller(1, Value)],NA))
####This does not work
2条答案
按热度按时间2uluyalo1#
我建议你不需要递归。
mdfafbf12#
可能递归使用了太多的内存,你可能更喜欢向量化/循环的方法,即使它需要更长的时间。下面我对你的功能做了一些修改,并创建了一些选项。
部分选项
原件:
矢量化的构建块:
使用for循环:
使用
Vectorize()
:带
purrr::map
:对比:
我们可以看到,即使递归更快,它也会使用更多的内存,这可能是你出错的原因。
可能还有更好的选择,我只是想提出一些类似于你原来的选择。
应用到问题中
您还可以使用
Date_time[find.next.smaller_map(n(), Value)]
或Date_time[find.next.smaller_vec(1:n(), Value)]
。