2017-06-14 2 views
1

Ich versuche derzeit, mich zu verbessern effizient mehrere Modelle gegeneinander zu testen. Mein Versuch, für den ich einen Beispielcode zur Verfügung gestellt habe, kann wie folgt beschrieben werden:Übergeben Sie verschiedene Arten von Argumenten an Vectorize()

Für eine gegebene abhängige Variable (Spalte 11 in data) werden lineare Modelle geschätzt, die sich durch ihre erklärenden Eingangsvariablen unterscheiden. Mein Wunsch ist, ein Paar Parameter a und b zu haben, die die Anfangs- und Endspalte für die Auswahl der erklärenden Variablen in meinem Datenrahmen data bestimmen.

Diese Parameterkombinationen habe ich unter parameters gespeichert. Ich würde gerne eine Spalte hinzufügen, die die Bewertung eines Maßes enthält (hier df.residual) mit den Parametern in seiner Zeile.

Ich scheitere jedoch bei der Vektorisierung des Problems. Genauer gesagt passiere ich a und b richtig, aber nicht data.

# Example data 
data = as.data.frame(mtcars) 

# Setting the parameters for choosing x-columns 
# a is the start column, b the end column 
parameters = tidyr::expand(tibble(a=1:5, b = 1:5 * 2),a,b) %>% 
dplyr::filter(a<b) 


# Define the function called to yield the result 
another_fun = function(a, b, data) {  
# Vectorize, here's some trouble 
    case_fun_another = Vectorize( 
    function(a, b, data=data) { 
     x = as.matrix(data[,a:b]) 
     y = as.matrix(data[,11]) 
     lm.fit(x=x,y=y)$df.residual 
    }, SIMPLIFY = FALSE 
) 

output = case_fun_another(a, b) 
return(output) 
} 

# Calculate result 
parameters = dplyr::mutate(parameters, result=another_fun(a, b, data)) 

, dass die Renditen:

promise already under evaluation: recursive default argument reference or earlier problems?

Die Fragen, die ich zu diesem Thema gefunden waren nicht ganz verständlich zu mir. Vielleicht wird es mit der Beschreibung des Problems einfacher.

Irgendeine Idee, wie man damit umgeht? Ich wäre auch offen für andere Optionen als mit Vectorize :-)

Vielen Dank im Voraus.

+0

@ 李哲源 Zheyuan Li: Kudos - das hat geholfen, ich habe gerade viel gelernt, danke :-) Wird dies als eine Antwort akzeptieren, sobald ich kann. – MaHo

Antwort

2

Hier ist eine Alternative ohne geschachtelte Funktion und Vectorize zu beschäftigen.

# get all the possible pairwise combination of independent variables with combn 
ind.var <- names(data)[-11] %>% 
     combn(., 2) %>% 
     t 

head(ind.var) 

#  [,1] [,2] 
# [1,] "mpg" "cyl" 
# [2,] "mpg" "disp" 
# [3,] "mpg" "hp" 
# [4,] "mpg" "drat" 
# [5,] "mpg" "wt" 
# [6,] "mpg" "qsec" 


# paste values of each row of ind.var, with separator "+" 

x <- do.call(paste, c(as.list(data.frame(ind.var, stringsAsFactors = FALSE)), sep="+")) 
y <- "carb" 

# write out all the linear model formula: 

forms <- mapply(function(a,b) paste(a, b, sep="~"), y, x) %>% 
     setNames(NULL) 

all.lm <- lapply(forms, function(x) eval(bquote(lm(.(x), data=data)))) 

all.lm[[1]] 

# Call: 
# lm(formula = "carb~mpg+cyl", data = data) 
# 
# Coefficients: 
# (Intercept)   mpg   cyl 
#  3.63978  -0.09968  0.18995 

Dank für den Hinweis auf die Verwendung von bquote zum Halten der Formel Anrufs in lm.object @Roland.

+0

Sie sollten sowieso nicht parsen. Dein letzter Satz kann folgendermaßen angesprochen werden: 'f <- Sepal.Length ~.; eval (bquote (lm (. (f), Daten = Iris))) (unter Verwendung eines anderen Beispiels zur Vereinfachung). Parsen von Text sollte immer vermieden werden. – Roland

+0

Das Beispiel funktioniert gut, danke. Ich muss untersuchen, ob ich es auf die gewünschte Parametrisierung erweitern kann. – MaHo

+1

@Roland Danke, dass Sie mich auf 'bquote' aufmerksam gemacht haben. Ich werde den Code aufräumen, wenn ich kann. –

Verwandte Themen