从 pyspark 中的数据框数组类型列中获取“名称”元素

Posted

技术标签:

【中文标题】从 pyspark 中的数据框数组类型列中获取“名称”元素【英文标题】:Get "name" elements from dataframe arraytype column in pyspark 【发布时间】:2019-02-14 12:02:37 【问题描述】:

我已经生成了 pyspark.sql.dataframe.DataFrame,其中列名称为 cast 和 score。

但是,我想在 _score 列旁边保留 cast 列中的唯一名称,而不是与它们关联的 id。

e.g Liam Neeson, 'Dan Stevens, Marina Squerciati, Scott Frank

cast 列中数据类型的结构如下所示

df_test.schema['cast'].dataType

StructType(List(StructField(Acteur$divActrice,ArrayType(StructType(List(StructField(id,StringType,true),StructField(name,StringType,true))),true),true),StructField(Regisseur,ArrayType(StructType(List(StructField(id,StringType,true),StructField(name,StringType,true))),true),true),StructField(writer,ArrayType(StructType(List(StructField(id,StringType,true),StructField(name,StringType,true))),true),true)))
    elasticsearch_performance_evaluation.drop('id', '_type', 'name').show(20, False)
+------------------------------------------------------------------------------------------------------------+---------+
|cast                                                                                                        |_score   |
+------------------------------------------------------------------------------------------------------------+---------+
|[[[3713, Liam Neeson], [24315, Dan Stevens], [37138, Marina Squerciati]], [[37136, Scott Frank]],]          |90.68749 |
|[[[365, Susan Sarandon], [1939, Tom Hanks], [13425, Halle Berry]], [[6813, Tom Tykwer]],]                   |42.601303|
|[[[1939, Tom Hanks], [3339, Julia Roberts], [8479, Sarah Mahoney]], [[1939, Tom Hanks]],]                   |42.601196|
|[[[1939, Tom Hanks], [42930, Sarita Choudhury], [44288, Alexander Black]], [[6813, Tom Tykwer]],]           |42.601196|
|[[[13379, Emilio Estevez], [13381, Martin Sheen], [13383, Deborah Kara Unger]], [[13379, Emilio Estevez]],] |22.130056|
|[[[15871, Frank Lammers]], [[30157, Mark Mertens]],]                                                        |20.221449|
|[[[44061, Erin Darke], [44548, Hansel Tan], [233, Rachel Weisz]], [[10329, Joshua Marston]],]               |19.26571 |
|[[[1535, Pim Wessels], [2327, Joosje Duk], [2329, Ydwer Bosma]], [[1537, Steven de Jong]],]                 |18.798985|
|[[[6741, Chantal Janzen], [16357, Benja Bruijning], [15865, Fedja van Huêt]], [[2769, Kees van Nieuwkerk]],]|18.79888 |
|[[[6105, Stephen Dorff], [9611, Tom Berenger], [12397, Chyler Leigh]], [[12395, Gabe Torres]],]             |17.88121 |
|[[[2309, Gene Hackman], [8955, Tom Cruise], [12971, Ed Harris]], [[30047, Sydney Pollack]],]                |17.88121 |
|[[[1105, Marisa Tomei], [12763, Hugh Grant], [43842, J.K Simmons]], [[5637, Marc Lawrence]],]               |17.88121 |
|[[[8955, Tom Cruise], [10405, Kelly McGillis], [2023, Val Kilmer]], [[2311, Tony Scott]],]                  |17.88121 |
|[[[2105, Tom Hughes], [43507, Emma Greenwell], [43508, Alex Macqueen]], [[43506, Vivienne de Courcy]],]     |17.881105|
|[[[1201, Carice van Houten], [2271, Bill Nighy], [8955, Tom Cruise]], [[18203, Bryan Singer]],]             |17.881105|
|[[[9159, Anne Hathaway], [9161, Jim Sturgess], [9163, Tom Mison]], [[9157, Lone Scherfig]],]                |17.881105|
|[[[921, Ewan McGregor], [4603, Naomi Watts], [16997, Tom Holland]], [[16995, Juan Antonio Bayona]],]        |17.881105|
|[[[44161, Edie Falco], [44162, Miles Gaston Villanueva], [44163, Gus Halper]],,]                            |17.65994 |
|[[[2327, Joosje Duk], [2329, Ydwer Bosma], [3461, Leo de Jong]], [[1537, Steven de Jong]],]                 |17.65994 |
|[[[10841, Bas Muijs], [25285, Vivian van Huiden], [28091, Tom van Kalmthout]], [[1537, Steven de Jong]],]   |16.626995|
+------------------------------------------------------------------------------------------------------------+---------+

