zx8*_*754 10 regex r delimiter dataframe
我有一个列data.frame,其中一些空格应该是分隔符,有些只是一个空格.
#input data
dat <- data.frame(x=c("A 2 2 textA1 textA2 Z1",
"B 4 1 textX1 textX2 textX3 Z2",
"C 3 5 textA1 Z3"))
# x
# 1 A 2 2 textA1 textA2 Z1
# 2 B 4 1 textX1 textX2 textX3 Z2
# 3 C 3 5 textA1 Z3
Run Code Online (Sandbox Code Playgroud)
需要将其转换为5列data.frame:
#expected output
output <- read.table(text="
A 2 2 textA1 textA2 Z1
B 4 1 textX1 textX2 textX3 Z2
C 3 5 textA1 Z3",sep="\t")
# V1 V2 V3 V4 V5
# 1 A 2 2 textA1 textA2 Z1
# 2 B 4 1 textX1 textX2 textX3 Z2
# 3 C 3 5 textA1 Z3
Run Code Online (Sandbox Code Playgroud)
基本上,需要将第一个,第二个,第三个和最后一个空格更改为选项卡(或任何其他分隔符,如果它更容易编码).
玩弄regex没有任何有用的东西......
注1:在实际数据中,我必须将第1,第2,第3,......,第19和最后一个空格替换为制表符.
注2:没有模式V4,文本可以是任何东西.
注3:最后一列是一个可变长度的单词文本.
尝试
v1 <- gsub("^([^ ]+)\\s+([^ ]+)\\s+([^ ]+)\\s+", '\\1,\\2,\\3,', dat$x)
read.table(text=sub(' +(?=[^ ]+$)', ',', v1, perl=TRUE), sep=",")
# V1 V2 V3 V4 V5
#1 A 2 2 textA1 textA2 Z1
#2 B 4 1 textX1 textX2 textX3 Z2
#3 C 3 5 textA1 Z3
Run Code Online (Sandbox Code Playgroud)
或者选择灵感来自@ Tensibai的帖子
n <- 3
fpat <- function(n){
paste0('^((?:\\w+ ){', n,'})([\\w ]+)\\s+(\\w+)$')
}
read.table(text=gsub(fpat(n), "\\1'\\2' \\3", dat$x, perl=TRUE))
# V1 V2 V3 V4 V5
#1 A 2 2 textA1 textA2 Z1
#2 B 4 1 textX1 textX2 textX3 Z2
#3 C 3 5 textA1 Z3
Run Code Online (Sandbox Code Playgroud)
对于更多列,
n <- 19
v1 <- "A 24 34343 212 zea4 2323 12343 111 dsds 134d 153xd 153xe 153de 153dd dd dees eese tees3 zee2 2353 23335 23353 ddfe 3133"
read.table(text=gsub(fpat(n), "\\1'\\2' \\3", v1, perl=TRUE), sep='')
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15
#1 A 24 34343 212 zea4 2323 12343 111 dsds 134d 153xd 153xe 153de 153dd dd
# V16 V17 V18 V19 V20 V21
#1 dees eese tees3 zee2 2353 23335 23353 ddfe 3133
Run Code Online (Sandbox Code Playgroud)
使用可变数量的列:
library(stringr)
cols <- 3
m <- str_match(dat$x, paste0("((?:\\w+ ){" , cols , "})([\\w ]+) (\\w+)"))
t <- paste0(gsub(" ", "\t", m[,2]), m[,3], "\t", m[,4])
> read.table(text=t,sep="\t")
V1 V2 V3 V4 V5
1 A 2 2 textA1 textA2 Z1
2 B 4 1 textX1 textX2 textX3 Z2
3 C 3 5 textA1 Z3
Run Code Online (Sandbox Code Playgroud)
更改列数以告知您之前的数量.对于正则表达式:
((?:\\w+ ){3})捕获{3}非捕获组的3次重复, (?:\w+ )其中至少一个字母数字字符w+后跟一个空格([\\w ]+) (\w+)从字母数字字符或空格中捕获自由文本,[\w ]+后跟空格并捕获最后一个单词\w+完成后,通过制表符str_match替换第一组中的空格,粘贴返回的3个部分m[,2].
m[,1] 是整场比赛所以它在这里没用.
老答案:
基于固定数量的字段的基本匹配:
> read.table(text=gsub("(\\w+) (\\w+) (\\w+) ([\\w ]+) (\\w+)$","\\1\t\\2\t\\3\t\\4\t\\5",dat$x,perl=TRUE),sep="\t")
V1 V2 V3 V4 V5
1 A 2 2 textA1 textA2 Z1
2 B 4 1 textX1 textX2 textX3 Z2
3 C 3 5 textA1 Z3
Run Code Online (Sandbox Code Playgroud)
添加你想要的数量(\ w +),并增加\ 1(反向引用)的数量