我想将字符串(人名)的矢量分成两列(矢量)。问题是有些人有一个“两个字”的姓氏。我想将名字和姓氏分成两列。我可以使用下面的代码切出并使用名字,但姓氏使我无效。 (看看下面的样本集中的obs 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
答案 0 :(得分:26)
正则表达式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
答案 1 :(得分:17)
对我而言,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
答案 2 :(得分:11)
以下是两种方法:
1)strsplit 。此方法仅使用R核心中的函数,并且不使用复杂的正则表达式。将第一个空格替换为分号(使用sub
和不 gsub
),strsplit
替换分号,然后将rbind
替换为2列矩阵:
mat <- do.call("rbind", strsplit(sub(" ", ";", x), ";"))
colnames(mat) <- c("MANUF", "MAKE")
2)gsubfn包中的strapply 这是gsubfn包中使用strapply
的单行内容。正则表达式的两个带括号的部分分别捕获所需的第一列和第二列,并且函数(在公式表示法中指定 - 与指定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"
参数。
答案 3 :(得分:7)
另一种方法:
来自str_split
的 stringr
将处理拆分,但会以不同的形式(列表,如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
答案 4 :(得分:0)
如果你可以进行模式和组匹配,我会尝试这样的事情(未经测试):
\s+(.*)\s+(.*)
答案 5 :(得分:0)
我认为搜索[^\s]+
会有效。未经测试。