Я уже решил свою проблему, но я хочу знать, есть ли более эффективный способ ее решения.
У меня есть 22 миллиона строк x 9 столбцов данных, со столбцами, имеющими следующая структура:
factorID
= коэффициент с 99000 уровнями
Date
= дата
RDate
= число c (дата в виде прогрессивного числа, вычисленного как R, количество дней с момента 01.01.1970)
V1:V6
= целое число
Каждый факторный уровень состоит из временного ряда из 231 внутригодовых наблюдений, охватывающих промежуток времени в 40 лет. Из-за сбоев в некоторых наблюдениях представлены значения NA
, которые могут быть общими для всех 6 переменных или ограничены только 1. Я хотел заменить эти значения NA
ближайшим наблюдением во временной области, главным образом предыдущим или следующим. (самый простой случай, но иногда предыдущий или следующий тоже были NA
).
Чтобы решить мою проблему, я попытался и преуспел с помощью вложенных циклов for
:
## Isolating one factor at a time with the first loop, since NA amount and position
## differ for each level
for (i in 1:length(levels(df$factorID))){
ID = levels(df$factorID)[i]
Point_df <- subset(df, df$factorID == ID)
## Calculating total amount and position of NA and integer values by column,
## and identify them by their RDate
## If NA values are present in the column, execute the third loop
for (j in 1:6){
ID_column = j+3
NAcheck <- is.na(Point_df[[ID_column]])
difference_table <- cbind.data.frame(Point_df$RDate, NAcheck)
NoNA <- subset(difference_table, difference_table$NAcheck == FALSE)
True_NA <- subset(difference_table, difference_table$NAcheck == TRUE)
colnames(True_NA)[1] <- "RDate"
colnames(NoNA)[1] <- "RDate"
if (length(True_NA$RDate) > 0){
## With the third loop I compute the nearest not NA observation based on the
## minimum absolute value difference in the time domain (treating the date as a progressive number),
## then I replace one NA at a time
for (k in 1:length(True_NA$NAcheck)){
difference <- abs(True_NA$RDate[k]-NoNA$RDate)
difference_list <- cbind.data.frame(NoNA$RDate, difference)
replacing_difference <- min(difference)
replacing_date <- subset(difference_list, difference_list$difference==replacing_difference)
NA_tochange <- subset(Point_df, Point_df$RDate == True_NA$RDate[k])
replacing_value <- subset(Point_df, Point_df$RDate == replacing_date[1,1])
NA_tochange[[ID_column]] <- replacing_value[[ID_column]]
row <- as.numeric(rownames(True_NA)[k])
Point_df[row] <- NA_tochange
}
}
}
## Writing the new dataframe one level at a time
fwrite(Point_df, "B:/Point-predictors_NA-replaced.csv", append=TRUE, sep=",")
}
Как вы можете себе представить, решение этой проблемы занимает очень много времени (использование data.table
с двумя потоками на моем ноутбуке заняло около 12 часов: весь фрейм данных занимает более 1 ГБ, а каждая итерация всего l oop пишет что-то вроде 15-30 КБ данных). Как я уже упоминал, поскольку у каждого удостоверения есть свои особенности, я не мог придумать что-либо, чтобы лучше автоматизировать задачу. Как вы думаете, как можно ускорить всю операцию?
Большое спасибо.
Редактировать По запросу я прилагаю несколько примеров; Я не хотел делать пост длиннее, чем он был.
Пример данных:
factorID Date RDate V1 V2 V3 V4 V5 V6
1 1989-02-06 6976 318 351 172 570 260 108
1 1989-05-13 7072 77 NA 591 NA 801 550
1 1989-05-29 7088 NA NA NA NA NA NA
1 1989-06-14 7104 252 305 286 835 271 85
.
2 1989-02-06 6976 236 389 323 2078 908 373
2 1989-05-13 7072 77 NA 591 NA 801 550
2 1989-05-29 7088 55 62 410 2001 NA NA
2 1989-06-14 7104 351 508 456 1618 780 421
Желаемый результат:
factorID Date RDate V1 V2 V3 V4 V5 V6
1 1989-02-06 6976 318 351 172 570 260 108
1 1989-05-13 7072 77 351 591 570 801 550
1 1989-05-29 7088 77 351 591 570 801 550
1 1989-06-14 7104 252 305 286 835 271 85
.
2 1989-02-06 6976 236 389 323 2078 908 373
2 1989-05-13 7072 77 62 591 2001 801 550
2 1989-05-29 7088 55 62 410 2001 801 550
2 1989-06-14 7104 351 508 456 1618 780 421
Надеюсь, что так и будет помощь.