R - 正则表达式根据第一个点分隔字符串?

时间:2016-12-21 20:57:48

标签: r regex dplyr tidyr

我有一个填充了包含多个点的字符串的列。我想将此列拆分为两个包含第一个点之前和之后的两个子串。

after_scenario

comb          num
UWEA.n.49.sp   3
KYFZ.n.89.kr   5
     ...

我正在使用 a b num UWEA n.49.sp 3 KYFZ n.89.kr 5 ... 中的separate函数,但无法正确使用正则表达式。我正在尝试使用this answer中的正则表达式样式:

tidyr

因此,列foo %>% separate(comb, into=c('a', 'b'), sep="([^.]+)\\.(.*)") 应由包含至少一个非点字符的第一个捕获组a确定,然后是第一个点,然后第二个捕获组([^.]+)才匹配剩下的事情。

然而,这似乎与任何事情都不匹配:

(.*)

这是我的虚拟数据集:

a   b   num
         3
         5

3 个答案:

答案 0 :(得分:6)

在这种情况下,您可以利用extra = "merge"中的separate选项。由于separate默认情况下会对符号进行分隔,因此您无需定义分隔符。如果您愿意,可以使用"\\."

foo %>%
    separate(comb, into=c('a', 'b'), extra = "merge")

      a       b num
1  NPTE p.10.ku   4
2  YAIU p.54.lw   4
3  CHUR n.51.kx   6
4  EPGX n.14.lg   3
5  POBJ n.11.ja   5
6  LEWI n.72.un   7
7  WLAP n.20.ve  10
8  XZUY p.75.cf   6
9  ZSNJ  p.4.aj   3
10 ABKR n.69.ua   3

extra = "merge"获取您定义的列之外的所有额外部分,并将它们合并到最后一列。

答案 1 :(得分:4)

我认为@ aosmith的答案很棒,而且肯定不如涉及外观的regex解决方案那么笨重。但是,既然您打算使用regex,那么它就是:

foo %>% 
    separate(comb, 
             into = c("a","b"), 
             sep = "(?<=[A-Z])\\.(?=[a-z]+)")

这里的诀窍是正则表达式本身。它使用所谓的lookaround。基本上,您正在寻找一个点(.),它位于UWEA.n参数的大写字母和小写字母(即sep)之间。这意味着:match a dot preceded by a capital letter and followed by a lowercase letter

这允许separate函数在combA之间或n和{{1}之间的点上拆分Z列在你的情况下。

我希望这会有所帮助。

答案 2 :(得分:1)

这是base R选项。将第一个.替换为“梳子”列中的,,并使用read.csv阅读,根据分隔符,cbind创建两列'foo'的列

cbind(read.csv(text=sub("\\.", ",", foo$comb), 
          col.names = c('a', 'b'), header=FALSE), foo[-1])
#      a       b num
#1  GJMU n.83.cu   3
#2  IVMD p.85.ny   9
#3  HLQB p.94.rd   8
#4  WIJY n.92.sz   4
#5  QXCM n.38.lf   8
#6  UBNC n.82.js   5
#7  EPLZ n.56.kl   3
#8  YRBA  n.6.ny   8
#9  HQMR p.54.pn  10
#10 LBPO p.98.tv   7

或另一个选项是来自extract的{​​{1}},其中我们匹配一个或多个不是tidyr的字符,将其放入捕获组(.),后跟一个点(([^.]+)),后跟第二个捕获组中的其他字符(\\.)。捕获的组字符将返回两列,替换原始的“梳子”列。

(.*)

注意:OP的帖子中没有library(tidyr) extract(foo, comb, into = c("a", "b"), "([^.]+)\\.(.*)") # a b num #1 GJMU n.83.cu 3 #2 IVMD p.85.ny 9 #3 HLQB p.94.rd 8 #4 WIJY n.92.sz 4 #5 QXCM n.38.lf 8 #6 UBNC n.82.js 5 #7 EPLZ n.56.kl 3 #8 YRBA n.6.ny 8 #9 HQMR p.54.pn 10 #10 LBPO p.98.tv 7