2013-08-02 12 views
12

Mam formułę zawierającą pewne terminy i ramkę danych (dane wyjściowe z wcześniejszej rozmowy model.frame()), która zawiera wszystkie te terminy i kilka innych. Chcę podzbiór ramki modelu, który zawiera tylko zmienne, które pojawiają się w formule.Wyodrębnij zmienne we wzorze z ramki danych

ff <- log(Reaction) ~ log(1+Days) + x + y 
fr <- data.frame(`log(Reaction)`=1:4, 
       `log(1+Days)`=1:4, 
       x=1:4, 
       y=1:4, 
       z=1:4, 
       check.names=FALSE) 

Pożądany wynik jest fr minus kolumna z (fr[,1:4] oszukuje - Muszę programowe rozwiązanie ...)

Niektóre strategie, które nie praca:

fr[all.vars(ff)] 
## Error in `[.data.frame`(fr, all.vars(ff)) : undefined columns selected 

(ponieważ all.vars() otrzymuje "Reaction", a nie log("Reaction"))

stripwhite <- function(x) gsub("(^ +| +$)","",x) 
vars <- stripwhite(unlist(strsplit(as.character(ff)[-1],"\\+"))) 
fr[vars] 
## Error in `[.data.frame`(fr, vars) : undefined columns selected 

(ponieważ podział na + nieoczekiwanie dzieli termin log(1+Days)).

Myślałam o schodził z drzewa składniowy o wzorze:

ff[[3]]  ## log(1 + Days) + x + y 
ff[[3]][[1]] ## `+` 
ff[[3]][[2]] ## log(1 + Days) + x 

ale nie mam rozwiązanie ułożyła, a wydaje się, że jadę w dół króliczej nory. Pomysły?

+0

Wydaje się, że główną zmienną, która powoduje problemy, jest 'log (1 + Days)'. Czy musisz to tak nazwać, czy możesz użyć innej nazwy? – Thomas

+1

Co z 'attr (terms.formula (ff)," term.labels ")'? –

+1

Próbuję wymyślić ogólne rozwiązanie. Dlatego wszystko, co może pojawić się w "modelu".frame() 'wygenerowany z formuły prawnej musi być traktowany. To część problemu. –

Odpowiedz

4

To powinno działać:

> fr[gsub(" ","",rownames(attr(terms.formula(ff), "factors")))] 
    log(Reaction) log(1+Days) x y 
1    1   1 1 1 
2    2   2 2 2 
3    3   3 3 3 
4    4   4 4 4 

i rekwizyty Roman Luštrik dla wskazujące mnie we właściwym kierunku.

Edit: Wygląda na to, można wyciągnąć go off "zmiennych" atrybut, a także:

fr[gsub(" ","",attr(terms(ff),"variables")[-1])] 

Edit 2: Znaleziono sprawa Pierwszym problemem, z udziałem I() lub offset():

ff <- I(log(Reaction)) ~ I(log(1+Days)) + x + y 
fr[gsub(" ","",attr(terms(ff),"variables")[-1])] 

Tych byłoby całkiem łatwe do skorygowania za pomocą regex. ALE, gdybyś miał sytuacje takie jak w pytaniu, gdzie zmienna jest wywoływana, np. log(x) i jest używany w formule obok czegoś podobnego do I(log(y)) dla zmiennej y, stanie się to naprawdę nieprzyjemne.

+0

dzięki. Nie mogę tego zaakceptować przez kolejne kilka minut. "gsub (...)" nie będzie konieczny w moim przypadku, myślę - niedopasowanie w białej przestrzeni tam nie będzie. Wprowadziłem to przypadkowo podczas konfigurowania przykładu. –

+0

@BenBolker Tak, prawdopodobnie byłoby dobrze przetestować to na innych konstrukcjach formuł, aby sprawdzić, czy jest to ogólne ... – Thomas

+1

, ale twoja oryginalna odpowiedź, 'rownames (attr (terms.formula (ff)," factors "))) ', wydaje się działać dobrze na twoim przypadku problemu. –

0

Wydaje mi się, że jedynym problemem jest brak miejsca w nazwie drugiej kolumny fr. Przemianować go z miejsca i ciągnąć kolumny w ten sposób:

ff <- log(Reaction) ~ log(1+Days) + x + y 
fr <- data.frame(`log(Reaction)`=1:4, 
       `log(1 + Days)`=1:4, 
       x=1:4, 
       y=1:4, 
       z=1:4, 
       check.names=FALSE) 


fr[labels(terms(ff))] 

Jeśli uważasz, że jedyną różnicą między nimi zawsze będzie, że nazwy fr ma miejsca, gdzie nazwy w ff nie, wówczas powyżej znajduje się rozwiązanie. Jednak bardziej lubię labels(terms(x)), ponieważ wydaje się nieco bardziej abstrakcyjna.

fr[gsub(pattern = ' ', replacement = '', x = labels(terms(ff)))] 
Powiązane problemy