我有一个填充了包含多个点的字符串的列。我想将此列拆分为两个包含第一个点之前和之后的两个子串。
即
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
答案 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
函数在comb
和A
之间或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