当术语进行OR运算时,R中的grep找不到行

时间:2015-06-17 21:27:27

标签: regex r grep

我是R.的新手。我正在开发一个包含1M +行和1000多列的非常大的数据集,需要进行严格的数据清理。我已经成功地清理了大部分数据,但是这给我留下了一些杂乱无章的重复代码。

我正在尝试使用grep查找与无效数据匹配的行,并用正确的值替换它们。但是,当我在搜索条件中使用OR多个术语时,它并没有按预期工作。我将用一个例子来解释这一点,这是有道理的。

这是一个小数据框,用于显示正在发生的事情。

数据框有三列,状态,死亡,事件。事件列包含需要清理的混乱数据。

state <- c("AL", "CA", "AZ", "MA", "MN", "NY", "NJ", "GA", "TX", "MN")
fatalities <- c(2,1,4,6,7,9,1,10,1,7)
event <- c("THUNDERSTORM", "THUNERSTORM W","THUNDERSTROM","TSTM","HUNDERSTORM","THUNDERSTORM","THUNDERSTORM","THUNDERSTORM","THUNDERSTORM","THUNDERSTORM")
df <- data.frame(state,fatalities,event, stringsAsFactors = FALSE)
df$Corrected <- ''
df



   state fatalities         event                 Corrected

1     AL          2  THUNDERSTORM          
2     CA          1 THUNERSTORM W          
3     AZ          4  THUNDERSTROM          
4     MA          6          TSTM          
5     MN          7   HUNDERSTORM          
6     NY          9  THUNDERSTORM          
7     NJ          1  THUNDERSTORM          
8     GA         10  THUNDERSTORM          
9     TX          1  THUNDERSTORM          
10    MN          7  THUNDERSTORM     

正如您所看到的,该活动有“TSTM”,“THUNERSTORM”等需要更正为“THUNDERSTORM”的内容。

如果我只是说

grep(&#34; TSTM&#34;,df $ event)

然后它可以正常工作,如下所示。

df$Corrected[grep("TSTM", df$event)] <- "THUNDERSTORM"
df

   state fatalities         event    Corrected

1     AL          2  THUNDERSTORM             
2     CA          1 THUNERSTORM W             
3     AZ          4  THUNDERSTROM             
4     MA          6          TSTM THUNDERSTORM
...

然而,问题是如果我有100个变种,我最终会有100个语句。

如果我使用OR运算符并尝试这样的东西,它就不起作用。我的想法是在一个地方列出所有变体,然后只在一个镜头中替换所有出现的事件(或者至少将有效值放在匹配行的Corrected列中)

现在,如果我尝试OR多个术语,如下所示:

df$Corrected[grep("TSTM | THUNERSTORM", df$event)] <- "THUNDERSTORM"
df

如您所见,没有任何变化,Corrected列保持空白,就好像没有找到任何匹配一样。

   state fatalities         event                Corrected

1     AL          2  THUNDERSTORM          
2     CA          1 THUNERSTORM W          
3     AZ          4  THUNDERSTROM          
4     MA          6          TSTM          
5     MN          7   HUNDERSTORM          
6     NY          9  THUNDERSTORM          
7     NJ          1  THUNDERSTORM          
8     GA         10  THUNDERSTORM          
9     TX          1  THUNDERSTORM          
10    MN          7  THUNDERSTORM    

为什么不像我的OR语句那样grep? 我错过了一些明显的东西吗? 我尝试了this thread的建议,但没有用。

其次,有没有更好的方法,考虑到每个类别我会有数百个这样的清理声明?意思是,我可以将它转换为一个带有两个参数的函数,滤波器匹配和字符串替换并直接更改数据吗?

e.g。

CleanUp <- function(filter, replacement) df$Corrected[grep(filter, df$event)] <- replacement

然后我可以继续称它为:

CleanUp("TSTM", "THUNDERSTORM")
CleanUp("THUNERSTORM", "THUNDERSTORM")
...etc

我尝试了这个,它也没用。我无法弄清楚它为什么不起作用。我考虑过的事情并不能始终如一地工作:不同的正则表达式,egrep,dplyr包含。 最后,抱歉,如果它出现太长时间&#39;发帖问一些简单的事情。

1 个答案:

答案 0 :(得分:4)

回答评论。对于你的第一个问题:空间在正则表达式中很重要。 &#34; TSTM | THUNERSTORM&#34;正在寻找&#34; TSTM&#34;或&#34; THUNERSTORM&#34;尾随/前导空格。尝试&#34; TSTM | THUNERSTORM&#34;

对于功能化的东西,R函数通常不会修改外部对象。你可以重写你的功能

CleanUp <- function(df, filter, replacement) {
    df$Corrected[grep(filter, df$event)] <- replacement
    return(df)
}

然后将其称为

df <- CleanUp(df, "TSTM", "THUNDERSTORM")

一种更好的方法可能是编译正则表达式模式的向量并以编程方式构造grep调用:

patterns = c("ERSTORM", "TSTM", "THUNER")
df$Corrected = ifelse(grep(paste(patterns, collapse = "|"), df$event),
                      "THUNDERSTORM", df$Corrected)