【问题标题】:how to preserve regex using stringr (str_split) or strsplit with r如何使用 stringr (str_split) 或 strsplit with r 保留正则表达式
【发布时间】:2020-11-18 17:39:25
【问题描述】:

我有一些肮脏的数据需要整理。这是一个例子:

x <- "FIRST LAST Sep 1, 2020   1234567 Jan 1, 1985 555-555-5555 100 Main St. Somewhere, CA 90009  Atorvastatin Calcium Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 1, 2020 Sep 1, 2020   1234567 Jan 1, 1985 555-555-5555 

FIRSTA LASTA Sep 12, 2020   2234567 Jan 12, 1985 555-555-5552 1002 MAIN AVE, CA 90009 DR. JOHN SMITH Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 12, 2020 Sep 12, 2020   2234567 Jan 12, 1985 555-555-5552 Smith REX

FIRSTB LASTB Sep 13, 2020   3234567 Jan 13, 1985 555-555-5553 1003 Main St. Somewhere, CA 90009  Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 13, 2020 Sep 13, 2020   3234567 Jan 13, 1985 555-555-5553 Somewhere"
    

我正在尝试获取一个表,其中包含单列和数据行,按第一个 - 空格 - 姓氏(全部大写,例如 FIRST LAST、FIRSTB LASTA、FIRSTB、LASTB),同时保留所述名称。我从基础 strsplit 开始,但放弃了。以下是我的 stringr 尝试:

str_split(x, "[A-Z]+ (?=[A-Z]+)")

这很接近,但我忘记了名字。

str_split(x, "(?<=[A-Z]+) (?=[A-Z]+)")

由于缺少有界最大值,这会引发错误。

预期输出:

[1] FIRST LAST Sep 1, 2020   1234567 Jan 1, 1985 555-555-5555 100 Main St. Somewhere, CA 90009  Atorvastatin Calcium Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 1, 2020 Sep 1, 2020   1234567 Jan 1, 1985 555-555-5555 

[2] FIRSTA LASTA Sep 12, 2020   2234567 Jan 12, 1985 555-555-5552 1002 Main St. Somewhere, CA 90009  Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 12, 2020 Sep 12, 2020   2234567 Jan 12, 1985 555-555-5552 

[3] FIRSTB LASTB Sep 13, 2020   3234567 Jan 13, 1985 555-555-5553 1003 Main St. Somewhere, CA 90009  Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 13, 2020 Sep 13, 2020   3234567 Jan 13, 1985 555-555-5553

【问题讨论】:

  • 您的预期输出是什么? strsplit(x, "(?&lt;=\\d) (?=[A-Z]{3,})", perl=TRUE) 能解决问题吗?
  • 是的 Onyambu,适用于我最初发布的示例。我的真实数据更复杂,并且不会始终以数字结尾。我已经调整了样本,使其更能代表真实数据。
  • 或许你应该考虑strsplit(x, "(?&lt;=[^A-Z])\\s+(?=[A-Z]{3,})", perl = TRUE)
  • 我知道你用正则表达式去哪里了。说得通。我的数据中有一些全部大写的案例,所以我确实再次更新了样本,以防万一有人有想法。否则代码运行良好。
  • 问题是你怎么知道名字和姓氏?您需要尽可能具体,以免最终在错误的位置分裂

标签: r stringr


【解决方案1】:

我猜你想要的是获取每条记录,如果是这样,你需要在名字姓氏之前的换行符上进行拆分:

str_split(x, "\\n(?=[A-Za-z]+ [A-Za-z]+)")
[[1]]
[1] "FIRST LAST Sep 1, 2020   1234567 Jan 1, 1985 555-555-5555 100 Main St. Somewhere, CA 90009  Atorvastatin Calcium Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 1, 2020 Sep 1, 2020   1234567 Jan 1, 1985 555-555-5555 \n"
[2] "FIRSTA LASTA Sep 12, 2020   2234567 Jan 12, 1985 555-555-5552 1002 MAIN AVE, CA 90009 DR. JOHN SMITH Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 12, 2020 Sep 12, 2020   2234567 Jan 12, 1985 555-555-5552 Smith REX\n"
[3] "FIRSTB LASTB Sep 13, 2020   3234567 Jan 13, 1985 555-555-5553 1003 Main St. Somewhere, CA 90009  Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 13, 2020 Sep 13, 2020   3234567 Jan 13, 1985 555-555-5553 Somewhere"  

