提前感谢您的帮助。我知道也有类似的问题,但是它们都比这里要问的问题简单,因为它们按因子而不是DateTime处理分组。
我的目标是编写一个可以应用于海洋数据集中各种物理参数(<100列)的函数。每个物理参数每隔30分钟自动记录一次,并且需要进行相同的复杂摘要计算。
数据帧(df)如下:
dt par 1 par 2 par 3 par 100
2018-06-06 00:00 95.6 976 0.18 ...
2018-06-06 00:30 NA 1002 0.19 ...
2018-06-06 01:00 95.9 1019 0.20 ...
...
[regularly spaced data]
...
2018-10-31 23:00 72.4 887 NA ...
2018-10-31 23:30 72.1 889 0.17 ...
我有代码可以成功地为数据框的单个参数(1列)进行所需的计算。要将这些计算应用于其他参数,需要复制和粘贴代码,然后在该复制和粘贴的代码中更改列名。似乎有一种更好的方法可以做到这一点,例如编写一个函数(我曾尝试做)或使用data.frame(我正试图做得更好,但实际上不知道那是否可行)。我试图写一个函数。
fun = function(df,dt, par){
df1=df %>% #new dataframe to temporarily store site specific calculations
group_by(hour = cut(dt , breaks="60 min")) %>% #Cut data into 1-hour intervals
summarize(x = mean(par)) #Calulated the average for each 1-hour interval
df1$hour <- as.Date(df1$hour) #Remove time element from datetime so hourly averaged can be grouped by date
df.avg <- aggregate(df1$x, by=list(df1$hour), mean) #calculate daily average
df.max <- aggregate(df1$x, by=list(df1$hour), max) #calculate daily max
#Temporary dataframe
date=as.data.frame(df.avg$Group.1) #used to calculate 7-day rolling mean
avg=as.data.frame(df.avg$x) #used to calculate 7-day rolling mean
max=as.data.frame(df.max$x) #used to calculate 7-day rolling mean
#7-day rolling mean (centered) of average daily mean temp
calc.avg=as.data.frame(cbind(date, (rollapply(avg,7,mean,align='center',fill=NA))))
#7-day rolling mean (centered) of average daily maximum temp
calc.max=as.data.frame(cbind(date, (rollapply(max,7,mean,align='center',fill=NA))))
#Identify maximum temperatures and date of occurence based on the 7-day running mean calculation
df.avg=calc.avg[which.max(calc.avg$`df.avg$x`),]
df.max=calc.max[which.max(calc.max$`df.max$x`),]
#site-specific data as dataframe to be combined with all sites at end
calc=cbind(df.avg, df.max)
names(calc)=c("Date AVG", "Par AVG", "Date MAX", "Par Max")
nam=data.frame("Par 1 Summary")#
names(nam)="Location"
output=cbind(nam,calc)
output}
par=df$Par1
fun(df,dt,par)
这不起作用,我收到一条错误消息“参数不是数字或逻辑”。但是,如果在函数的摘要行中将文本par替换为Par 1
,则获得所需的输出。我认为可能存在一个与语法有关的问题,我没有坚持,但是无法弄清它是什么。
我最终希望获得的结果是一个包含以下信息的数据框:
Parameter Date of AVG AVG Date of MAX MAX
Par 1 2018-07-21 99.9 2018-07-25 101.1
Par 2 2018-07-03 1005 2018-07-25 1081
Par 3 2018-07-20 0.29 2018-07-27 0.45
...
[Par 4 - 99]
...
Par 100 ... ... ... ...
答案 0 :(得分:0)
首先,在查看数据时,第dt
列看起来不是日期时间格式。使用POSIXct
之前,您需要转换成cut
类。您可以将函数的初始部分更改为
library(dplyr)
library(rlang)
df1 = df %>% group_by(new = cut(as.POSIXct(dt),
format = "%Y-%m-%d %H:%M", breaks="60 min")) %>%
summarize(x = mean(!!sym(par), na.rm = TRUE))
如果代码的其余部分正确,则应给出预期结果,因为它将文字字符串转换为符号,然后对其求值。而且据我所知,该功能仅适用于一列。尝试将其作为
用于第一列fun(df, dt, "par1")
,然后检查您是否获得了预期的输出。现在,您需要对所有可以使用paste0
生成并使用lapply
/ map
lapply(paste0("par ", 1:100), function(par) fun(df,dt,par))
这将为您生成一个数据帧列表,您可以将其与do.call
绑定在一起
do.call(rbind, lapply(paste0("par ", 1:100), function(par) fun(df,dt,par)))