2016-06-15 19 views
6

W tej chwili mam combn z wbudowanej irysa zestawu danych. Do tej pory zostałem poprowadzony, aby móc znaleźć współczynnik lm() pary wartości.R: jak wykonać bardziej złożone obliczenia z zestawu danych?

myPairs <- combn(names(iris[1:4]), 2) 

formula <- apply(myPairs, MARGIN=2, FUN=paste, collapse="~") 

model <- lapply(formula, function(x) lm(formula=x, data=iris)$coefficients[2]) 

model 

Jednakże, I jak przejść kilka kroków dalej i wykorzystać współczynnik z lm() do stosowania w dalszych obliczeniach. Chciałbym zrobić coś takiego:

Coefficient <- lm(formula=x, data=iris)$coefficients[2] 
Spread <- myPairs[1] - coefficient*myPairs[2] 
library(tseries) 
adf.test(Spread) 

Sama procedura jest dość prosta, ale nie udało się znaleźć sposób, aby to zrobić dla każdego combn w zbiorze danych. (Jako przykład, test adf.test nie zostałby zastosowany do takich danych, ale używam tylko zestawu danych tęczówki do demonstracji). Zastanawiam się, czy byłoby lepiej napisać pętlę do takiej procedury?

+1

Po prostu chciałem mieć jasność co do tego, ek. Potrzebujesz rozwiązania, które zapewni wynik (w szczególności ostatnie 4 linie) dla każdej kombinacji bez konieczności użycia pętli. Czy to prawda? –

+1

Jestem trochę zdezorientowany przez twój drugi blok. Czy chcesz obliczyć spread dla wszystkich par? Co dzieje się na końcu ('myPairs [6] - coefficient *' ???)? – TARehman

+0

@AnalyticalMonk Tak, to prawda, ale jeśli pętla jest bardziej wydajna, nie miałbym nic przeciwko napisaniu tego. –

Odpowiedz

2

Możesz to wszystko zrobić w ciągu combn.

Jeśli tylko chciał uruchomić regresji nad wszystkimi kombinacjami i wyodrębnić drugi współczynnik można zrobić

fun <- function(x) coef(lm(paste(x, collapse="~"), data=iris))[2] 
combn(names(iris[1:4]), 2, fun) 

Następnie można rozszerzyć funkcję do obliczania Spread

fun <- function(x) { 
     est <- coef(lm(paste(x, collapse="~"), data=iris))[2] 
     spread <- iris[,x[1]] - est*iris[,x[2]] 
     adf.test(spread) 
     } 

out <- combn(names(iris[1:4]), 2, fun, simplify=FALSE) 
out[[1]] 

# Augmented Dickey-Fuller Test 

#data: spread 
#Dickey-Fuller = -3.879, Lag order = 5, p-value = 0.01707 
#alternative hypothesis: stationary 

porównać wyniki do uruchomienia pierwszej ręcznie

est <- coef(lm(Sepal.Length ~ Sepal.Width, data=iris))[2] 
spread <- iris[,"Sepal.Length"] - est*iris[,"Sepal.Width"] 
adf.test(spread) 

# Augmented Dickey-Fuller Test 

# data: spread 
# Dickey-Fuller = -3.879, Lag order = 5, p-value = 0.01707 
# alternative hypothesis: stationary 
+1

Dzięki, inna odpowiedź była dobra, ale właśnie to próbowałem zrobić. –

2

Wygląda na to, co chcesz napisać własną funkcję i wywołać go w pętli myPairs (zastosowanie):

yourfun <- function(pair){ 
    fm <- paste(pair, collapse='~') 
    coef <- lm(formula=fm, data=iris)$coefficients[2] 
    Spread <- iris[,pair[1]] - coef*iris[,pair[2]] 
    return(Spread) 
} 

Następnie można wywołać tę funkcję:

model <- apply(myPairs, 2, yourfun) 

myślę, że to jest najczystszy sposób. Ale nie wiem, co dokładnie chcesz zrobić, więc wymyśliłem przykład dla Spread. Zauważ, że w moim przykładzie otrzymujesz komunikaty ostrzegawcze, ponieważ czynnikiem jest kolumna Species.

+0

Myślę, że robisz to niepotrzebnie skomplikowane. Po pierwsze, możesz użyć 'lapply()', aby uniknąć wywołania 'apply()', ale bardziej ogólnie, 'eval (parse())' bit jest prawdopodobnie wymienny z nazwanymi wektorami. – TARehman

+0

Tak, dziękuję, jestem świadomy komplikacji eval (parse()), która była tylko szybką pracą, aby uniknąć jakiegoś dziwnego problemu (teraz rozwiązany). Będę edytować odpowiedź; może nadal być przydatne. – jkt

1

Kilka wskazówek: Nie nazwałabym rzeczy, które ty nazywasz tak samo jak funkcje wbudowane (model, formula przyjdź do głowy w twojej oryginalnej wersji).

Możesz także uprościć paste, którą robisz - patrz poniżej.

Na koniec bardziej ogólne stwierdzenie: nie ma się wrażenia, że ​​wszystko musi być zrobione w jakimś rodzaju *apply. Czasami zwięzłość i krótki kod są trudniejsze do zrozumienia, a pamiętajmy, że funkcje *apply oferują w najlepszym wypadku marginalną poprawę prędkości w porównaniu z prostą pętlą for. (Nie zawsze tak było z R, ale jest w tym momencie).

# Get pairs 
myPairs <- combn(x = names(x = iris[1:4]),m = 2) 

# Just directly use paste() here 
myFormulas <- paste(myPairs[1,],myPairs[2,],sep = "~") 

# Store the models themselves into a list 
# This lets you go back to the models later if you need something else 
myModels <- lapply(X = myFormulas,FUN = lm,data = iris) 

# If you use sapply() and this simple function, you get back a named vector 
# This seems like it could be useful to what you want to do 
myCoeffs <- sapply(X = myModels,FUN = function (x) {return(x$coefficients[2])}) 

# Now, you can do this using vectorized operations 
iris[myPairs[1,]] - iris[myPairs[2,]] * myCoeffs[myPairs[2,]] 

Jeśli dobrze rozumiem, uważam, że powyższe zadziała. Zauważ, że nazwy na wyjściu w chwili obecnej będą bezsensowne, musisz je zastąpić czymś w swoim własnym projekcie (może wartości myFormulas).

+0

Możesz to wszystko zrobić w 'combn':' fun <- function (x) coef (lm (wklej (x, zwiń = "~"), data = iris)) [2]; combn (imiona (tęczówki [1: 4]), 2, zabawa) ' – user20650

+0

Interesujące, nie wiedziałem o tym. Nadal wydaje się naruszać tę trzecią część, jeśli chodzi o zwięzłość, która nie zawsze jest najlepsza. – TARehman

Powiązane problemy