Kamil Bęczyński

Kamil Bęczyński R, SAS, analizy

Temat: Pytanie odnośnie '...'


f<-function(...){

#nie wiem co tu wpisać :/

}

w wyniku przykładowego użycia f() chciałbym otrzymać :

>f(x="a" , y="b" , "c")
>[1] "x" "y" ""


czyli nazwy parametrów wymienionych w '...',

a tak ogólnie, to czym jest '...', próbowałem w ciele funkcji umieścić class(...), length(...) i inne, żeby się czegoś dowiedzieć, ale takie funkcje dają wyłącznie komunikaty o błędach, więc chyba '...' nie jest obiektem. Z tego co zrozumiałem to '...' jest po prostu skrótem oznaczającym ciąg znaków wprowadzonych podczas wywoływania funkcji (z pominięciem zdefiniowanych zmiennych oczywiście), nie dostarcza mi to jednak pomysłu na rozwiązanie przedstawionego problemu.

PozdrawiamKamil B edytował(a) ten post dnia 31.01.12 o godzinie 00:20

Temat: Pytanie odnośnie '...'

Proszę :)

 > test <- function(x, ...) {
+ (args <- as.list(substitute(list(...)))[-1L])
+ }
>
> test(10, a=1, b=2, c=3)
$a
[1] 1

$b
[1] 2

$c
[1] 3

> test(10, a=1, b=2, c=3)$c
[1] 3
> names(test(10, a=1, b=2, c=3))
[1] "a" "b" "c"
Adrian Olszewski edytował(a) ten post dnia 26.01.12 o godzinie 16:06
Kamil Bęczyński

Kamil Bęczyński R, SAS, analizy

Temat: Pytanie odnośnie '...'

Dziękuję o to chodziło :)

nadal nie rozumiem rozwiązania, gdyż nigdy nie mogłem zrozumieć co robi substitute() ;D

konto usunięte

Temat: Pytanie odnośnie '...'

można użyć też colnames(f) <- c("a","b","c") , gdzie wektor c określa nazwy kolumn
Pozdrowionka
Wojciech Sobala

Wojciech Sobala Redaktor
statystyczny,
biostatystyk,
Instytut Medycyny
Pr...

Temat: Pytanie odnośnie '...'

Jeżeli chcesz tylko nazwy argumentów to wystarczy:

f<- function(...) {
argnames <- names(list(...))
return(argnames)
}
Wojciech Sobala

Wojciech Sobala Redaktor
statystyczny,
biostatystyk,
Instytut Medycyny
Pr...

Temat: Pytanie odnośnie '...'

substitute jest odpowiednikiem sub tylko działa na wyrażeniach (expression).


sub("a","z","a+1")
[1] "z+1"

substitute(a+1,list(a=as.name("z"))) # można też zamiast
as.name("z") napisać quote(z)
z + 1


substitute użyte wewnątrz funkcji z argumentem funkcji jako argumentem zwraca wyrażenie z wywołania funkcji (jeżeli y jest argumentem funkcji f i funkcję wywołamy f(y=a+1) to substitute(y) wywołane wewnątrz funkcji f zwróci a+1).Wojciech Sobala edytował(a) ten post dnia 29.01.12 o godzinie 07:37
Kamil Bęczyński

Kamil Bęczyński R, SAS, analizy

Temat: Pytanie odnośnie '...'

Dziękuję bardzo za odpowiedzi:)

Pytanie które zadałem, było trochę nie tym o co chciałem zapytać :-/
spostrzegłem to gdy zobaczyłem " names(list(...)) ", bo używałem tego fragmentu kodu i nie zadziałało. Źle sformułowałem pytanie.

Problem jest taki :


a=1;b="jhlkjh"

f=function(a,b){
#jakis kod
}
[quote]f(a,b)[/quote][1] "a" "b"


czy coś takiego można zrobić ? gdy użyje się names(list(...)) to w odpowiedzi otrzymamy ciąg zawierający zmienne będące ciągami o zerowej długości, czyli ' "" '.Kamil B edytował(a) ten post dnia 31.01.12 o godzinie 00:19

konto usunięte

Temat: Pytanie odnośnie '...'

może spróbuj lepiej opisać swój problem.
a=1;b="jhlkjh"

f=function(a,b){
#jakis kod
}

f(a,b)

[1] "a" "b"

co oznacza tu #jakiś kod? i co chcesz osiągnąć?
Wojciech Sobala

Wojciech Sobala Redaktor
statystyczny,
biostatystyk,
Instytut Medycyny
Pr...

Temat: Pytanie odnośnie '...'

Kamil B:
Dziękuję bardzo za odpowiedzi:)

