【问题标题】:Separating a column in R using Regex & separate (tidyr)使用正则表达式和分离(tidyr)在 R 中分离一列
【发布时间】:2018-06-17 18:03:46
【问题描述】:

这就是我希望能够做到的。
https://regex101.com/r/KchccA/1

我想匹配 = 和 ) 之间的任何字符,同时还要考虑是否有一个空捕获组,因为我希望每行填充所有字段。

行示例:在此示例中,地址 4、县和联系人姓名为空。您还可以看到一些错误/不正确的值。 我还需要删除一些初始/结束文本。

x <- "Please enter an UT location before booking the order.. ADDRESS_VALIDATION_FAILED (SITE_TYPE=uct) (SITE_USE_ID=1000) (CUSTOMER_NAME=cname) (CUSTOMER_NUMBER=2000) (ADDRESS1=addy1) (ADDRESS2=addy2) (ADDRESS3=addy3) (ADDRESS4=) (CITY=.) (STATE=) (ZIP=0000) (COUNTY=) (COUNTRY=NO) (CONTACT_NAME=) The task is raised for line_number: 7"

但是在 R 中,当我尝试使用 tidyr 的单独方法时,我最终会得到不希望的结果。我不是在逃避它吗?

这是我的代码:

df.sub <- separate(data = main.data, col = Order.Task.Text.CCW, into = c("SITE_TYPE", "SITE_USE_ID", "CUSTOMER_NAME","CUSTOMER_NUMBER", "ADDRESS1", "ADDRESS2", "ADDRESS3", "ADDRESS4", "CITY", "STATE", "ZIP", "COUNTY", "COUNTRY", "CONTACT_NAME"), sep = "=([^\\)]+|())\\)")

结果示例:

   SITE_TYPE    SITE_USE_ID   CUSTOMER_NAME      CUSTOMER_NUMBER       
