rlike
工作正常,但not rlike
抛出错误:
scala> sqlContext.sql("select * from T where columnB rlike '^[0-9]*$'").collect()
res42: Array[org.apache.spark.sql.Row] = Array([412,0], [0,25], [412,25], [0,25])
scala> sqlContext.sql("select * from T where columnB not rlike '^[0-9]*$'").collect()
java.lang.RuntimeException: [1.35] failure: ``in'' expected but `rlike' found
val df = sc.parallelize(Seq(
(412, 0),
(0, 25),
(412, 25),
(0, 25)
)).toDF("columnA", "columnB")
或者是问题的延续https://issues.apache.org/jira/browse/SPARK-4207?
在PySpark中实现这一点的一种简洁方法是:
df.filter(~df.column.rlike(pattern))
没有什么不是rlike,但在regex中,有一种叫做负前瞻的东西,这意味着它会给出不匹配的单词。
对于上述查询,您可以使用如下regex。比方说,你希望列B不应该以数字"0"开头
然后你可以这样做。
sqlContext.sql("select * from T where columnB rlike '^(?!.*[1-9]).*$'").collect()
Result: Array[org.apache.spark.sql.Row] = Array([412,0])
总的来说,我的意思是,你必须用正则表达式本身来否定匹配,而不是用rlike。Rlike只是匹配您要求匹配的正则表达式。如果您的regex告诉它不匹配,它会应用它,如果您的正则表达式是用于匹配的,那么它会这样做。
以上答案建议使用负面前瞻。在某些情况下可以实现。然而,regexp的设计并不是为了进行有效的负匹配。这些正则表达式很容易出错,而且很难阅读。
Spark从2.0版本开始就支持"not rlike"。
# given 'url' is column on a dataframe
df.filter("""url not rlike "stackoverflow.com"""")
我唯一知道的用法是sql字符串表达式(如上所述)。我在python api中找不到"not"sql dsl函数。scala中可能有一个。
我知道你的问题有点老了,但以防万一:你只是试过scala的一元"!"运算符吗?
在java中,你会使用类似的方法:
DataFrame df = sqlContext.table("T");
DataFrame notLikeDf = df.filter(
df.col("columnB").rlike("^[0-9]*$").unary_$bang()
);
在pyspark中,我是这样做的:
df = load_your_df()
matching_regex = "yourRegexString"
matching_df = df.filter(df.fieldName.rlike(matching_regex))
non_matching_df = df.subtract(matching_df)