2016-02-22 4 views
0

У меня очень большой набор данных, структурированный как образец ниже.Сплайн-интерполяция R с условиями

Я пытался использовать функцию na.spline, чтобы

1) определить категорию «ФИПС» с отсутствующими Выход.

2) если менее 3 значений урожайности - NA на каждый оборот (здесь 1-3), функция сплайна должна пинать и заполнять NA.

3) Если 3 или более урона являются NA для «fips», код должен удалить все подмножества «fips», в этом случае fips 2 следует удалить.

Мой код до сих пор:

finX <- dataset 

finxx <- transform(subset(finX, ave(na.spline(finX$Yield), fips, FUN=sum)<2)) 

#or 

finxx <- transform(subset(finX, ave(is.na(finX$Yield), fips, FUN=sum)<2)) 

Year fips Max  Min Rain Yield 
1980 1  24.7 0.0 71 37 
1981 1  22.8 0.0 62 40 
1982 1  22.6 0.0 47 37 
1983 1  24.2 0.0 51 39 
1984 1  23.8 0.0 61 47 
1985 1  25.1 0.0 67 43 
1980 2  24.8 0.0 72 34 
1981 2  23.2 0.4 54 **NA** 
1982 2  25.3 0.1 83 55 
1983 2  23.0 0.0 68 **NA** 
1984 2  22.4 0.7 70 **NA** 
1985 2  24.6 0.0 47 31 
1980 3  25.5 0.0 51 31 
1981 3  25.5 0.0 51 31 
1982 3  25.5 0.0 51 31 
1983 3  25.5 0.0 51 **NA** 
1984 3  25.5 0.0 51 31 
... 

В настоящее время коды выше или не заполнять все числовые апертуры в конечном продукте, или просто не имеют никакого результата вообще.

Любое руководство было бы очень полезно, спасибо.

ответ

1

Yield необходимо преобразовать с символа в числовое или NA. Затем используйте by для разделения finX на отдельные фреймы данных на fips значение. Для каждого кадра данных с менее чем 3 NA's выполните сплайн-интерполяцию. Те, у кого 3 или более, возвращаются как NULL. Объедините list возвращенных кадров данных в единый фрейм данных. Код будет выглядеть следующим образом:

library(zoo) 
# convert finX$Yield values from character to either numeric or NA 
    finX$Yield <- sapply(finX$Yield, function(x) if(x =="**NA**") NA_real_ else as.numeric(x)) 

# use spline interpolation on fips sets with less than 3 NA's 
    finxx <- by(finX, finX$fips, function(x) if(sum(is.na(x$Yield)) < 3) transform(x, Yield=na.spline(object=Yield, x=Year)))  
# combine results into a single data frame 
    finxx <- do.call(rbind, finxx) 

В качестве альтернативы после преобразования числовых значений, можно использовать ave на Yield колонке, где сплайн интерполяция возвращает значения на fips наборов менее 3 NA и все НС на любых других наборах. Затем все строки с любым NA в конечном результате будут удалены. Код выглядит следующим образом:

finxx2 <- transform(finX, Yield=ave(Yield, fips, FUN=function(x) if(sum(is.na(x)) < 3) na.spline(object=x) else NA)) 
finxx2 <- na.omit(finxx2) 

Обе версии дают одинаковый результат для выборки данных, но первая версия, использующая by позволяет работать с полным кадром данных для каждого fips набора, а не только с Yield. В этом случае это разрешало указывать Year для значений x в сплайновой интерполяции, поэтому любые данные с отсутствующим Year все равно дадут правильную интерполяцию. Версия ave получит неверный ответ. Таким образом, версия by кажется более надежной.

Существует также версия dplyr, которая очень похожа на версию by и дает тот же ответ, что и базовые версии R. Если вы в порядке с dplyr, это, вероятно, самый простой и надежный подход.

library(dplyr) 
finxx3 <- finX %>% group_by(fips) %>% 
     filter(sum(is.na(Yield)) < 3) %>% 
     mutate(Yield=na.spline(object=Yield, x=Year)) 

Первая версия возвращает

 Year fips Max Min Rain Yield 
1.1 1980 1 24.7 0 71 37 
1.2 1981 1 22.8 0 62 40 
1.3 1982 1 22.6 0 47 37 
1.4 1983 1 24.2 0 51 39 
1.5 1984 1 23.8 0 61 47 
1.6 1985 1 25.1 0 67 43 
3.13 1980 3 25.5 0 51 31 
3.14 1981 3 25.5 0 51 31 
3.15 1982 3 25.5 0 51 31 
3.16 1983 3 25.5 0 51 31 
3.17 1984 3 25.5 0 51 31 
+0

Это фантастический ответ, спасибо большое –