1  (SITE_TYPE    (SITE_USE_ID    (CUSTOMER_NAME  (CUSTOMER_NUMBER
2  (SITE_TYPE    (SITE_USE_ID    (CUSTOMER_NAME  (CUSTOMER_NUMBER
3  (SITE_TYPE    (SITE_USE_ID    (CUSTOMER_NAME  (CUSTOMER_NUMBER
4  (SITE_TYPE    (SITE_USE_ID    (CUSTOMER_NAME  (CUSTOMER_NUMBER

最终解决方案

这是我为任何好奇的人提供的最终解决方案,基于为便于查看而格式化的正确答案。

p <- proto(
 pre = function(.) .$k <- 0,
 fun = function(., x) {
 if (x == "(") .$k <- .$k + 1 else if (x == ")") .$k <- .$k - 1
 if (x == "(" && .$k == 1) "" else if (x == ")" && .$k == 0) "\n" else x
})
df.sub.final <- df.sub$text %>%
sub("^[^\\(]*\\(", "(", .) %>% 
sub("\\)[^\\)]*$", ")", .) %>% 
gsub("\n", "", .) %>%
gsub("=", ": ", .) %>%
gsubfn("([\\(\\)]) *", p, .) %>%
textConnection %>%
read.dcf %>%
as.data.frame(.)

【问题讨论】:

  • 尽量使用正面的lookhead和正面的look back。 (?
  • 说错误:'\=' 是从 ""(? 开始的字符串中无法识别的转义
  • (?
  • No 没用,抱怨 ) 你有。我尝试将 \\ 添加到 all 但它没有提供所需的输出,而是看起来像:) (SITE_USE_ID= 用于 SITE_USE_ID 字段。我认为堆栈溢出可能还需要你转义你的 \'s 可能吗?
  • 试试"\\(\\w+=|\\)\\s*",但我相信它可能会产生一些空值。

标签: r regex tidyr


【解决方案1】:

关于有效输入是什么似乎存在一些不确定性。以下是基于不同假设的几个不同答案。都将输入转换为dcf形式(即name:value)然后使用read.dcf

!) 圆括号。

转换为dcf形式(即名称:值)。

我们可以用gsubfn 处理平衡括号。首先创建一个原型对象,其pre 函数将计数器k 初始化为零,然后对于每个匹配到() 的函数fun 输入它并增加或减少k 输出适当的替换字符。有关更多信息,请参阅 gsubfn 包小插图。

现在从 x 开始替换开头的垃圾,将 = 替换为 : 和一个空格,然后运行 ​​gsubfn 匹配(或),后跟可选空格与我们定义的 proto 对象。最后使用read.dcf读取转换后的文本。

library(gsubfn)
library(magrittr)

p <- proto(
 pre = function(.) .$k <- 0,
 fun = function(., x) {
  if (x == "(") .$k <- .$k + 1 else if (x == ")") .$k <- .$k - 1
  if (x == "(" && .$k == 1) "" else if (x == ")" && .$k == 0) "\n" else x
})

x %>%
  sub("^.*?\\(", "(", .) %>%
  gsub("=", ": ", .) %>%
  gsubfn("([\\(\\)]) *", p, .) %>%
  textConnection %>%
  read.dcf

2) 嵌套括号没有相邻的空格

x <- "(SITE_TYPE=Site1) (SITE_USE_ID=2000) (CUSTOMER_NAME=cname) (CUSTOMER_NUMBER=11111) (ADDRESS1=addy1) (ADDRESS2=addy2) (ADDRESS3=addy3) (ADDRESS4=) (CITY=.) (STATE=) (ZIP=0000) (COUNTY=) (COUNTRY=NO) (CONTACT_NAME=)"


library(magrittr)

x %>%
  paste0(" ") %>%
  sub("^.*?\\(", "", .) %>%
  gsub(" +\\(", " ", .) %>%
  gsub("=", ": ", .) %>%
  gsub("\\) ", "\n", .) %>%
  textConnection %>%
  read.dcf

给予:

     SITE_TYPE SITE_USE_ID CUSTOMER_NAME CUSTOMER_NUMBER ADDRESS1 ADDRESS2
[1,] "Site1"   "2000"      "cname"       "11111"         "addy1"  "addy2" 
     ADDRESS3 ADDRESS4 CITY STATE ZIP    COUNTY COUNTRY CONTACT_NAME
[1,] "addy3"  ""       "."  ""    "0000" ""     "NO"    ""     

3) 固定关键字跟在左外括号之后。

对于这个,内括号可以不平衡,但外括号后面总是跟cn中的关键字之一。

x <- "ADDRESS_VALIDATION_FAILED (SITE_TYPE=site1) (SITE_USE_ID=200) (CUSTOMER_NAME=abc) (CUSTOMER_NUMBER=1000) (ADDRESS1=issue here (some more text) (ADDRESS2=) (ADDRESS3=) (ADDRESS4=) (CITY=city, ) (STATE=na) (ZIP=250) (COUNTY=) (COUNTRY=NA) (CONTACT_NAME=)"

cn <- c("SITE_TYPE", "SITE_USE_ID", "CUSTOMER_NAME", "CUSTOMER_NUMBER", 
"ADDRESS1", "ADDRESS2", "ADDRESS3", "ADDRESS4", "CITY", "STATE", 
"ZIP", "COUNTY", "COUNTRY", "CONTACT_NAME")
rx <- sprintf(".(%s)", paste(cn, collapse = "|"))

x %>%
  sub("^.*?\\(", "(", .) %>%
  gsub("=", ": ", .) %>%
  gsub(rx, "\n\\1", .) %>%
  gsub("\\) *\\n", "\n", .) %>%
  sub("\\)$", "", .) %>%
  textConnection %>%
  read.dcf

给予:

     SITE_TYPE SITE_USE_ID CUSTOMER_NAME CUSTOMER_NUMBER
[1,] "site1"   "200"       "abc"         "1000"         
     ADDRESS1                     ADDRESS2 ADDRESS3 ADDRESS4 CITY    STATE
[1,] "issue here (some more text" ""       ""       ""       "city," "na" 
     ZIP   COUNTY COUNTRY CONTACT_NAME
[1,] "250" ""     "NA"    ""          

注意

可重现形式的输入是:

【讨论】:

  • 所以这几乎对我有用,有两件事。一个是我在 x 之前和之后有一些文本,我看到这个 gsub 没有摆脱,我已经更新了我的 OP(参见 x
  • 使用sub 两次。一次移除之前的部件,一次移除之后的部件。它已经适用于多行。例如,将 x 定义为 x &lt;- c(x, x) 并运行相同的代码。
  • 我在上面的代码之前添加了以下内容,以便根据需要仅使用 ( 和 ) 子开始和结束文本。有关完整解决方案,请参阅 OP 底部。
  • 如何阻止它在 ()s 中使用 gsubbing ()s?请参阅此示例中的客户名称。 ex: x
  • 我已经修改了代码,以便它替换空格(或)空格。在您的示例中,内部括号旁边没有空格,因此只会替换外部括号。 sub 也会在第一个 ( .
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-01
  • 1970-01-01
  • 2018-02-19
  • 2020-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多