2013-05-20 5 views
2

При применении индивидуально к каждому элементу вектора моя функция дает другой результат, чем использование sapply. Это сводит меня с ума!Sapply отличается от индивидуального применения функции

Item Я использую: это (упрощенный) список аргументов другой функции была вызвана:

f <- as.list(match.call()[-1]) 
> f 
$ampm 
c(1, 4) 

Чтобы повторить это можно выполнить следующие действия:

foo <- function(ampm) {as.list(match.call()[-1])} 
f <- foo(ampm = c(1,4)) 

Вот моя функция , Он просто удаляет 'c (...)' из строки.

stripConcat <- function(string) { 
    sub(')','',sub('c(','',string,fixed=TRUE),fixed=TRUE) 
} 

При использовании только одного он работает так, что это то, что я хочу:

> stripConcat(f) 
[1] "1, 4" 

Но при использовании sapply, это дает что-то совершенно другое, что я не хочу:

> sapply(f, stripConcat) 
ampm 
[1,] "c" 
[2,] "1" 
[3,] "4" 

Lapply не работает либо:

> lapply(f, stripConcat) 
$ampm 
[1] "c" "1" "4" 

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

+0

'> Структура dput (f) (список (ampm = c (1, 4)), .Names =" ampm ")' – esa606

+2

Проблема здесь (что я полностью понять) - это различие между «as.character (f)» и «as.character» (f [[1]]). Попробуйте 'sapply (as.character (f), stripConcat)'. – joran

+0

Это почти добирается! Он дает правильный ответ, но удаляет имя элемента: '> sapply (as.character (f), stripConcat) c (1, 4)« 1, 4 », тогда как ранее элемент« 1,4 »был назван« ampm ». – esa606

ответ

2

Неверность, которую вы видите, я считаю, объясняется просто тем, как as.character заставляет элементы списка.

x2 <- list(1:3, quote(c(1, 5))) 
as.character(x2) 
[1] "1:3"  "c(1, 5)" 

lapply(x2, as.character) 
[[1]] 
[1] "1" "2" "3" 

[[2]] 
[1] "c" "1" "5" 

f не призыв, а список, чей первый элемент является вызовом.

is(f) 
[1] "list" "vector" 
as.character(f) 
[1] "c(1, 4)" 

> is(f[[1]]) 
[1] "call"  "language" 
> as.character(f[[1]]) 
[1] "c" "1" "4" 

sub попытки заставить что-либо, что не персонаж в chracter.
Когда вы передаете дополнительный список, он называет as.character на list.
Когда вы передаете ему вызов, он называет as.character на этом call.


Похоже, для stripConcat функции, вы предпочитают список в качестве входных данных.

В этом случае я бы рекомендовал следующее для этой функции:

stripConcat <- function(string) { 
    if (!is.list(string)) 
     string <- list(string) 
    sub(')','',sub('c(','',string,fixed=TRUE),fixed=TRUE) 
} 

Однако следует отметить, что строка является неправильным, так как это не кажется, что вы когда-либо планируют пройти stripConcat строка. (нет, конечно, это проблема)

+1

, вы, вероятно, должны добавить, что, полагая, что это правильный ввод, исправление заключается в вызове 'deparse' внутри функции OP – eddi

+0

@eddi, я просто добавил пункт об исправлении функции, но я бы не пошел с' deparse'. –

+0

Спасибо, что это отлично работает! – esa606