{stringr} 使用的底层正则表达式库不支持动态长度后视

在与 @Onyambu 讨论之后,如果您的数据集没有换行符,即换行符,您可以使用以下内容:

str_split(x, " +(?=[A-Za-z]+ [A-Za-z]+ [A-Z][a-z]+ \\d{2}, \\d{4} +\\d{7})")
[[1]]
[1] "FIRST LAST Sep 1, 2020   1234567 Jan 1, 1985 555-555-5555 100 Main St. Somewhere, CA 90009  Atorvastatin Calcium Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 1, 2020 Sep 1, 2020   1234567 Jan 1, 1985 555-555-5555" 
[2] "FIRSTA LASTA Sep 12, 2020   2234567 Jan 12, 1985 555-555-5552 1002 MAIN AVE, CA 90009 DR. JOHN SMITH Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 12, 2020 Sep 12, 2020   2234567 Jan 12, 1985 555-555-5552 Smith REX"
[3] "FIRSTB LASTB Sep 13, 2020   3234567 Jan 13, 1985 555-555-5553 1003 Main St. Somewhere, CA 90009  Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 13, 2020 Sep 13, 2020   3234567 Jan 13, 1985 555-555-5553 Somewhere"   

如果名称是 @Onyambu 建议的大写,则可以简化正则表达式:

tr_split(x, " +(?=[A-Z]+ [A-Z]+ [A-Z][a-z]+ \\d)")
[[1]]
[1] "FIRST LAST Sep 1, 2020   1234567 Jan 1, 1985 555-555-5555 100 Main St. Somewhere, CA 90009  Atorvastatin Calcium Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 1, 2020 Sep 1, 2020   1234567 Jan 1, 1985 555-555-5555" 
[2] "FIRSTA LASTA Sep 12, 2020   2234567 Jan 12, 1985 555-555-5552 1002 MAIN AVE, CA 90009 DR. JOHN SMITH Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 12, 2020 Sep 12, 2020   2234567 Jan 12, 1985 555-555-5552 Smith REX"
[3] "FIRSTB LASTB Sep 13, 2020   3234567 Jan 13, 1985 555-555-5553 1003 Main St. Somewhere, CA 90009  Cetirizine HCl Diflucan Flonase Allergy Relief Hydrochlorothiazide HydrOXYzine Pamoate Oct 13, 2020 Sep 13, 2020   3234567 Jan 13, 1985 555-555-5553 Somewhere"  

【讨论】:

  • 每次我们发布问题时,他都会编辑这个问题。您会注意到他希望我们直观地看到 x。起初,x 只是一个没有换行符的长字符串。所以从技术上讲,我不认为这是 OP 的想法,但我可能错了
  • @Onyambu 是的,我知道降价不正确,我对其进行了编辑。和你一样,当我看到标题时,我首先想到的是使用环视,现在看起来有点过头了。
  • 您会注意到,在 cmets 中,我会发布一个有效的正则表达式,然后 OP 会编辑问题。可能后来添加了换行符。但我认为 OP 在他们的数据集中没有 LF
  • @Onyambu 我发现了一个模式,主要是名字后跟姓氏,然后是一个日期,然后是一个 7 位数字
  • 这是解决这个问题的好方法
猜你喜欢
  • 2019-11-22
  • 1970-01-01
  • 2018-12-25
  • 2018-09-01
  • 1970-01-01
  • 2017-02-27
  • 1970-01-01
  • 1970-01-01
  • 2011-09-27
相关资源
最近更新 更多