我的数据框架如下:
b <- data.frame(height = c(190,165,174,176), name = c('John Smith 34','Mr.Turner 54', 'Antonio P. 23', 'John Brown 31'))
# height name
# 1 190 John Smith 34
# 2 165 Mr.Turner 54
# 3 174 Antonio P. 23
# 4 176 John Brown 31
我们可以看到名称和年龄是相同的值。所以我想用字符串中的最后两个字符拆分它:
height name age
1 190 John Smith 34
2 165 Mr.Turner 54
3 174 Antonio P. 23
4 176 John Brown 31
我怎么能这样做?
答案 0 :(得分:5)
tidyr::separate
允许您传递分割位置的整数索引(包括从字符串末尾负向索引),从而使分隔列变得简单。 (当然,正则表达式也可以。)
library(tidyr)
b %>% separate(name, into = c('name', 'age'), sep = -4, convert = TRUE)
## height name age
## 1 190 John Smith 34
## 2 165 Mr.Turner 54
## 3 174 Antonio P. 23
## 4 176 John Brown 31
或以最终空格分开:
b %>% separate(name, into = c('name', 'age'), sep = '\\s(?=\\S*?$)', convert = TRUE)
返回同样的东西。
在基础R中,它需要更多工作:
b$name <- as.character(b$name)
split_name <- strsplit(b$name, '\\s(?=\\S*?$)', perl = TRUE)
split_name <- do.call(rbind, split_name)
colnames(split_name) <- c('name', 'age')
b <- data.frame(b[-2], split_name, stringsAsFactors = FALSE)
b$age <- type.convert(b$age)
b
## height name age
## 1 190 John Smith 34
## 2 165 Mr.Turner 54
## 3 174 Antonio P. 23
## 4 176 John Brown 31
答案 1 :(得分:3)
这里使用正则表达式的许多选项。我会使用substr
,因为您想要确切地知道要提取的字符数。
在data.table
内(对于syntax-sugar):
library(data.table)
setDT(b)[,c("name","age"):=list(
substr(name,1,nchar(name)-3),
substr(name,nchar(name)-2,nchar(name)))]
height name age
1: 190 John Smith 34
2: 165 Mr.Turner 54
3: 174 Antonio P. 23
4: 176 John Brown 31
请注意,名称应为character
:
b <- data.frame(
height = c(190,165,174,176),
name = c('John Smith 34','Mr.Turner 54', 'Antonio P. 23', 'John Brown 31'),
stringsAsFactors = FALSE)
答案 2 :(得分:1)
使用基数R(与@ agstudy的答案中使用的数据相同):
data.frame(t(apply(b,1,function(x) {s <- unlist(strsplit(trimws(x[2]), " "));
c(x[1],paste0(head(s,-1),collapse=" "),tail(s,1)) })))
# X1 X2 X3
# 1 190 John Smith 34
# 2 165 Mr.Turner 54
# 3 174 Antonio P. 23
# 4 176 John Brown 31
为了安全起见,我们按空格(即name
)拆分修剪 strsplit(trimws(x[2]), " ")
列并取最后一部分(即tail(s,1)
)作为age
,其余(即head(s,-1)
)作为名称。
答案 3 :(得分:1)
就个人而言,我会发现以下正则表达式最有用。
library (stringr)
b $age <- str_extract (b$name, "\\d{1,3}$")
b $name <- str_replace (b $name, "\\d{1,3}$", "")
这将在字符串末尾查找长度为1-3个字符的数字序列。可能有一种方法可以将其合并到separate
语法中,但我是从手机上写的,无法探索。
这个正则表达式的优点是它可以处理单个,两个和三个数字的年龄,而不必依赖于存在的空间,或者必须从字符串的末尾开始倒数。
答案 4 :(得分:1)
我们可以使用,
创建分隔符(sub
)而不是年龄前的空格,使用read.table
和cbind
使用第一列使用{{ 1}}
base R
或使用cbind(b[1],read.table(text=sub("\\s+(\\d+)$", ", \\1", b$name),
col.names = c("name", "age"), header=FALSE, sep=","))
# height name age
#1 190 John Smith 34
#2 165 Mr.Turner 54
#3 174 Antonio P. 23
#4 176 John Brown 31
extract
tidyr