Разделить вектор строк и вставить подмножество результирующих элементов в новый вектор

Определить

z<- as.character(c("1_xx xx xxx_xxxx_12_sep.xls","2_xx xx xxx_xxxx_15_aug.xls"))

такое, что

> z
[1] "1_xx xx xxx_xxxx_12_sep.xls" "2_xx xx xxx_xxxx_15_aug.xls"

Я хочу создать вектор w такой, что

> w
[1] "1_12_sep" "2_15_aug"

То есть разбиваем каждый элемент z на _ и затем соединяем элементы 1,4,5 с удалением из .xls из последнего.

Я могу управлять разделенной частью, но не уверен, какую функцию предоставить, например, что-то вроде

w <- as.character(lapply(strsplit(z,"_"), function(x) ???))

Ответ 1

Вы можете сделать это, используя комбинацию strsplit, substr и lapply:

y <- strsplit(z,"_",fixed=TRUE)
lapply(y,FUN=function(x){paste(x[1],x[4],substr(x[5],1,3),sep="_")})

Ответ 2

Используя немного магии в пакете stringr: я отдельно извлекаю поля левой и правой даты, объединяю их и, наконец, удаляю .xls в конце.

library(stringr)
l <- str_extract(z, "\\d+_")
r <- str_extract(z, "\\d+_\\w*\\.xls")
gsub(".xls", "", paste(l, r, sep=""))

[1] "1_12_sep" "2_15_aug"

str_extract является оберткой вокруг некоторых базовых R-функций, которые мне легче использовать.

Изменить. Ниже приведено краткое описание того, что делает регулярное выражение:

  • \\d+ ищет одну или несколько цифр. Это ускользает, чтобы отличить от нормального символа d.
  • \\w* ищет нулевые или более буквенно-цифровые символы (слово). Опять же, это ускользнуло.
  • \\. ищет десятичную точку. Это нужно экранировать, потому что в противном случае десятичная точка означает любой символ.

Теоретически регулярное выражение должно быть достаточно гибким. Он должен найти одиночные или двойные символы для ваших дат.

Ответ 3

Один вызов gsub (и некоторая магия регулярных выражений, основанная на ответе @Andrie) может сделать это. Подробнее о том, что я использовал в аргументах pattern и replacement (back-reference), см. ?regexp.

gsub("^(\\d+_).*_(\\d+_\\w*).xls", "\\1\\2", z)
# [1] "1_12_sep" "2_15_aug"

Ответ 4

Альтернатива по тем же строкам @Joran Ответ таков:

foo <- function(x) {
    o <- paste(x[c(1,4,5)], collapse = "_")
    substr(o, 1, nchar(o) - 4) 
}

sapply(strsplit(z, "_"), foo)

Различия незначительны - я использую collapse = "_" и nchar(), но не похож.

Вы можете написать это как однострочный

sapply(strsplit(z, "_"), 
       function(x) {o <- paste(x[c(1,4,5)], 
                               collapse = "_"); substr(o, 1, nchar(o)-4)})

но запись пользовательской функции для применения лучше.