在第一个和最后一个逗号上拆分字符串

时间:2014-05-30 18:18:53

标签: regex string r split

我想在第一个和最后一个逗号上拆分字符串。每个字符串至少有两个 逗号。下面是一个示例数据集和所需的结果。

此处的类似问题询问如何拆分第一个逗号:Split on first comma in string

我在这里询问了如何在前两个冒号上分割字符串:Split string on first two colons

感谢您的任何建议。我更喜欢基地R的解决方案。抱歉,如果这是重复的话。

my.data <- read.table(text='

my.string        some.data
123,34,56,78,90     10
87,65,43,21         20
a4,b6,c8888         30
11,bbbb,ccccc       40
uu,vv,ww,xx         50
j,k,l,m,n,o,p       60', header = TRUE, stringsAsFactors=FALSE)

desired.result <- read.table(text='

 my.string1 my.string2 my.string3 some.data
        123   34,56,78         90        10
         87      65,43         21        20
         a4         b6      c8888        30
         11       bbbb      ccccc        40
         uu      vv,ww         xx        50
          j  k,l,m,n,o          p        60', header = TRUE, stringsAsFactors=FALSE)

5 个答案:

答案 0 :(得分:4)

您可以使用\K运算符来保持文本已经匹配到结果之外,并使用负向预测断言来执行此操作(很好几乎,开头有一个恼人的逗号在strsplit中我尚未摆脱的中间部分。但我喜欢这个作为构建正则表达式的练习......

x <- '123,34,56,78,90'
strsplit( x , "^[^,]+\\K|,(?=[^,]+$)" , perl = TRUE )
#[[1]]
#[1] "123"       ",34,56,78" "90"

Explantion:

  • ^[^,]+:从字符串开头匹配一个或多个 a ,
  • 的字符
  • \\K:但不要在匹配中包含匹配的字符
  • 所以第一场比赛是第一个逗号......
  • |:或者你可以匹配......
  • ,(?=[^,]+$),只要后跟[(?=...)]一个或多个 ,的字符,直到$为止字符串的结尾({{1}})...

答案 1 :(得分:3)

这是一种相对简单的方法。在第一行中,我们使用sub将第一个和最后一个逗号替换为生成s的分号。然后,我们使用s阅读sep=";",最后cbind阅读my.data的其余内容:

s <- sub(",(.*),", ";\\1;", my.data[[1]])
DF <- read.table(text=s, sep =";", col.names=paste0("mystring",1:3), as.is=TRUE)
cbind(DF, my.data[-1])

,并提供:

  mystring1 mystring2 mystring3 some.data
1       123  34,56,78        90        10
2        87     65,43        21        20
3        a4        b6     c8888        30
4        11      bbbb     ccccc        40
5        uu     vv,ww        xx        50
6         j k,l,m,n,o         p        60

答案 2 :(得分:1)

以下是分割第一个和最后一个逗号的代码。这段代码很大程度上来自@bdemarest的回答:Split string on first two colons下面的gsub模式是答案的重点,它包含重要的差异。分割字符串后创建新数据帧的代码与@bdemarest

的代码相同
# Replace first and last commas with colons.

new.string <- gsub(pattern="(^[^,]+),(.+),([^,]+$)", 
              replacement="\\1:\\2:\\3", x=my.data$my.string)
new.string

# Split on colons
split.data <- strsplit(new.string, ":")

# Create data frame
new.data <- data.frame(do.call(rbind, split.data))
names(new.data) <- paste("my.string", seq(ncol(new.data)), sep="")

my.data$my.string <- NULL
my.data <- cbind(new.data, my.data)
my.data

#   my.string1 my.string2 my.string3 some.data
# 1        123   34,56,78         90        10
# 2         87      65,43         21        20
# 3         a4         b6      c8888        30
# 4         11       bbbb      ccccc        40
# 5         uu      vv,ww         xx        50
# 6          j  k,l,m,n,o          p        60



# Here is code for splitting strings on the first comma

my.data <- read.table(text='

my.string        some.data
123,34,56,78,90     10
87,65,43,21         20
a4,b6,c8888         30
11,bbbb,ccccc       40
uu,vv,ww,xx         50
j,k,l,m,n,o,p       60', header = TRUE, stringsAsFactors=FALSE)


# Replace first comma with colon

new.string <- gsub(pattern="(^[^,]+),(.+$)", 
                   replacement="\\1:\\2", x=my.data$my.string)
new.string

# Split on colon
split.data <- strsplit(new.string, ":")

# Create data frame
new.data <- data.frame(do.call(rbind, split.data))
names(new.data) <- paste("my.string", seq(ncol(new.data)), sep="")

my.data$my.string <- NULL
my.data <- cbind(new.data, my.data)
my.data

#   my.string1  my.string2 some.data
# 1        123 34,56,78,90        10
# 2         87    65,43,21        20
# 3         a4    b6,c8888        30
# 4         11  bbbb,ccccc        40
# 5         uu    vv,ww,xx        50
# 6          j k,l,m,n,o,p        60




# Here is code for splitting strings on the last comma

my.data <- read.table(text='

my.string        some.data
123,34,56,78,90     10
87,65,43,21         20
a4,b6,c8888         30
11,bbbb,ccccc       40
uu,vv,ww,xx         50
j,k,l,m,n,o,p       60', header = TRUE, stringsAsFactors=FALSE)


# Replace last comma with colon

new.string <- gsub(pattern="^(.+),([^,]+$)", 
                   replacement="\\1:\\2", x=my.data$my.string)
new.string

# Split on colon
split.data <- strsplit(new.string, ":")

# Create new data frame
new.data <- data.frame(do.call(rbind, split.data))
names(new.data) <- paste("my.string", seq(ncol(new.data)), sep="")

my.data$my.string <- NULL
my.data <- cbind(new.data, my.data)
my.data

#     my.string1 my.string2 some.data
# 1 123,34,56,78         90        10
# 2     87,65,43         21        20
# 3        a4,b6      c8888        30
# 4      11,bbbb      ccccc        40
# 5     uu,vv,ww         xx        50
# 6  j,k,l,m,n,o          p        60

答案 3 :(得分:1)

您可以在该列

上执行简单的strsplit
popshift<-sapply(strsplit(my.data$my.string,","), function(x) 
    c(x[1], paste(x[2:(length(x)-1)],collapse=","), x[length(x)]))

desired.result <- cbind(data.frame(my.string=t(popshift)), my.data[-1])

我只是将所有值分开并使用第一个,最后一个和中间的字符串创建一个新的向量。然后我用剩下的数据来解决这个问题。结果是

  my.string.1 my.string.2 my.string.3 some.data
1         123    34,56,78          90        10
2          87       65,43          21        20
3          a4          b6       c8888        30
4          11        bbbb       ccccc        40
5          uu       vv,ww          xx        50
6           j   k,l,m,n,o           p        60

答案 4 :(得分:1)

使用套餐str_match()中的stringr,以及您的某个链接提供的一些帮助,

> library(stringr)
> data.frame(str_match(my.data$my.string, "(.+?),(.*),(.+?)$")[,-1], 
             some.data = my.data$some.data)
#    X1        X2    X3 some.data
# 1 123  34,56,78    90        10
# 2  87     65,43    21        20
# 3  a4        b6 c8888        30
# 4  11      bbbb ccccc        40
# 5  uu     vv,ww    xx        50
# 6   j k,l,m,n,o     p        60