R: Используйте аргументы функции в качестве имен для подэлементов списка.

Вот упрощенный пример того, что я пытаюсь сделать

set.seed(1)
a <- rnorm(10)
b <- rnorm(10)

asdf<-function(vec1,vec2){
  mylist <- list(sums = c(vec1 = sum(a), vec2 = sum(b)),
                 products = c(vec1 = prod(a), vec2 = prod(b)))
  return(mylist)
}

asdf(a,b)

Вот результат:

$sums
vec1     vec2 
1.322028 2.488450 
$products
vec1         vec2 
0.0026236813 0.0003054751 

Имена элементов списка основаны на именах, которые я указал при определении функции, а не на фактических входных данных, используемых в функции. В целом это имеет смысл, но я хотел бы знать, как изменить это поведение для конкретной проблемы.

Мой желаемый результат, учитывая входные данные a и b, будет

$sums
a        b 
1.322028 2.488450 

$products
a            b 
0.0026236813 0.0003054751 

Какими бы ни были входные данные, будь то c(1,2,3,3,3,123) и c(2,1,1,5,7,1) или rnorm(10) и rpois(10), они должны быть возвращены на выходе.

Я знаю, как сделать переименование после выполнения функции, но я хочу, чтобы наименование происходило внутри функции. Я просматривал некоторые другие вопросы о SO, но у меня ничего не получалось.

Несколько вещей, которые я пробовал без успеха.

asdf<-function(vec1,vec2){
  name1<- deparse(substitute(vec1))
  name2<- deparse(substitute(vec2))
  mylist <- list(sums = c(name1 = sum(a), name2 = sum(b)),
                 products = c(name1 = prod(a), name2 = prod(b)))
  return(mylist)
}

asdf<-function(vec1,vec2){ 
  mylist <- list(sums = c(name1 = sum(a), name2 = sum(b)),
                 products = c(name1 = prod(a), name2 = prod(b)))
  assign(names(mylist(vec1,vec2)$sums,
         c(deparse(substitute(vec1)),deparse(substitute(vec2)))))
  return(mylist)
}

Кажется, мне может понадобиться использовать get, assign или match.call, но здесь я не в своей лиге.

Я чувствую себя немного тупицей, читая некоторые из этих справочных страниц. Если я не знаю достаточно, чтобы понять страницы справки, что ж, я далеко не так хорош в R, как я думал.


person Jota    schedule 27.11.2013    source источник


Ответы (1)


используйте substitute для захвата имен, затем setNames для их установки.

asdf<-function(vec1,vec2){
  nms <- as.character(c(substitute(vec1), substitute(vec2)))

  mylist <- list(sums = c(vec1 = sum(a), vec2 = sum(b)),
                 products = c(vec1 = prod(a), vec2 = prod(b)))

  # return
  lapply(mylist, setNames, nms)
}

asdf(a,b)

вы можете поместить setNames прямо в вызов list() выше, но это может привести к тому, что код будет слишком громоздким для чтения

person Ricardo Saporta    schedule 27.11.2013
comment
+1, Просто ради обучения, могу я попросить вас предоставить код с setNames в вызове list()? Я дурачился с этим, но я думаю, что сегодня вечером я должен быть очень тугим. - person Jota; 27.11.2013