Отделить посторонние остатки от набора данных R

Я создал линейную модель для своего набора данных, который состоит примерно из 12 миллионов строк. Используя остатки, я установил границы выбросов. Нижний забор и верхний забор.

Теперь я хочу извлечь выбросы и поместить соответствующие данные в вектор или записать их в файл.

Вот две строки из моего исходного набора данных:

 print(res[1:2,])
 PIG_ID trial       res$bla   gain        LINE      CODE     comp BIRTH_WEIGHT_SCALED farm_trend birth_weight_scaled
 123456   XXX  0012345ABCDFF  1000        CCDDC        Z     <NA>               955.2         -9                  -9
 135411   XXX  11122233ASDDD  889         TTDDT        Z     <NA>                 0.0         -9                  -9

resid(lmfit) выводит кучу значений:

 700       750      2132      3394      4123      4213      4583      4842      5288      8287     12331     12427     13726

Вот код, который вычисляет модель и выбросы:

lmfit = lm(res$gain ~ res$trial + res$bla * res$LINE* res$CODE + res$birth_weight_scaled )

kwant <- quantile(resid(lmfit), probs= c(0.25, 0.75))
Q1 <- kwant[1]
Q3 <- kwant[2]
sigma <- IQR(resid(lmfit))
upp_multi <- 3.5        ##Amount of times sigma for outlier calculation
low_multi <- 1.5        ##Amount of times sigma for outlier calculation

upp_fence <- Q3+(upp_multi * sigma)
low_fence <- Q1-(low_multi * sigma)

print(paste("Upper fence: ", upp_fence, " \t  Lower Fence: ", low_fence ,"\n"))

Я безуспешно гуглил и пробовал фрагменты кода.

Псевдокод будет следующим:

if(resid(lmfit)>upp_fence){add res[row] to vector OutlierUpperBoundary }
if(resid(lmfit)<low_fence){add res[row] to vector OutlierLowerBoundary }

Есть ли способ отделить выпадающие остатки со строками из моего исходного набора данных («Res») и поместить их в матрицу?

Ожидаемый результат будет матрицей, содержащей строки с выбросами:

 PIG_ID trial       res$bla   gain        LINE      CODE     comp BIRTH_WEIGHT_SCALED farm_trend birth_weight_scaled
 135411   XXX  11122233ASDDD  889         TTDDT        Z     <NA>                 0.0         -9                  -9



Изменить

Использование следующего цикла for копирует весь размер исходной матрицы, но просто добавляет значения к внешним строкам:

OutliersUpperBoundary <- data.frame(matrix(ncol = ncol(res)))
for (row in 1:length(resid(lmfit))){
    if(resid(lmfit)[row]>upp_fence){
        OutliersUpperBoundary[row,] <- res[row,]
    }
}

Результат:

694          NA <NA>           <NA>   NA  <NA> <NA>       <NA>     NA NA  NA
695          NA <NA>           <NA>   NA  <NA> <NA>       <NA>     NA NA  NA
696   112341234  XXX 11213421LAAAAA  915 TTTTT    B       <NA>  175.2 -9  -9
697          NA <NA>           <NA>   NA  <NA> <NA>       <NA>     NA NA  NA
698          NA <NA>           <NA>   NA  <NA> <NA>       <NA>     NA NA  NA

Каким образом я должен изменить цикл for, чтобы получать только строки со значениями? (Я думаю, что rbind может работать здесь)

Кроме того, зная немного R, я думаю, что должен быть более быстрый способ, чем использование цикла for (мой набор данных составляет более 12 миллионов строк, и мне нужно пройти этот процесс 14 раз).


person Bas    schedule 23.09.2015    source источник


Ответы (1)


Можно попробовать цикл.

OutlierUpperBoundary <- data.frame(matrix(ncol = ncol(res)))

out_index <- 1
for(row in 1:length(resid(lmfit))){
    if(resid(lmfit)[row]>upp_fence){
        OutlierUpperBoundary[out_index, ] <- res[row, ]
        out_index <- out_index + 1
    }
}

Это может занять много времени, если ваша таблица res большая. В этом случае предварительное выделение всей матрицы будет быстрее. Затем вы можете просто удалить строки NA в конце.

OutlierUpperBoundary <- data.frame(matrix(ncol = ncol(res), nrow = nrow(res)))

out_index <- 1
for(row in 1:length(resid(lmfit))){
    if(resid(lmfit)[row]>upp_fence){
        OutlierUpperBoundary[out_index, ] <- res[row, ]
        out_index <- out_index + 1
    }
}

OutlierUpperBoundary <- OutlierUpperBoundary[complete.cases(OutlierUpperBoundary), ]

И вы можете добавить остаточное значение к выходу, объединив его с исходной строкой с помощью cbind(), когда вы выполняете назначение.

OutlierUpperBoundary <- data.frame(matrix(ncol = ncol(res) + 1, nrow = nrow(res)))

out_index <- 1
for(row in 1:length(resid(lmfit))){
    if(resid(lmfit)[row]>upp_fence){
        OutliersUpperBoundary[out_index,] <- cbind(res[row,], resid(lmfit)[row])

        out_index <- out_index + 1
    }
}

OutlierUpperBoundary <- OutlierUpperBoundary[complete.cases(OutlierUpperBoundary), ]
person neerajt    schedule 24.09.2015
comment
Это фактически копирует всю матрицу и помещает значения только в крайние строки. Остальное помечено как ‹NA›. Я отредактирую свой исходный вопрос с дополнительной информацией :) - person Bas; 24.09.2015
comment
Ой! Это можно исправить, увеличив выходной индекс отдельно. Отредактировано. - person neerajt; 24.09.2015
comment
Спасибо, кажется, это помогает! На заметку: я изменил знаки = в ваших сообщениях на ‹-, так как это правильный синтаксис в R. - person Bas; 24.09.2015
comment
Кроме того, зная немного R, я думаю, что должен быть более быстрый способ, чем использование цикла for (мой набор данных составляет более 12 миллионов строк, и мне нужно пройти этот процесс 14 раз). - person Bas; 24.09.2015
comment
Вы правы, наверное, это лучший способ. Я добавил решение, которое будет быстрее работать с большим набором данных. Надеюсь, это поможет на данный момент. - person neerajt; 24.09.2015
comment
Большое спасибо! еще один вопрос, надеюсь, вы сможете ответить, как мне добавить значение остатка в дополнительный столбец, чтобы я мог проверить значения выбросов на моем графике :) - person Bas; 24.09.2015
comment
Пожалуйста. Добавлено, как добавить остаточную стоимость к выводу. Не уверен, что это то, что вы искали. - person neerajt; 24.09.2015
comment
Я изменил list() на cbind(), чтобы добавить дополнительный столбец! - person Bas; 24.09.2015