Apache spark 无法在spark/pyspark中创建数组文字

Apache spark 无法在spark/pyspark中创建数组文字,apache-spark,pyspark,Apache Spark,Pyspark,基于要筛选的项目的两列列表,尝试从dataframe中删除行时遇到麻烦。例如,对于此数据帧: df = spark.createDataFrame([(100, 'A', 304), (200, 'B', 305), (300, 'C', 306)], ['number', 'letter', 'id']) df.show() +------+------+---+ |number|letter| id| +------+------+---+ | 100| A|304| | 2

基于要筛选的项目的两列列表,尝试从dataframe中删除行时遇到麻烦。例如,对于此数据帧:

df = spark.createDataFrame([(100, 'A', 304), (200, 'B', 305), (300, 'C', 306)], ['number', 'letter', 'id'])
df.show()
+------+------+---+
|number|letter| id|
+------+------+---+
|   100|     A|304|
|   200|     B|305|
|   300|     C|306|
+------+------+---+
我可以在一列上使用isin轻松删除行:

df.where(~col('number').isin([100, 200])).show()
+------+------+---+
|number|letter| id|
+------+------+---+
|   300|     C|306|
+------+------+---+
但当我尝试通过两列删除它们时,我得到了一个例外:

df.where(~array('number', 'letter').isin([(100, 'A'), (200, 'B')])).show()

Py4JJavaError: An error occurred while calling z:org.apache.spark.sql.functions.lit.
: java.lang.RuntimeException: Unsupported literal type class java.util.ArrayList [100, A]
    at org.apache.spark.sql.catalyst.expressions.Literal$.apply(literals.scala:57)
    at org.apache.spark.sql.functions$.lit(functions.scala:101)
    at org.apache.spark.sql.functions.lit(functions.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:237)
    at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
    at py4j.Gateway.invoke(Gateway.java:280)
    at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
    at py4j.commands.CallCommand.execute(CallCommand.java:79)
    at py4j.GatewayConnection.run(GatewayConnection.java:214)
    at java.lang.Thread.run(Thread.java:745)
经过一些调查,我意识到问题的根本原因是从非原语类型创建文本。我在pyspark中尝试了以下代码:

lit((100, 'A'))
lit([100, 'A'])
以及scala spark中的以下内容:

lit((100, "A"))
lit(List(100, "A"))
lit(Seq(100, "A"))
lit(Array(100, "A"))

但是没有运气。。。有人知道在spark/pyspark中创建数组文字的方法吗?或者是否有其他方法按两列过滤数据帧?

要在spark中创建数组文字,您需要从一系列列创建数组,其中一列是通过lit函数创建的:

scala> array(lit(100), lit("A"))
res1: org.apache.spark.sql.Column = array(100, A)

首先,您可能需要结构而不是数组。请记住,Spark SQL不支持异构数组,因此将数组1中的“a”强制转换为数组

所以查询可以如下所示:

选项=[100,'A',200,'B'] 目标=[ 结构 litnumber.aliasnumber.castlong, litletter.aliasletter.caststring 对于数字,选择中的字母] query=structnumber,letter.isintarget 这似乎生成了有效的表达式:

查询 柱 但由于某些原因,analyzer出现故障:

df.where~查询 AnalysisException回溯最近的调用last ... AnalysisException:由于数据类型不匹配,无法将命名结构“col1”中的“命名结构“number”、“number”、“letter”、“letter”解析为BIGINT、“col2”,将“A”转换为STRING,将“col1”转换为STRING,将“CAST200”转换为BIGINT,“col2”,将“B”转换为STRING:参数的类型必须相同\n'Filter未命名为\u structnumber,number0L,letter,letter1在命名为\u structcol1中,cast100作为bigint,col2,castA作为string,命名为\u structcol1,cast200作为bigint,col2,castB作为string\n+-LogicalRDD[number0L,letter1,id2L]\n 奇怪的是,使用SQL时,以下操作也会失败:

df.createOrReplaceTempViewdf spark.sqlSELECT*来自df,其中structletter,structCAST1中的字母为bigint,“a” AnalysisException:由于数据类型不匹配,无法将命名结构'col1',CAST1中的'named_struct'letter',df.'letter',df.'letter',df.'letter'解析为BIGINT,'col2',a:参数必须是相同的类型;第1行位置46\n'Project[*]\n+-'过滤器名为_structletter,letter1,letter,letter1在命名的_structcol1中,cast1作为bigint,col2,a\n+-子查询字段df\n+-逻辑RDD[number0L,letter1,id2L]\n 但当两边都替换为文字时:

spark.sqlSELECT*来自df,其中structCAST1作为bigint,'a'在structCAST1作为bigint,'a'中 数据帧[编号:bigint,字母:string,id:bigint] 工作正常,所以看起来像个虫子

也就是说,左反连接在这里应该可以正常工作:

从pyspark.sql.functions导入广播 加入 broadcastspark.createDataFramechoices、数字、字母、, [数字、字母], 左撇子 +---+---+--+ |编号|字母| id| +---+---+--+ |300 | C | 306| +---+---+--+
问题是关于pyspark,而不是scala。这是答案中的一个提示!从pyspark.sql.functions导入*;arraylit100,利塔工厂