Pytanie które zadałem, było trochę nie tym o co chciałem zapytać :-/
spostrzegłem to gdy zobaczyłem " names(list(...)) ", bo używałem tego fragmentu kodu i nie zadziałało.

Nie zadziała bo "..." odnosi się do nie nazwanych argumentów funkcji w chwili definiowania funkcji a nie w chwili jej wywołania.
Jeżeli operujesz na nazwanych argumentach funkcji to rozwiązanie jest następujące (podobne do tego które podał wcześniej @adrian):


a=1;b="jhlkjh"

f <- function(x,y){
c(x=deparse(substitute(x)),
y=deparse(substitute(y)))
}

f(a,b)
x y
"a" "b"
Wojciech Sobala

Wojciech Sobala Redaktor
statystyczny,
biostatystyk,
Instytut Medycyny
Pr...

Temat: Pytanie odnośnie '...'

Najbardziej ogólna metoda dla wszystkich argumentów:


f <- function(a,b,...){
cn <- as.list(match.call())[-1]
unlist(lapply(cn,deparse))
}
Kamil Bęczyński

Kamil Bęczyński R, SAS, analizy

Temat: Pytanie odnośnie '...'

Ciekawostka (przynajmniej dla mnie) :


f<-function(a=1,...)..2

f(1,2)
[1] 2


'..n', zwraca n-tą wartość z '...'.

:)

W jaki sposób zamienić listę utworzoną z ciągu parametrów ponownie na ciąg parametrów ?
czyli, czy można powtórnie zamienić listę parametrów do postaci jakiej są przechowywane w '...', przykładowo :


f<-function(x,...){

lista=list(...)#zakładam, że lista zawiera tylko i wyłącznie parametry graficzne obsługiwane przez plot()

plot(x, jakaśFunkcja(lista))

}


przykładowe użycie f:


f(1:11,col="green",xlab="X")


przykładowa postać lista to


> lista
$col
[1] "green"

$xlab
[1] "X"


Czy istnieje jakaśFunkcja() będąca w stanie zrealizować to zadanie, być może switch() przydałoby się do tego ?

Jeżeli nie, to może zamiast plot(x, jakaśFunkcja(lista)) wpisać coś innego, próbowałem przy pomocy par() ustawić opcje wykresu ale się nie udało ('col' odpowiada tam za 'default colour')

Ten problem wziął się stąd, że nie wiem w jaki sposób rozwiązać problem, gdy mam funkcję która zawiera w sobie dwie funkcje, z których obie powinny móc korzystać z części parametrów podanych przez '...', ale w jaki sposób przekazać
część z parametrów w jedno, a część w drugie miejsce ?
Pomyślałem, żeby stworzyć list(...) korzystając z informacji w names(list(...)) podzielić list(...)
na dwie części, ale nie wiem, w jaki sposób zamienić listę utworzoną z ciągu parametrów ponownie na ciąg parametrów ?Kamil B edytował(a) ten post dnia 31.01.12 o godzinie 00:19
Wojciech Sobala

Wojciech Sobala Redaktor
statystyczny,
biostatystyk,
Instytut Medycyny
Pr...

Temat: Pytanie odnośnie '...'

Nie bardzo wiem na czym polega problem z przekazywaniem parametrów ....
Jeżeli chcesz przekazać wszystkie parametry do funkcji wywoływanej wewnątrz danej funkcji to nie ma z tym żadnego problemu (kod poniżej).


f <- function(width,height,...){
windows(width,height)
plot(...)
}

f(4,4,x=1:4,pch=16,col="red")
Kamil Bęczyński

Kamil Bęczyński R, SAS, analizy

Temat: Pytanie odnośnie '...'

Wojciech Sobala:
Nie bardzo wiem na czym polega problem z przekazywaniem parametrów ....
Jeżeli chcesz przekazać wszystkie parametry do funkcji wywoływanej wewnątrz danej funkcji to nie ma z tym żadnego problemu (kod poniżej).


f <- function(width,height,...){[/quote]> windows(width,height)[quote] plot(...)
}

f(4,4,x=1:4,pch=16,col="red")



Chciałbym część parametrów z '...' przekazać do jednej, a część do drugiej funkcji. Na przykład :

f<-function(x,...){

model=lm(x,część parametrów z '...')
plot(model$res,cześć parametrów z '...')

}


przy czym znam nazwy parametrów które chciałbym umieścić jako argumenty w plot(). Wszystkich parametrów nie mogę przekazać do lm() i plot(), bo otrzymam komunikaty o błędach.

PozdrawiamKamil B edytował(a) ten post dnia 31.01.12 o godzinie 00:20
Michał Bojanowski

Michał Bojanowski socjolog, analityk

Temat: Pytanie odnośnie '...'

