2011-11-28 91 views
20

我想将字符串(人名)的矢量分成两列(矢量)。问题是有些人的姓氏是'两个字'。我想将姓氏和名字分成两列。我可以利用下面的代码分出头名,但最后一个名字不见了。 (看OBS 29的下方设置的样品中得到一个想法作为福特拥有的,必须放在一起潘多拉升的“姓氏”)在第一个空格上分割一个字符串

我试图到目前为止做的;

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 

回答

25

正则表达式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 
+0

@ Joshua Ullrich美丽。谢谢你的解释。 –

0

如果你可以做模式和组匹配,我想尝试像这样(未经):

\s+(.*)\s+(.*) 
+4

大家知道,正则表达式在R中的工作方式有点不同。至少,你需要在每个s前面添加一个\,以避免错误。 – joran

0

我认为搜索[^\s]+将工作。未经测试。

17

对于我来说,哈德利的在reshape2colsplit功能是最直观的用于这一目的。约书亚的方式是更一般的(即可以使用任何正则表达式可以使用)和灵活(如果你想改变规范);但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 
+0

非常好的使用列拆分。谢谢。 –

+0

+1非常有趣,因为我认为在这种情况下'colsplit'将返回三列以上。我是多么的错误。 – Andrie

7

然而,这样做的另一种方式:

str_splitstringr将处理拆分,但以不同的形式返回它(列表,像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 
+0

@Riche通过哈德利Wickham包的另一个解决方案。感谢分享 –

+2

使用'str_split_fixed'甚至更好# – hadley

+1

有趣的是,这个答案+ hadley的评论与'colsplit'解决方案有关,因为'colsplit'使用'str_split_fixed'。 –

11

这里有两种方法:

1)strsplit。这种方法仅使用R核心中的函数,而没有复杂的正则表达式。替换用分号第一空间(使用subgsub)上分号,strsplit然后rbind它变成一个2列矩阵:在gsubfn包这里

mat <- do.call("rbind", strsplit(sub(" ", ";", x), ";")) 
colnames(mat) <- c("MANUF", "MAKE") 

2)strapply是一-liner在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"列想要的。

+0

我刚刚在这里检查过。我确实喜欢你的#1解决方案是最好的。谢谢并为以后的回报感到遗憾。 –