PySpark - map with lambda function
在 Spark 环境中混合 python map 和 lambda 函数时,我遇到了一个问题。
给定 df1,我的源数据框:
1 2 3 4 5 6 7 | Animals | Food | Home ---------------------------------- Monkey | Banana | Jungle Dog | Meat | Garden Cat | Fish | House Elephant | Banana | Jungle Lion | Meat | Desert |
我想创建另一个数据框 df2。它将包含两列,每列 df1 一行(在我的示例中为 3)。
第一列将包含 df1 列的名称。第二列将包含出现次数最多的元素数组(在下面的示例中 n=3)和计数。
1 2 3 4 5 | Column | Content ----------------------------------------------------------- Animals | [("Cat", 1), ("Dog", 1), ("Elephant", 1)] Food | [("Banana", 2), ("Meat", 2), ("Fish", 1)] Home | [("Jungle", 2), ("Desert", 1), ("Garden", 1)] |
我尝试使用 python 列表、映射和 lambda 函数来实现,但与 PySpark 函数发生冲突:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | def transform(df1): # Number of entry to keep per row n = 3 # Add a column for the count of occurence df1 = df1.withColumn("future_occurences", F.lit(1)) df2 = df1.withColumn("Content", F.array( F.create_map( lambda x: (x, [ str(row[x]) for row in df1.groupBy(x).agg( F.sum("future_occurences").alias("occurences") ).orderBy( F.desc("occurences") ).select(x).limit(n).collect() ] ), df1.columns ) ) ) return df2 |
错误是:
1 | TypeError: Invalid argument, not a string or column: <function <lambda> at 0x7fc844430410> of type <type 'function'>. For column literals, use 'lit', 'array', 'struct' or 'create_map' function. |
知道怎么解决吗?
非常感谢!
这是一种可能的解决方案,其中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | from pyspark.sql.functions import col, collect_list, desc, lit, struct from functools import reduce def transform(df, n): return reduce( lambda a, b: a.unionAll(b), ( df.groupBy(c).count()\\ .orderBy(desc("count"), c)\\ .limit(n)\\ .withColumn("Column", lit(c))\\ .groupBy("Column")\\ .agg( collect_list( struct( col(c).cast("string").alias("Content"), "count") ).alias("Content") ) for c in df.columns ) ) |
此函数将遍历输入DataFrame
接下来,将值收集到结构数组中,最后将每列的结果
1 2 3 4 5 6 7 8 9 10 | n = 3 df1 = transform(df, n) df1.show(truncate=False) #+-------+------------------------------------+ #|Column |Content | #+-------+------------------------------------+ #|Animals|[[Cat,1], [Dog,1], [Elephant,1]] | #|Food |[[Banana,2], [Meat,2], [Fish,1]] | #|Home |[[Jungle,2], [Desert,1], [Garden,1]]| #+-------+------------------------------------+ |
这与您要求的输出不完全相同,但可能足以满足您的需求。 (Spark 没有您描述的元组。)这是新模式:
1 2 3 4 5 6 7 | df1.printSchema() #root # |-- Column: string (nullable = false) # |-- Content: array (nullable = true) # | |-- element: struct (containsNull = true) # | | |-- Content: string (nullable = true) # | | |-- count: long (nullable = false) |