2016-12-20 2 views
2

Есть ли способ сделать следующий список функций, используя lapply? Ниже я делаю список, названный «длинным» длинным путем. Я хотел бы упростить код, используя lapply (или цикл for), но ни один из них не работает. Спасибо.Сделать список функций с lapply

#This works as expected 
long <- list(function(x) x <- within(x, DATE <- as.Date("2013-01-01")), 
      function(x) x <- within(x, DATE <- as.Date("2014-01-01")), 
      function(x) x <- within(x, DATE <- as.Date("2015-01-01"))) 

#This does not work 
long <- lapply(2013:2015, function(i) x <- within(x, DATE <- as.Date(paste(i, "01", "01", sep = "-")))) 

#This does not work 
for (i in 2013:2015) long <- list(function(x) x <- within(x, DATE <- as.Date(paste(i, "01", "01", sep = "-")))) 

ответ

4

Возможно, самый простой способ - добавить еще function.

long <- lapply(2013:2015, 
       function(i) function(x) { 
          x <- within(x, DATE <- as.Date(paste(i, "01", "01", sep = "-")))}) 

Убедитесь, что элементы функции

typeof(long[[1]]) 
[1] "closure" 

Попробуй

# empty list, x 
x <- list() 
x <- long[[1]](x) 
x 
$DATE 
[1] "2013-01-01" 

Как @Roland упоминает в комментариях, было бы безопаснее, чтобы заставить оценку из i аргумент.

long <- lapply(2013:2015, function(i) { 
          force(i); 
          function(x) x <- within(x, 
              DATE <- as.Date(paste(i, "01", "01", sep = "-"))) 
          }) 
+0

Спасибо, но это не дает того же результата, что и в моем примере. – user1491868

+2

@ user1491868 Единственное различие заключается в том, что значение 'i' сохраняется в окружающей среде функций. Они могут использоваться и давать те же возвращаемые значения, что и ваш пример. – Roland

+3

@lmo Я думаю, что я старомодный, но я бы «заставил (i)». – Roland

3

С некоторыми bquote магией:

dates <- c("2013-01-01", "2014-01-01", "2015-01-01") 

lapply(dates, function(d) eval(bquote(function(x) within(x, DATE <- as.Date(.(d)))))) 

#[[1]] 
#function (x) 
#within(x, DATE <- as.Date("2013-01-01")) 
#<environment: 0x000002b1815ba450> 
# 
#[[2]] 
#function (x) 
#within(x, DATE <- as.Date("2014-01-01")) 
#<environment: 0x000002b1815ae320> 
# 
#[[3]] 
#function (x) 
#within(x, DATE <- as.Date("2015-01-01")) 
#<environment: 0x000002b1815a1520> 

(Назначение x <- within(...) лишнее внутри функции.)

Объяснения: bquote создает невычисленный объект выражения, с символами Отмеченных .(*) заменены на их значения. Затем вычисляется выражение eval.

В этом случае bquote создает вызов для генерации функции с использованием function(x) ... с конкретной вставленной датой, так что если d имеет значение "2013-01-01", то bquote(function(x) ... as.Date(.(d)) приводит к экспрессии function(x) ... as.Date("2013-01-01")невычисленного. Когда вы вызываете eval, результатом является объект функции, содержащий ваш желаемый орган функции.

Для получения более подробной информации см. ?eval и ?bquote.

+0

Этот список идентичен моему примеру, но для . – user1491868

+1

Это нормально, это среда, созданная 'lapply'. Он по-прежнему будет работать. –

+0

Спасибо, что это очень хорошо. Если у вас есть момент, чтобы объяснить, что делают «eval» и «bquote», это будет здорово. – user1491868

Смежные вопросы