Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark Pyspark:如何过滤MapType列上的数据帧?(与isin()的样式相同)_Apache Spark_Pyspark_Apache Spark Sql_Pyspark Dataframes - Fatal编程技术网

Apache spark Pyspark:如何过滤MapType列上的数据帧?(与isin()的样式相同)

Apache spark Pyspark:如何过滤MapType列上的数据帧?(与isin()的样式相同),apache-spark,pyspark,apache-spark-sql,pyspark-dataframes,Apache Spark,Pyspark,Apache Spark Sql,Pyspark Dataframes,当我想以isin()的样式过滤MapType列上的数据帧时,最好的策略是什么 因此,基本上我想获得数据帧的所有行,其中MapType列的内容匹配MapType列表中的一个条目——“实例”。也可以是该列上的联接,但迄今为止我尝试的所有方法都失败了,因为EqualTo不支持对map类型进行排序 除了使用isin()或join()的直接方法外,我还想到了使用to_json()将映射转储到json,然后对json字符串进行过滤,但这似乎会随机排列键,因此字符串比较也不可靠 有什么容易的东西我错过了吗?您

当我想以
isin()
的样式过滤MapType列上的数据帧时,最好的策略是什么

因此,基本上我想获得数据帧的所有行,其中MapType列的内容匹配MapType列表中的一个条目——“实例”。也可以是该列上的联接,但迄今为止我尝试的所有方法都失败了,因为
EqualTo不支持对map类型进行排序

除了使用isin()或join()的直接方法外,我还想到了使用
to_json()
将映射转储到json,然后对json字符串进行过滤,但这似乎会随机排列键,因此字符串比较也不可靠

有什么容易的东西我错过了吗?您建议如何解决这个问题

示例df:

+----+---------------------------------------------------------+
|key |metric                                                   |
+----+---------------------------------------------------------+
|123k|Map(metric1 -> 1.3, metric2 -> 6.3, metric3 -> 7.6)      |
|d23d|Map(metric1 -> 1.5, metric2 -> 2.0, metric3 -> 2.2)      |
|as3d|Map(metric1 -> 2.2, metric2 -> 4.3, metric3 -> 9.0)      |
+----+---------------------------------------------------------+
过滤器(伪代码):

期望输出:

----+---------------------------------------------------------+
|key |metric                                                   |
+----+---------------------------------------------------------+
|123k|Map(metric1 -> 1.3, metric2 -> 6.3, metric3 -> 7.6)      |
|d23d|Map(metric1 -> 1.5, metric2 -> 2.0, metric3 -> 2.2)      |
+----+---------------------------------------------------------+

这不是比较映射相等性的最优雅的方法:您可以收集映射键,比较两个映射中每个键的值,并确保所有值都相同。我想最好构造一个过滤器df并进行半连接,而不是使用
isin
传递它们:

样本df和过滤器df:

df.show(truncate=False)
+----+------------------------------------------------+
|key |metric                                          |
+----+------------------------------------------------+
|123k|[metric1 -> 1.3, metric2 -> 6.3, metric3 -> 7.6]|
|d23d|[metric1 -> 1.5, metric2 -> 2.0, metric3 -> 2.2]|
|as3d|[metric1 -> 2.2, metric2 -> 4.3, metric3 -> 9.0]|
+----+------------------------------------------------+

filter_df = df.select('metric').limit(2)
filter_df.show(truncate=False)
+------------------------------------------------+
|metric                                          |
+------------------------------------------------+
|[metric1 -> 1.3, metric2 -> 6.3, metric3 -> 7.6]|
|[metric1 -> 1.5, metric2 -> 2.0, metric3 -> 2.2]|
+------------------------------------------------+
过滤方法:

import pyspark.sql.functions as F

result = df.alias('df').join(
    filter_df.alias('filter_df'),
    F.expr("""
        aggregate(
            transform(
                concat(map_keys(df.metric), map_keys(filter_df.metric)),
                x -> filter_df.metric[x] = df.metric[x]
            ),
            true,
            (acc, x) -> acc and x
        )"""),
     'left_semi'
)

result.show(truncate=False)
+----+------------------------------------------------+
|key |metric                                          |
+----+------------------------------------------------+
|123k|[metric1 -> 1.3, metric2 -> 6.3, metric3 -> 7.6]|
|d23d|[metric1 -> 1.5, metric2 -> 2.0, metric3 -> 2.2]|
+----+------------------------------------------------+

比较spark中的两个贴图列并不是很明显。对于第一个映射中的每个键,需要检查第二个映射中的值是否相同。钥匙也一样

使用UDF可能更简单,因为在Python中,您可以检查dict相等性:

from pyspark.sql import functions as F

map_equals = F.udf(lambda x, y: x == y, BooleanType())

# create map1 literal to filter with
map1 = F.create_map(*[
    F.lit(x) for x in chain(*{"metric1": 1.3, "metric2": 6.3, "metric3": 7.6}.items())
])

df1 = df.filter(map_equals("metric", map1))

df1.show(truncate=False)

#+----+------------------------------------------------+
#|key |metric                                          |
#+----+------------------------------------------------+
#|123k|[metric1 -> 1.3, metric2 -> 6.3, metric3 -> 7.6]|
#+----+------------------------------------------------+

另一种方法是添加要作为列过滤的映射文本,并检查
metric
中的每个键是否从该文本映射中获得相同的值

下面是一个使用映射键数组上的
transfrom
array\u min
创建过滤器表达式的示例。(如果
array\u min
返回true,则表示所有值相等):



匹配意味着什么?按键匹配,还是按值匹配?或者两者都有?
from pyspark.sql import functions as F

map_equals = F.udf(lambda x, y: x == y, BooleanType())

# create map1 literal to filter with
map1 = F.create_map(*[
    F.lit(x) for x in chain(*{"metric1": 1.3, "metric2": 6.3, "metric3": 7.6}.items())
])

df1 = df.filter(map_equals("metric", map1))

df1.show(truncate=False)

#+----+------------------------------------------------+
#|key |metric                                          |
#+----+------------------------------------------------+
#|123k|[metric1 -> 1.3, metric2 -> 6.3, metric3 -> 7.6]|
#+----+------------------------------------------------+
filter_map_literal = F.create_map(*[
    F.lit(x) for x in chain(*{"metric1": 1.3, "metric2": 6.3, "metric3": 7.6}.items())
])

df1 = df.withColumn("filter_map", filter_map_literal).filter(
    F.array_min(F.expr("""transform(map_keys(metric),
                           x -> if(filter_map[x] = metric[x], true, false)
                    )""")
                )
).drop("filter_map")