我有一个时间序列数据的数据框,每天观察温度.我需要创建一个虚拟变量,计算每天温度高于5C的阈值.这本身很容易,但存在一个附加条件:计数仅在超过阈值连续十天后开始计数.这是一个示例数据帧:
df <- data.frame(date = seq(365),
temp = -30 + 0.65*seq(365) - 0.0018*seq(365)^2 + rnorm(365))
Run Code Online (Sandbox Code Playgroud)
我想我已经完成了,但是我喜欢的循环太多了.这就是我做的:
df$dummyUnconditional <- 0
df$dummyHead <- 0
df$dummyTail <- 0
for(i in 1:nrow(df)){
if(df$temp[i] > 5){
df$dummyUnconditional[i] <- 1
}
}
for(i in 1:(nrow(df)-9)){
if(sum(df$dummyUnconditional[i:(i+9)]) == 10){
df$dummyHead[i] <- 1
}
}
for(i in 9:nrow(df)){
if(sum(df$dummyUnconditional[(i-9):i]) == 10){
df$dummyTail[i] <- 1
}
}
df$dummyConditional <- ifelse(df$dummyHead == 1 | df$dummyTail == 1, 1, 0)
Run Code Online (Sandbox Code Playgroud)
有谁能建议更简单的方法吗?
这是一个基本R选项使用rle:
df$dummy <- with(rle(df$temp > 5), rep(as.integer(values & lengths >= 10), lengths))
Run Code Online (Sandbox Code Playgroud)
一些解释:该任务是运行长度encoding(rle)函数imo 的经典用例.我们首先检查值temp是否大于5(创建逻辑向量)并应用于rle该向量导致:
> rle(df$temp > 5)
#Run Length Encoding
# lengths: int [1:7] 66 1 1 225 2 1 69
# values : logi [1:7] FALSE TRUE FALSE TRUE FALSE TRUE ...
Run Code Online (Sandbox Code Playgroud)
现在,我们要找出那些情况下,valuesIS TRUE(即温度大于5),并在同一时间lengths大于10(即连续至少十个temp值大于5).我们这样做是通过运行:
values & lengths >= 10
Run Code Online (Sandbox Code Playgroud)
最后,因为我们想要返回一个长度相同的向量nrow(df),我们使用rep(..., lengths)和as.integer返回1/0而不是TRUE/ FALSE.
我认为你可以在动物园包中使用简单的ifelse和roll apply函数的组合来实现你想要的.最后一步只是将结果填充到第一个N-1天,其中没有足够的信息来填充窗口.
library(zoo)
df <- data.frame(date = seq(365),
temp = -30 + 0.65*seq(365) - 0.0018*seq(365)^2 + rnorm(365))
df$above5 <- ifelse(df$temp > 5, 1, 0)
temp <- rollapply(df$above5, 10, sum)
df$conseq <- c(rep(0, 9),temp)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1538 次 |
| 最近记录: |