使用 separate 函数(tidyr)通过 dplyr 在首个数字处分隔列

15

我试图将一列相当混乱的数据分成包含时间段描述两列。我的数据类似于以下示例:

set.seed(1)
dta <- data.frame(indicator=c("someindicator2001", "someindicator2011",
                              "some text 20022008", "another indicator 2003"),
                  values = runif(n = 4))

期望结果

期望的结果应该是这样的:

          indicator   period    values
1     someindicator     2001 0.2655087
2     someindicator     2011 0.3721239
3         some text 20022008 0.5728534
4 another indicator     2003 0.9082078

特点

  1. 指标描述在一列中
  2. 数值(从第一个数字开始计算,包括第一个数字)在第二列中

代码

require(dplyr); require(tidyr); require(magrittr)
dta %<>%
  separate(col = indicator, into = c("indicator", "period"),
           sep = "^[^\\d]*(2+)", remove = TRUE)

当然这是不起作用的:

> head(dta, 2)
  indicator period    values
1              001 0.2655087
2              011 0.3721239

其他尝试

  • 我还尝试了默认的分隔方法sep = "[^[:alnum:]]",但它会将列分成太多的列,因为它似乎匹配了所有可用的数字。
  • sep = "2*"也无法正常工作,因为有时候出现了太多的2 (例如:20032006)

我的目标是:

  • 识别字符串中的第一个数字
  • 在该字符上进行分割。实际上,如果能保留该特定字符,我会很高兴。
2个回答

16

我想这样可能可以。

library(tidyr)
separate(dta, indicator, c("indicator", "period"), "(?<=[a-z]) ?(?=[0-9])")
#           indicator   period    values
# 1     someindicator     2001 0.2655087
# 2     someindicator     2011 0.3721239
# 3         some text 20022008 0.5728534
# 4 another indicator     2003 0.9082078
以下是一个正则表达式的解释,由regex101提供:
- (?<=[a-z]) 是一个正向后瞻断言 - 它断言可以匹配到一个单个的在 a 到 z 范围内(区分大小写)的字符。 - ? 匹配紧随其前的空格字符一次或者零次,尽可能地多次匹配,必要时进行回溯。 - (?=[0-9]) 是一个正向前瞻断言 - 它断言可以匹配到一个单个的在 0 到 9 范围内的字符。

1
谢谢,这太棒了,它似乎正确匹配了结果,非常感谢您的解释。我想到解决这个问题可能涉及到向后/向前查找,但我觉得它们不容易使用。 - Konrad

1
您也可以使用 unglue::unnest()

dta <- data.frame(indicator=c("someindicator2001", "someindicator2011",
                              "some text 20022008", "another indicator 2003"),
                  values = runif(n = 4))

# remotes::install_github("moodymudskipper/unglue")
library(unglue)
unglue_unnest(dta, indicator, "{indicator}{=\\s*}{period=\\d*}")
#>       values         indicator   period
#> 1 0.43234262     someindicator     2001
#> 2 0.65890900     someindicator     2011
#> 3 0.93576805         some text 20022008
#> 4 0.01934736 another indicator     2003

该内容由reprex package (v0.3.0)于2019年9月14日创建


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接