Разбиение строки на первом пространстве
Я хотел бы разбить вектор символьных строк (имена людей) на два столбца (векторы). Проблема в том, что у некоторых людей есть фамилия "два слова". Я хотел бы разбить имя и фамилию на два столбца. Я могу вырезать и взять первые имена, используя код ниже, но фамилия ускользает от меня. (посмотрите на обс 29 в примере, приведенном ниже, чтобы получить представление о том, что у Форда есть "фамилия" Pantera L, которая должна храниться вместе)
То, что я пытался сделать до сих пор;
x<-rownames(mtcars)
unlist(strsplit(x, " .*"))
Как бы мне хотелось выглядеть:
MANUF MAKE
27 Porsche 914-2
28 Lotus Europa
29 Ford Pantera L
30 Ferrari Dino
31 Maserati Bora
32 Volvo 142E
Ответы
Ответ 1
Регулярное выражение rexp
соответствует слову в начале строки, необязательному пространству, а затем остальной строке. Скобки являются подвыражениями, доступными как обратные ссылки \\1
и \\2
.
rexp <- "^(\\w+)\\s?(.*)$"
y <- data.frame(MANUF=sub(rexp,"\\1",x), MAKE=sub(rexp,"\\2",x))
tail(y)
# MANUF MAKE
# 27 Porsche 914-2
# 28 Lotus Europa
# 29 Ford Pantera L
# 30 Ferrari Dino
# 31 Maserati Bora
# 32 Volvo 142E
Ответ 2
Для меня функция Hadley colsplit
в пакете reshape2
является наиболее интуитивной для этой цели. Способ Джошуа более общий (т.е. Может использоваться везде, где может использоваться регулярное выражение) и гибким (если вы хотите изменить спецификацию); но функция colsplit
отлично подходит для этой конкретной настройки:
library(reshape2)
y <- colsplit(x," ",c("MANUF","MAKE"))
tail(y)
# MANUF MAKE
#27 Porsche 914-2
#28 Lotus Europa
#29 Ford Pantera L
#30 Ferrari Dino
#31 Maserati Bora
#32 Volvo 142E
Ответ 3
Вот два подхода:
1) strsplit. Этот подход использует только функции в ядре R и не содержит сложных регулярных выражений. Замените первое пространство точкой с запятой (используя sub
, а не gsub
), strsplit
в точке с запятой, а затем rbind
в матрицу из двух столбцов:
mat <- do.call("rbind", strsplit(sub(" ", ";", x), ";"))
colnames(mat) <- c("MANUF", "MAKE")
2) в комплекте gsubfn. Ниже приведен один слой с использованием strapply
в пакете gsubfn. Две скобки в регулярном выражении фиксируют желаемый первый и второй столбцы соответственно, а функция (которая указана в нотации формулы - ее то же, что и указание function(x, y) c(MANUF = x, MAKE = y)
), захватывает их и добавляет имена. Аргумент simplify=rbind
используется для превращения его в матрицу, как в предыдущем решении.
library(gsubfn)
mat <- strapply(x, "(\\S+)\\s+(.*)", ~ c(MANUF = x, MAKE = y), simplify = rbind)
Примечание. В любом случае возвращается матрица "character"
, mat
. Если требуется кадр данных в столбцах "character"
, добавьте следующее:
DF <- as.data.frame(mat, stringsAsFactors = FALSE)
Опустите аргумент stringsAsFactors
, если нужны столбцы "factor"
.
Ответ 4
Еще один способ сделать это:
str_split
из stringr
будет обрабатывать split, но возвращает его в другой форме (список, например strsplit
). Манипулирование в правильную форму является простым, хотя.
library(stringr)
split_x <- str_split(x, " ", 2)
(y <- data.frame(
MANUF = sapply(split_x, head, n = 1),
MAKE = sapply(split_x, tail, n = 1)
))
Или, как упоминал Хэдли в комментариях, с str_split_fixed
.
y <- as.data.frame(str_split_fixed(x, " ", 2))
colnames(y) <- c("MANUF", "MAKE")
y
Ответ 5
Если вы можете выполнить сопоставление шаблонов и групп, я бы попробовал что-то вроде этого (untested):
\s+(.*)\s+(.*)
Ответ 6
Я думаю, что поиск [^\s]+
будет работать. Непроверенные.