Использование dplyr для группировки и суммирования данных временных рядов внутри функции - PullRequest
0 голосов
/ 07 июня 2019

Заранее спасибо за помощь.Я знаю, что есть похожие вопросы, но все они проще, чем вопрос, который здесь задают, поскольку они имеют дело с группировкой по факторам, а не по DateTime.

Моя цель - написать функцию, которая может применяться к различным физическим параметрам в наборе океанических данных (<100 столбцов).Каждый физический параметр автоматически записывается с 30-минутным интервалом и должен подвергаться такому же сложному суммарному вычислению.</p>

Фрейм данных (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      ...            ...     ...            ...

1 Ответ

0 голосов
/ 07 июня 2019

Во-первых, при просмотре ваших данных столбец 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")

и проверьте, получите ли вы ожидаемый результат.Теперь вам нужно сделать это для всех 100 столбцов, которые можно сгенерировать с помощью 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)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...