循环代码,根据R中的每日最大值和最小值模拟每小时温度

循环代码,根据R中的每日最大值和最小值模拟每小时温度,r,loops,iteration,modeling,temperature,R,Loops,Iteration,Modeling,Temperature,我的最终目标是使用R从1986年到2017年的每日最高温度和最低温度对每小时温度进行建模。我已经成功地为一个日期的数据编写了代码,但是我在跨多个日期应用此代码时遇到了问题 我从国家资源保护局(NRCS)获取了我的重点站点的每日温度数据: 以下是此处发布的模型: 莱考斯基,D.S.,温克尔曼,L.J.,贝克,J.M.,贝克,D.G.1989。 根据每日最低和最高气温计算的每小时气温的准确性。 农业和森林气象学。46:193-209 我编写了以下代码,它非常适合对一天的每小时温度数据进行建模: #

我的最终目标是使用R从1986年到2017年的每日最高温度和最低温度对每小时温度进行建模。我已经成功地为一个日期的数据编写了代码,但是我在跨多个日期应用此代码时遇到了问题

我从国家资源保护局(NRCS)获取了我的重点站点的每日温度数据:

以下是此处发布的模型:

莱考斯基,D.S.,温克尔曼,L.J.,贝克,J.M.,贝克,D.G.1989。 根据每日最低和最高气温计算的每小时气温的准确性。 农业和森林气象学。46:193-209

我编写了以下代码,它非常适合对一天的每小时温度数据进行建模:

#create df for SINGLE DATE. 
#The actual data frame that I wish to model temperatures from will be exactly like this 
#but with 11,689 rows.

d8a <- data.frame(
  Day.of.Year = 213, 
  Date = as.Date("01-Aug-2011",format = "%d-%b-%Y"), 
  SunRise_decimal = 4.9, 
  Air.Temperature.Minimum..degC. = 8.0, 
  Air.Temperature.Maximum..degC. = 22.1
) 

#create matrix to serve as repository for modeled hourly temp data

OneDay <- data.frame(OneDay <- matrix(0, ncol = 0, nrow = 24))

hour <- OneDay$hour <- c(0:23)
rise <- OneDay$sunrise <- d8a$SunRise_decimal
tmax <- OneDay$tmax <- d8a$Air.Temperature.Maximum..degC.
tmin <- OneDay$tmin <- d8a$Air.Temperature.Minimum..degC.
tavg <- OneDay$tavg <- (OneDay$tmax + OneDay$tmin) / 2
peakhour <- OneDay$peakhour <- 14
amp <- OneDay$amp <- (OneDay$tmax - OneDay$tmin)/2

#Now for the actual modelling:

OneDay$tmod <- ifelse(hour < rise, tavg + amp * cos(pi * (hour + 10) / (10 + rise)), 
           ifelse(hour > peakhour, tavg + amp * cos(pi * (hour - peakhour) / (10 + rise)),
                    ifelse(hour >= rise, tavg - amp * cos(pi * (hour - rise) / (peakhour - rise)),
                                                               99999)))

plot(tmod ~ hour, data = OneDay, pch = 19, cex = 1.5, ylim = c(8,23), 
    main = "01 August 2011", las = 1, ylab = "Temp (C)", xlab = "Hour of Day")
lines(tmod ~ hour, data = OneDay)
#为单个日期创建df。
#我希望从中模拟温度的实际数据帧将与此完全相同
#但是有11689行。

d8a一个非常简单的方法是for循环,我想你也可以用apply做一些事情,但我想循环在这里就足够了,特别是因为它只有11000次计算(…)

假设您的数据保存在数据帧d8a中

    OneDay<-list()
for(i in 1:nrow(d8a)){
OneDay[[i]] <- data.frame(OneDay[[i]] <- matrix(0, ncol = 8, nrow = 24))

hour <- OneDay[[i]][,1] <- c(0:23)
rise <- OneDay[[i]][,2] <- d8a$SunRise_decimal[i]
tmax <- OneDay[[i]][,3] <- d8a$Air.Temperature.Maximum..degC.[i]
tmin <- OneDay[[i]][,4] <- d8a$Air.Temperature.Minimum..degC.[i]
tavg <- OneDay[[i]][,5] <- (OneDay[[i]][,3] + OneDay[[i]][,4]) / 2
peakhour <- OneDay[[i]][,6] <- 14
amp <- OneDay[[i]][,7] <- (OneDay[[i]][,3] - OneDay[[i]][,4])/2

#Now for the actual modelling:

OneDay[[i]][,8] <- ifelse(hour < rise, tavg + amp * cos(pi * (hour + 10) / (10 + rise)), 
           ifelse(hour > peakhour, tavg + amp * cos(pi * (hour - peakhour) / (10 + rise)),
                    ifelse(hour >= rise, tavg - amp * cos(pi * (hour - rise) / (peakhour - rise)),
                                                               99999)))
}

OneDay看起来像是
data。table
可以让这变得简单

首先,将建模逻辑包含在函数中:

ModelHourly <- function(hour, rise, tmax, tmin) {
  peakhour <- 14
  tavg <- (tmax + tmin) / 2
  amp <- (tmax - tmin) / 2
  tmod <- ifelse(hour < rise, tavg + amp * cos(pi * (hour + 10) / (10 + rise)), 
         ifelse(hour > peakhour, tavg + amp * cos(pi * (hour - peakhour) / (10 + rise)),
                ifelse(hour >= rise, tavg - amp * cos(pi * (hour - rise) / (peakhour - rise)),
                       99999))) 
  return(tmod)
}
现在我们需要将每一行复制24次,并用
0:23
填充它。从概念上讲,这似乎是最简单的方法,但可能有更巧妙的方法:

hourly <- dat[, .(hour=0:23), .(Date)]
dat <- merge(hourly, dat, by='Date')

如果你
绘图(dat$modeled)
你会看到两条正弦曲线

谢谢@HarlandMason!这是有效的和有教育意义的!很好用,谢谢你,贝金纳。现在,我使用@HarlandMason的解决方案,因为它还绑定/整理所有日期。不过,我将保留并研究您的解决方案,以帮助我解决使用for循环的问题。我早就应该。。。
library('data.table')
dat <- as.data.table(dat)
hourly <- dat[, .(hour=0:23), .(Date)]
dat <- merge(hourly, dat, by='Date')
dat[, modeled := ModelHourly(hour, SunRise_decimal, Air.Temperature.Maximum..degC., Air.Temperature.Minimum..degC.)]