Pyspark:如何根据另一列中的匹配值从数组中的第一次出现中选择直到最后的值

Posted

技术标签:

【中文标题】Pyspark:如何根据另一列中的匹配值从数组中的第一次出现中选择直到最后的值【英文标题】:Pyspark : How to pick the values till last from the first occurrence in an array based on the matching values in another column 【发布时间】:2019-05-29 10:28:24 【问题描述】:

我有一个数据框,我需要在其中搜索一个列中存在的值,即另一列中的 StringType,即 ArrayType,但我想从第二列中选择值,直到第一次出现的数组中的最后一个值柱子。

下面举例说明:

输入DF如下:

Employee_Name|Employee_ID|Mapped_Project_ID
Name1|E101|[E101, E102, E103]
Name2|E102|[E101, E102, E103]
Name3|E103|[E101, E102, E103, E104, E105] 

输出 DF 应该如下所示:

Employee_Name|Employee_ID|Mapped_Project_ID
Name1|E101|[E101, E102, E103]
Name2|E102|[E102, E103]
Name3|E103|[E103, E104, E105] 

【问题讨论】:

【参考方案1】:

从 Spark 2.4 开始,您可以使用 array_positionslice 函数:

import pyspark.sql.functions as f    
from pyspark.sql.functions import array_position
from pyspark.sql.functions import slice

df = spark.createDataFrame([(["c", "b", "a","e","f"],'a')], ['arraydata','item'])

df.select(df.arraydata, f.expr("slice(arraydata,array_position(arraydata, item),size(arraydata))").alias("res")).show()

+---------------+---------+
|      arraydata|      res|
+---------------+---------+
|[c, b, a, e, f]|[a, e, f]|
+---------------+---------+

请把它翻译成你的 df colnames。希望这会有所帮助。

【讨论】:

感谢@mrjoseph 的解决方案,但不幸的是我在我的项目中使用Spark 2.3。【参考方案2】:

这就是我想的你想要的,我也在虚拟数据上实现了它:

import pyspark.sql.types as T
import pyspark.sql.functions as F

df = sqlContext.createDataFrame([['E101',["E101", "E102", "E103", "E104", "E105"]]],["eid", "mapped_eid"])
df.persist()
df.show(truncate = False)

+----+------------------------------+
|eid |mapped_eid                    |
+----+------------------------------+
|E101|[E101, E102, E103, E104, E105]|
+----+------------------------------+

@F.udf(returnType=T.ArrayType(T.StringType()))
def find_element(element,temp_list):
    count = 0
    res = []
    for i in range(len(temp_list)):
        if (count == 0) and (temp_list[i] != element):
            count = 1
            res.append(temp_list[i]) 
        elif count == 1:
            res.append(temp_list[i]) 
    return res

df.withColumn(
    "res_col",
    find_element(F.col("eid"), F.col("mapped_eid"))
).show(truncate = False)

+----+------------------------------+------------------------+
|eid |mapped_eid                    |res_col                 |
+----+------------------------------+------------------------+
|E101|[E101, E102, E103, E104, E105]|[E102, E103, E104, E105]|
+----+------------------------------+------------------------+

让我知道这是否适合你。

【讨论】:

我们可以避免使用 UDF。我想在不使用 UDF 的情况下工作 不,我们不能不使用 UDF,这不是最佳方法,唯一的其他选择是拆分数组不会推荐它 使用新函数可以避免使用 udfs(从 Spark 2.4 开始): slice 和 array_position: spark.apache.org/docs/latest/api/python/…

以上是关于Pyspark:如何根据另一列中的匹配值从数组中的第一次出现中选择直到最后的值的主要内容,如果未能解决你的问题,请参考以下文章

如何根据 PySpark 数据框的另一列中的值修改列? F.当边缘情况

使用 PySpark 连接与另一列中的两列确定的范围相匹配的数据框

利用 PySpark,确定数组列中有多少元素包含在另一列中的数组数组中

PySpark查找另一列中是否存在一列中的模式

Pyspark根据另一列的模式替换列中的字符串

基于另一列中的值的一列上的pyspark滞后函数