Jest kilka możliwości, użyteczność każdej zależy ile argumentów przekazujesz. Ponieważ plot i lm akceptują bardzo dużo dodatkowych argumentów przez ... więc, gdybym miał to robić, to bym zrobił tak za pomocą 'do.call':


f <- function(x, plot.args=NULL, lm.args=NULL)
{
model <- do.call("lm", c( list(x=x), lm.args))
do.call("plot", c(list(x=model$res), plot.args))
}


plot.args i lm.args powinny być listami z argumentami do przekazania do, odpowiednio, plot i lm. Na przykład:

f( x, lm.args=list(model=FALSE), plot.args=list(type="l") )

itd itp etc

EDIT: zle byly nawiasy w funkcji f...Michał Bojanowski edytował(a) ten post dnia 31.01.12 o godzinie 15:03
Wojciech Sobala

Wojciech Sobala Redaktor
statystyczny,
biostatystyk,
Instytut Medycyny
Pr...

Temat: Pytanie odnośnie '...'

Odpowiedź Michała zapewnia najbezpieczniejsze rozwiązanie, bo użytkownik ma pełną kontrolę nad tym które argumenty przekazuje do funkcji wywoływanych wewnątrz danej funkcji.
Można też pokusić się o automatyczne rodzielanie argumentów na podstawie ich nazwy.
cn <- as.list(match.call())[-1] (przykład powyżej) daje listę wszystkich argumentów.
W tym przypadku trzeba zdefiniować nazwy przekazywane do konkretnej funkcji i wybrać z tej listy wszystkie argumenty pasujące do odpowiedniego wektora z nazwami.
Pozostają tylko dwa problemy: konflikty nazwy argumentów przekazywanych do dwóch funkcji oraz decyzja co do przekazywania argumentów nie pasujących do żadnej z funkcji (np. argumenty przekazywane do funkcji plot poprzez ...).
Michał Bojanowski

Michał Bojanowski socjolog, analityk

Temat: Pytanie odnośnie '...'

Dodałbym jeszcze trzeci problem: automatyczne rozwiązanie się słabo sprawdzi jeżeli ... przekazuje argumenty do funkcji, dajmy na to f(), która z kolei je przekazuje do g(), potem do h() itd. Takich poziomów może być kilka i trudno będzie "zakodować" listę wszystkich możliwych argumentów wobec których wynik match.call będzie można match-ować.

Czwarty problem, związany z powyższym to przekazywanie argumentów przez funkcje generyczne różnym metodom. Przykładowo, argumenty akceptowane przez plot() w ramach ... będą różne w zależności od tego jakim obiektem jest 'x' w wywołaniu plot. Klasa tego obiektu determinuje czy ... zostanie przekazane do plot.default, plot.data.frame, plot.table, plot.function etc....

Wniosek: automatyczna metoda przydaje sie wtedy, gdy masz pełną kontrolę nad tym co się z tymi argumentami dzieje później.
Kamil Bęczyński

Kamil Bęczyński R, SAS, analizy

Temat: Pytanie odnośnie '...'

Michał Bojanowski:
Jest kilka możliwości, użyteczność każdej zależy ile argumentów przekazujesz. Ponieważ plot i lm akceptują bardzo dużo dodatkowych argumentów przez ... więc, gdybym miał to robić, to bym zrobił tak za pomocą 'do.call':


f <- function(x, plot.args=NULL, lm.args=NULL)[/quote]> {[quote]model <- do.call("lm", c( list(x=x), lm.args))[/quote]> do.call("plot", c(list(x=model$res), plot.args))[quote]}


plot.args i lm.args powinny być listami z argumentami do przekazania do, odpowiednio, plot i lm. Na przykład:

f( x, lm.args=list(model=FALSE), plot.args=list(type="l") )

itd itp etc

EDIT: zle byly nawiasy w funkcji f...

Właśnie takiego fragmentu kodu szukałem : "model <- do.call("lm", c( list(x=x), lm.args))"
wcześniej kombinowałem z call() i eval(), ale nie mogłem znaleźć rozwiązania. Rozwiązanie z listami jest bardzo zwięzłe, o to mi chodziło.
Wojciech Sobala

Wojciech Sobala Redaktor
statystyczny,
biostatystyk,
Instytut Medycyny
Pr...

Temat: Pytanie odnośnie '...'

Aby zabewnić pełną kontrolę na przekazywanymi przez listę parametrami można zdefiniować funkcję do walidacji przekazywanych parametrów, poniżej przykład z funkcji gpar z pakietu grid.


gpar <- function (...)
{
gp <- validGP(list(...))
class(gp) <- "gpar"
gp
}



Wyślij zaproszenie do