在R中使用负回顾的正则表达式

15

所以我有以下数据,假设称为“my_data”:

Storm.Type
TYPHOON
SEVERE STORM
TROPICAL STORM
SNOWSTORM AND HIGH WINDS

我想做的是对my_data$Storm.Type中的每个元素进行分类,判断它是否为风暴,但是我不想将热带风暴包括在内(我打算单独分类),这样我就会得到

Storm.Type                    Is.Storm
TYPHOON                       0
SEVERE STORM                  1
TROPICAL STORM                0
SNOWSTORM AND HIGH WINDS      1

我已经编写了下面的代码:

my_data$Is.Storm  <-  my_data[grep("(?<!TROPICAL) (?i)STORM"), "Storm.Type"]

但这只将“SEVERE STORM”作为暴风雨返回(但省略了SNOWSTORM和HIGH WINDS)。谢谢!


你的正则表达式中 (?i) 的作用是什么?问题在于你要寻找带有前导空格的字符串 " STORM",所以 "SNOWSTORM" 不符合要求。 - Blue Magister
1
嗨,Blue。虽然我接受了Ben的答案,但你实际上已经找到了我的代码问题的核心。我想让我的代码不关心那个空格(所以如果STORM在THUNDERSTORM或SNOWSTORM中,我希望它以及STORM本身都能被匹配)。你知道怎么去掉我代码中寻找的那个空格吗?(?i)的目的是为了防止有人将STORM输入为"storm"、"Storm"或"sToRm"等。 - Jonathan Charlton
3个回答

11

问题在于您正在查找具有前导空格的字符串" STORM",因此"SNOWSTORM" 不符合条件。

作为修复方法,请考虑将空格移到负回溯断言中,像这样:

ss <- c("TYPHOON","SEVERE STORM","TROPICAL STORM","SNOWSTORM AND HIGH WINDS",
        "THUNDERSTORM")
grep("(?<!TROPICAL )(?i)STORM", ss, perl = TRUE)
# [1] 2 4 5
grepl("(?<!TROPICAL )(?i)STORM", ss, perl = TRUE)
# [1] FALSE  TRUE FALSE  TRUE  TRUE

我不知道在正则表达式中(?i)(?-i)表示是否忽略大小写。这是个很酷的发现。另一种方式是使用ignore.case标志:

grepl("(?<!tropical )storm", ss, perl = TRUE, ignore.case = TRUE)
# [1] FALSE  TRUE FALSE  TRUE  TRUE

然后定义您的列:

my_data$Is.Storm  <-  grepl("(?<!tropical )storm", my_data$Storm.Type,
                            perl = TRUE, ignore.case = TRUE)

1
不客气。谢谢你教我关于(?i)的用法。我习惯于使用ignore.case参数,但是对于一般的PCRE表达式来说,(?i)更加灵活。 - Blue Magister

3

我也不是很擅长正则表达式,但是这个有什么问题呢?

ss <- c("TYPHOON","SEVERE STORM","TROPICAL STORM","SNOWSTORM AND HIGH WINDS")
grepl("STORM",ss) & !grepl("TROPICAL STORM",ss)
## [1] FALSE  TRUE FALSE  TRUE

... ?


0

类似于某些东西

x <- my_data$Storm.Type
grep("STORM", x)[!grep("STORM", x)%in%grep("TROPICAL", x)]

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