Python 使用SQL like IN子句筛选Pyspark数据帧

Python 使用SQL like IN子句筛选Pyspark数据帧,python,sql,apache-spark,dataframe,pyspark,Python,Sql,Apache Spark,Dataframe,Pyspark,我想在子句中使用类似SQL的来过滤Pyspark数据帧,如 sc = SparkContext() sqlc = SQLContext(sc) df = sqlc.sql('SELECT * from my_df WHERE field1 IN a') 其中a是元组(1,2,3)。我得到这个错误: java.lang.RuntimeException:[1.67]失败:`(''应为“”,但找到标识符a 这基本上是说它期待的是类似于“(1,2,3)”的东西,而不是a。 问题是我无法在从另一个作业

我想在子句中使用类似SQL的
来过滤Pyspark数据帧,如

sc = SparkContext()
sqlc = SQLContext(sc)
df = sqlc.sql('SELECT * from my_df WHERE field1 IN a')
其中
a
是元组
(1,2,3)
。我得到这个错误:

java.lang.RuntimeException:[1.67]失败:`(''应为“”,但找到标识符a

这基本上是说它期待的是类似于“(1,2,3)”的东西,而不是a。 问题是我无法在从另一个作业中提取的值中手动写入


在这种情况下如何过滤?

传递给
SQLContext
的字符串在SQL环境的范围内进行计算。它不会捕获闭包。如果要传递变量,必须使用字符串格式显式执行此操作:

df = sc.parallelize([(1, "foo"), (2, "x"), (3, "bar")]).toDF(("k", "v"))
df.registerTempTable("df")
sqlContext.sql("SELECT * FROM df WHERE v IN {0}".format(("foo", "bar"))).count()
##  2 
显然,出于安全考虑,这不是您在“真实”SQL环境中使用的东西,但在这里它不重要

实际上,当您想要创建动态查询时,DSL是一个更好的选择:

from pyspark.sql.functions import col

df.where(col("v").isin({"foo", "bar"})).count()
## 2

为您构建、编写和处理HiveQL/Spark SQL的所有细节都很容易。

重申@zero323上面提到的内容:我们也可以使用列表来做同样的事情(不仅仅是
设置
如下所示

from pyspark.sql.functions import col

df.where(col("v").isin(["foo", "bar"])).count()

只需一点添加/更新:

choice_list = ["foo", "bar", "jack", "joan"]
如果您想过滤数据帧“df”,以便根据列“v”保留行,只取选项列表中的值,那么

from pyspark.sql.functions import col

df_filtered = df.where( ( col("v").isin (choice_list) ) )

对我来说,一种稍微不同的方法是使用自定义筛选函数进行筛选

def filter_func(a):
"""wrapper function to pass a in udf"""
    def filter_func_(col):
    """filtering function"""
        if col in a.value:
            return True

    return False

return udf(filter_func_, BooleanType())

# Broadcasting allows to pass large variables efficiently
a = sc.broadcast((1, 2, 3))
df = my_df.filter(filter_func(a)(col('field1'))) \

也可以对整型列执行此操作:

df_filtered = df.filter("field1 in (1,2,3)")
或对字符串列执行以下操作:

df_filtered = df.filter("field1 in ('a','b','c')")

对于第二种方法,可以通过执行df.where(df.v.isin({“foo”,“bar”})).count()来实现相同的功能您可以,但我个人不喜欢这种方法。使用
col
我可以轻松地将SQL表达式和特定的
DataFrame
对象解耦。例如,您可以保留有用表达式的字典,并在需要时选择它们。使用显式DF对象,您必须将其放在函数中,而它不会构成well、 如何使用元组列表来实现这一点?例如,如果我有
[(1,1)、(1,2)、(1,3)]
,其中一个是
aid
,另一个是
bid
。它必须类似于
col(['aid','bid])。isin([(1,1)、(1,2)]
@zero323是否在like中存在对is的否定,而不是在sparksql中。是的。您可以使用“~”