Применение регулярных выражений к вектору

Я в недоумении, почему следующий код не работает. Намерение состоит в том, чтобы ввести вектор строк, некоторые из которых могут быть преобразованы в число, а некоторые нет. Следующая функция sapply должна использовать регулярное выражение для сопоставления чисел, а затем возвращать число или (если нет) возвращать оригинал.

sapply(c("test","6","-99.99","test2"), function(v){
  if(grepl("^[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?$",v)){as.numeric(v)} else {v}
})

Что возвращает следующий результат:

"test"      "6" "-99.99"  "test2" 

Изменить: что я ожидаю, что код вернет:

"test"      6  -99.99    "test2

Я могу успешно запустить оператор if для каждого элемента.

> if(grepl("^[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?$","test")){as.numeric("test")} else {"test"}
[1] "test"
if(grepl("^[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?$","6")){as.numeric("6")} else {"6"}
[1] 6

И так далее...

Я не понимаю, почему это происходит. Думаю, у меня есть два вопроса. Один: Почему это происходит? И второе: обычно я неплохо разбираюсь в устранении неполадок, но понятия не имею, где это искать. Если вы знаете проблему, как вы нашли/узнали решение? Должен ли я открыть внутренний код функции lapply?


person nfmcclure    schedule 11.03.2014    source источник


Ответы (2)


это происходит потому, что sapply возвращает вектор, а вектор нельзя смешивать. Если вы используете lapply, вы получите результат списка, который можно смешивать, тот же код, но с lapply вместо sapply работает так, как вы хотите.

person JeremyS    schedule 11.03.2014
comment
Ах! Спасибо. Не знаю, как этот факт у меня проскочил - прямо в справке. Лаппли будет работать отлично. - person nfmcclure; 11.03.2014
comment
sapply также возвращает список. Если вы спросите об этом. - person Roman Luštrik; 11.03.2014
comment
да, но тогда вы в основном просто просите, чтобы это было глупо. sapply означает упрощенный lappy. - person JeremyS; 12.03.2014

@Jeremy указывает правильное направление, вы можете использовать lapply, который возвращает список. Или вы можете указать sapply не упрощать результат.

Если происходит упрощение, тип вывода определяется из самого высокого типа возвращаемых значений в иерархии NULL ‹ исходное ‹ логическое ‹ целое ‹ двойное ‹ сложное ‹ символ ‹ список ‹ выражение, после приведения парных списков к спискам.

out <- sapply(c("test","6","-99.99","test2"), function(v){

  if(grepl("^[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?$",v)){
    as.numeric(v)
  } else {
    v
  }
}, simplify = FALSE)
> out
$test
[1] "test"

$`6`
[1] 6

$`-99.99`
[1] -99.99

$test2
[1] "test2"
person Roman Luštrik    schedule 11.03.2014