Назначьте имена элементам списка, где имя = имя объекта передачи функции

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

Вот пример:

returnNamedListofDataFrames.Test <- function(...) {

  # read inputs in list
  inputs <- list(...)

  # assign names to data frame list elements that have no names
  # ???
  inputs <- inputs %>% setNames(lapply(inputs[(names(inputs) == "") %>% which],
                                       function(x) deparse(substitute(x))))

  # return
  return(inputs = inputs)
}


# input data
a = data.frame(value = 1)
b = data.frame(value = 2)

output <- returnNamedListofDataFrames.Test(c = a, # named element, name should stay "c"
                                           b)     # unnamed element, name should be "b"

expected.output <- list(c = a,
                        b = b)

Здесь вывод:

> output
$`X[[i]]`
  value
1     1

$<NA>
  value
1     2

Причины:

  • Функция setNames получает только один элемент, но setNames требует имена для всех элементов, поэтому один из них — NA.
  • Трюк deparse(substitute(x)) не работает внутри такого вызова функции.

Я не знаю, как решить эти проблемы, и приветствую любые советы.

Для справки вывод должен быть:

> expected.output
$c
  value
1     1

$b
  value
1     2

person mzuba    schedule 08.11.2017    source источник
comment
Вам нужно setNames(mget(c('a', 'b')), c('c', 'b'))   -  person akrun    schedule 08.11.2017
comment
Проблема в том, что я не могу жестко закодировать имена, так как они должны быть такими, какими являются аргументы функции.   -  person mzuba    schedule 08.11.2017


Ответы (2)


Используйте 1_:

returnNamedListofDataFrames.Test <- function(...) {
  callvars <- as.list(match.call())[-1]
  name <- names(callvars)
  if (is.null(name)) name <- as.character(callvars) else 
    name[name == ""] <- as.character(callvars[name == ""])

  setNames(list(...), name)
}

returnNamedListofDataFrames.Test(c = a, # named element, name should stay "c"
                                 b)

#$c
#  value
#1     1
#
#$b
#  value
#1     2
person Roland    schedule 08.11.2017
comment
но попробуйте returnNamedListofDataFrames.Test(a, b) (я получаю [[1]] value 1 1 [[2]] value 1 2) - person duckmayr; 08.11.2017
comment
идеально; просто думая о комментарии OP, что я не могу жестко закодировать имена, поскольку они должны быть любыми аргументами функции - person duckmayr; 08.11.2017

Мы можем использовать substitute

f1 <- function(...) {
  v1 <- as.list(substitute(list(...)))[-1L]  

  inputs <- list(...)
  i1 <- names(inputs)
  i2 <- i1 == ""
  if(is.null(i1)) {
     names(inputs) <- v1
   } else names(inputs)[i2] <- v1[i2]


 inputs
 }

f1(c=a, b)
#$c
#    value
#1     1

#$b
#   value
#1     2


f1(a, b)
#$a
#   value
#1     1

#$b
#  value
#1     2
person akrun    schedule 08.11.2017
comment
но попробуйте f1(a, b) (я получаю [[1]] value 1 1 [[2]] value 1 2) - person duckmayr; 08.11.2017
comment
идеально; просто думая о комментарии OP, что я не могу жестко закодировать имена, поскольку они должны быть любыми аргументами функции - person duckmayr; 08.11.2017