有人可以帮助我如何仅使用演员名称和分数列提取数据。

提前致谢

【问题讨论】:

能否提供列名 @PrasanthGanesan 它的cast_Scorecast 列是包含数字 ID 和名称的数组类型,谢谢 您在迭代数据集时遇到任何问题吗? 是的,我有问题,我只需要得到这样的演员姓名Liam Neeson, 'Dan Stevens, Marina Squerciati, Scott Frank 您的列表看起来无效。每行都以 ,] 结尾,这是一个无效的语法。您发布了正确的数据集吗? 【参考方案1】:

一种可能的解决方案是转换为 rdd,然后是提取演员名称的映射函数,最后转换回数据帧。

df1 = spark.createDataFrame([([[["3713", "Liam Neeson"], ["24315", "Dan Stevens"],\
 ["37138", "Marina Squerciati"]], [["37136", "Scott Frank"]],], 90.687),\
([[["365", "Susan Sarandon"], ["1939", "Tom Hanks"], ["13425", "Halle Berry"]],\
 [["6813", "Tom Tykwer"]],], 42.601303)],["cast","score"])
#creation of the dataframe, e.g. first 2 rows of your example

def extract_actor(row):                    #extract function
    actors, score = row
    new_actors = list()
    for l in actors:
        res = list()
        for actor in l:
            res.append(actor[1])          #walk through all the lists and collect the names
        new_actors.append(res)
    return (new_actors,score)

df1.rdd.map(extract_actor).toDF(["cast","score"]).show(truncate=False)
#transform dataframe to rdd apply the map and transform result back to dataframe

输出:

+--------------------------------------------------------------------------------------+---------+
|cast                                                                                  |score    |
+--------------------------------------------------------------------------------------+---------+
|[WrappedArray(Liam Neeson, Dan Stevens, Marina Squerciati), WrappedArray(Scott Frank)]|90.687   |
|[WrappedArray(Susan Sarandon, Tom Hanks, Halle Berry), WrappedArray(Tom Tykwer)]      |42.601303|
+--------------------------------------------------------------------------------------+---------+

【讨论】:

这正是我想要的,然后第二个问题我有 1000 行要遍历并像你一样从每一行中获取名称。我怎样才能做到这一点?干杯 行数不应影响解。只需将您的数据加载到数据框中并将解决方案应用于它。它应该提取每一行的名称 对不起,我是这个意思。我收到一个错误,因为我将更复杂的数据结构添加到您的函数顶部?我如何使函数适应这种数据框。 你能说出你想要使用的数据框的架构或结构吗?该函数始终采用数据框的一行并处理那里的值,如果该行包含其他字段,则需要调整函数并获取类似于 score 变量的值 @gaw| | | |-- id: 字符串 (可为空 = true) | | | |-- 名称:字符串 (nullable = true) |-- _score: double (nullable = true)【参考方案2】:

你可以使用explode函数,更多信息见these答案

【讨论】:

那么你将不得不爆炸几次,因为它是一个列表列表的列表

以上是关于从 pyspark 中的数据框数组类型列中获取“名称”元素的主要内容,如果未能解决你的问题,请参考以下文章

pySpark:如何在数据框中的 arrayType 列中获取 structType 中的所有元素名称?

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

从 pyspark 数据框中的列中提取特定字符串

如何从 pyspark 数据框列中的列表中删除特定字符串

PySpark - 如何根据列中的两个值从数据框中过滤出连续的行块

pyspark 在循环中将数组转换为字符串