К сожалению, хвост относительно медленный. На самом деле индексирование последнего элемента выполняется намного быстрее.
FUN <- function(x) {ss <- strsplit(x,' ')[[1]];ss[length(ss)]}
На моей машине это вдвое быстрее, чем команда tail.
y <- c("AAAAAAAAAAA 250.00",
"01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 5.13",
"01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 834591283405347 50.00")
#make y bigger so that there's something to test
y <- rep(y, 1e5)
#testing tail
FUN <- function(x) {tail(strsplit(x,' ')[[1]],1)}
system.time( lapply(y,FUN) )
user system elapsed
22.108 0.110 22.069
#testing indexing
FUN <- function(x) {ss <- strsplit(x,' ')[[1]];ss[length(ss)]}
system.time( lapply(y,FUN) )
user system elapsed
9.396 0.037 9.372
Но еще большая скорость достигается за счет разделения функции и использования факта, что компоненты уже векторизованы. (Весь смысл применения семейства команд состоит не в том, чтобы заменить циклы, а в том, чтобы разрешить простой синтаксис и максимально использовать векторизованные команды. Простейшие функции, которые должны быть выполнены, должны быть в порядке и тому подобное.)
#first let strsplit do it's own vectory magic
s <- strsplit(y, ' ')
#then define a simpler function
FUN <- function(x) x[length(x)]
lapply(s, FUN)
Чтобы проверить время, необходимо сохранить strsplit внутри процедуры синхронизации, чтобы сделать ее справедливой
system.time( {s <- strsplit(y, ' ');lapply(s, FUN)} )
user system elapsed
5.281 0.048 5.305
(Я почти уверен, что что-то упустил в индексировании списков, и моя функция должна быть еще проще.)
Еще одна вещь, хотя ... и это ускорило бы весь процесс, но я просто добавлю это здесь. strsplit () имеет фиксированную опцию. Это работает намного быстрее, если вы установите значение true, если вы не используете регулярное выражение.
system.time( {s <- strsplit(y, ' ', fixed = TRUE); lapply(s, FUN)} )
user system elapsed
1.256 0.007 1.253
Если вы делаете это для большого набора данных или вам приходится часто делать это даже для наборов данных среднего размера, вам действительно следует использовать этот последний метод. Это почти в 20 раз быстрее.
Вот окончательное решение, которое можно просто скопировать для выполнения всей задачи, предполагая, что Y - это вектор символьных строк, отформатированный так, как ожидалось в Edit # 3. Ожидается, что последний элемент представляет собой денежную ценность для сохранения, а второй последний элемент является своего рода идентификатором.
s <- strsplit(y, ' ', fixed = TRUE)
moneyVal <- lapply(s, function(x) x[length(x)])
idVal <- lapply(s, function(x) x[length(x)-1])
restOfY <- lapply(s, function(x) paste(x[1:(length(x)-2)], collapse = ' '))
#These three values can be combined into a data frame
df <- data.frame(restOfY, idVal, moneyVal)