Spark DataFrame ArrayType或MapType用于检查列中的值

时间:2018-10-30 15:47:10

标签: python-2.7 apache-spark pyspark apache-spark-sql pyspark-sql

我有一个pyspark数据框,一列是ID列表。例如,我想获取其中具有特定ID的行数。

AFAIK与我相关的两个列类型为ArrayTypeMapType。我可以使用地图类型,因为检查地图/字典中的成员资格比检查数组中的成员资格更有效。

但是,要使用地图,我需要使用自定义udf进行过滤,而不是使用内置(标量)函数array_contains

使用MapType我可以做到:

from pyspark.sql.types import BooleanType
from pyspark.sql.functions import udf

df = spark.createDataFrame([("a-key", {"345": True, "123": True})], ["key", "ids"])

def is_in_map(k, d):
    return k in d.keys()

def map_udf(key):
    return udf(lambda d: is_in_map(key, d), BooleanType())

c = df.filter(map_udf("123")(df.ids)).count()

或使用ArrayType可以做到:

from pyspark.sql.functions import array_contains

df = spark.createDataFrame([("a-key", ["345", "123"])], ["key", "ids"])
c = df.filter(array_contains(df.ids, "123")).count()

我的第一反应是使用MapArray,因为(我认为)检查地图内部的成员身份效率更高。

另一方面,内置函数array_contains执行 scala 代码,并且我假设我调用的任何scala定义函数都比将列dict返回给python效率更高。上下文并检查k in d.keys()

要检查此(多值)列中的成员身份,最好使用MapTypeArrayType pyspark.sql.types

更新

有一个列方法pyspark.sql.Column.getItem,这意味着我可以按成员资格进行过滤,而无需使用Python udf

1 个答案:

答案 0 :(得分:1)

在使用过的Scala + Spark中,地图的性能更高

df.where(df("ids").getItem("123") === true)

它使用标准的Dataframe API和df(“ ids”)。getItem(“ 123”)返回具有地图值或为null的 Column ,它将以Spark的原始速度运行。 Pyspark开发人员说Pyspark也具有该API。