我在尝试从一个基于两列项目列表的 Dataframe 中删除行时遇到了麻烦。例如,对于此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中:
lit((100, "A"))
lit(List(100, "A"))
lit(Seq(100, "A"))
lit(Array(100, "A"))
但没有成功有人知道如何在Spark/PySpark中创建文字数组吗?或者是否有其他方法通过两列过滤 Dataframe ?
3条答案
按热度按时间nhaq1z211#
首先,您可能需要
struct
而不是arrays
。请记住,Spark SQL不支持异构阵列,因此array(1, 'a')
被转换为array<string>
。因此,query可能看起来像这样:
这似乎生成了有效的表达式:
但由于某种原因,分析仪上未通过:
奇怪的是,SQL following也会失败:
但是当两边都用文字替换时:
工作正常所以看起来像个bug。
也就是说,left anti join应该在这里工作得很好:
hiz5n14c2#
要在spark中创建一个数组字面量,你需要从一系列列中创建一个数组,其中一个列是从
lit
函数中创建的:kzipqqlq3#
Spark 3.4+
完整示例: