Подтвердить что ты не робот

Разбиение строки на первом пространстве

Я хотел бы разбить вектор символьных строк (имена людей) на два столбца (векторы). Проблема в том, что у некоторых людей есть фамилия "два слова". Я хотел бы разбить имя и фамилию на два столбца. Я могу вырезать и взять первые имена, используя код ниже, но фамилия ускользает от меня. (посмотрите на обс 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
4b9b3361

Ответ 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]+ будет работать. Непроверенные.