Обеспечение временной плотности данных в R
ВЫПУСК ---------
У меня есть тысячи файлов временных рядов (.csv), которые содержат прерывистые данные за 20-50 лет (см. Df). Каждый файл содержит дату и время и метрику (температуру). Данные являются почасовыми, и там, где нет измерений, есть "NA".
>df
date_time temp
01/05/1943 11:00 5.2
01/05/1943 12:00 5.2
01/05/1943 13:00 5.8
01/05/1943 14:00 NA
01/05/1943 15:00 NA
01/05/1943 16:00 5.8
01/05/1943 17:00 5.8
01/05/1943 18:00 6.3
Мне нужно проверить эти файлы, чтобы увидеть, имеют ли они достаточную плотность данных. Т.е. отношение NA к значениям данных не слишком велико. Для этого у меня есть 3 критерия, которые должны быть проверены для каждого файла:
- Убедитесь, что не более 10% часов в день - это NA
- Убедитесь, что не более 10% дней в месяце являются NA
- Убедитесь, что существует 3 непрерывных года данных с действительными днями и месяцами.
Каждый критерий должен выполняться последовательно, и если файл не соответствует требованиям, я должен создать фрейм данных (или любой список) файлов, которые не соответствуют критериям.
ВОПРОС--------
Я хотел спросить сообщество, как это сделать. Я рассмотрел значение вложенных циклов if вместе с использованием sqldf, plyr, aggregate или даже dplyr. Но я не знаю простейшего способа добиться этого. Любой пример кода или предложения будут очень благодарны.
1 ответ
Я думаю, что это будет работать для вас. Они будут проверять каждый час для NA на следующий день, месяц или 3 года. Не проверено, потому что я не хочу составлять данные, чтобы проверить это. Эти функции должны выплевывать количество NA за соответствующий период времени. Так что для контрольных дней функции, если она возвращает значение больше 2,4, то в соответствии с вашим правилом 10% у вас будут проблемы. Для месяцев 72 и для 3-летних периодов вы надеетесь на значения меньше 2628. Опять проверьте эти функции. Кстати, функции предполагают, что ваши данные NA находятся в столбце 2. Приветствия.
checkdays <- function(data){
countNA=NULL
for(i in 1:(length(data[,2])-23)){
nadata=data[i:(i+23),2]
countNA[i]=length(nadata[is.na(nadata)])}
return(countNA)
}
checkmonth <- function(data){
countNA=NULL
for(i in 1:(length(data[,2])-719)){
nadata=data[i:(i+719),2]
countNA[i]=length(nadata[is.na(nadata)])}
return(countNA)
}
check3years <- function(data){
countNA=NULL
for(i in 1:(length(data[,2])-26279)){
nadata=data[i:(i+26279),2]
countNA[i]=length(nadata[is.na(nadata)])}
return(countNA)
}
Так что я закончил тестировать их. Они работают на меня. Вот системное время для набора данных за год. Так что я не думаю, что у тебя будут проблемы.
> system.time(checkdays(RM_W1))
user system elapsed
0.38 0.00 0.37
> system.time(checkmonth(RM_W1))
user system elapsed
0.62 0.00 0.62
Оптимизация: я потратил время на запуск этих функций с данными, которые вы разместили выше, и это было не очень хорошо. Циклы for опасны, потому что они хорошо работают для небольших наборов данных, но экспоненциально замедляются по мере того, как наборы данных становятся больше, то есть если они построены неправильно. Я не могу сообщить системное время для указанных выше функций с вашими данными (это никогда не завершалось), но я ждал около 30 минут. После прочтения этого удивительного поста "Ускорение работы цикла в R" я переписал функции так, чтобы они были намного быстрее. Минимизируя количество вещей, которые происходят в цикле и предварительно выделяя память, вы действительно можете ускорить процесс. Вам нужно вызвать функцию как checkdays(df[,2])
но так быстрее.
checkdays <- function(data){
countNA=numeric(length(data)-23)
for(i in 1:(length(data)-23)){
nadata=data[i:(i+23)]
countNA[i]=length(nadata[is.na(nadata)])}
return(countNA)
}
> system.time(checkdays(df[,2]))
user system elapsed
4.41 0.00 4.41
Я считаю, что этого должно быть достаточно для ваших нужд. Что касается високосных годов, вы должны иметь возможность изменять оптимизированную функцию, как я упоминал в комментариях. Однако убедитесь, что вы указали набор данных високосного года в качестве второго набора данных, а не второго столбца.