Python 具有lambda函数的PySpark映射

Python 具有lambda函数的PySpark映射,python,pandas,apache-spark,lambda,pyspark,Python,Pandas,Apache Spark,Lambda,Pyspark,在Spark环境中混合python映射和lambda函数时,我面临一个问题 给定df1,我的源数据帧: Animals | Food | Home ---------------------------------- Monkey | Banana | Jungle Dog | Meat | Garden Cat | Fish | House Elephant | Banana | Jungle L

在Spark环境中混合python映射和lambda函数时,我面临一个问题

给定df1,我的源数据帧:

Animals     | Food      | Home
----------------------------------
Monkey      | Banana    | Jungle
Dog         | Meat      | Garden
Cat         | Fish      | House
Elephant    | Banana    | Jungle
Lion        | Meat      | Desert
我想创建另一个数据帧df2。它将包含两列,每列一行df1(在我的示例中为3)。 第一列将包含df1列的名称。第二列将包含出现次数最多的元素数组(在下面的示例中为n=3)和计数

Column      | Content
-----------------------------------------------------------
Animals     | [("Cat", 1), ("Dog", 1), ("Elephant", 1)]
Food        | [("Banana", 2), ("Meat", 2), ("Fish", 1)]
Home        | [("Jungle", 2), ("Desert", 1), ("Garden", 1)]
我尝试使用python list、map和lambda函数,但与PySpark函数有冲突:

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
错误是:

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.
TypeError:无效参数,不是类型为的字符串或列。对于列文字,请使用“lit”、“array”、“struct”或“create_map”函数。
知道怎么修吗


非常感谢

这里有一种可能的解决方案,
Content
列将是一个
StructType
数组,其中包含两个命名字段:
Content
count

从pyspark.sql.functions导入col、collect\u list、desc、lit、struct
从functools导入reduce
def变换(df,n):
回报率降低(
lambda a,b:a.unionAll(b),
(
df.groupBy(c.count)()\
.orderBy(描述(“计数”),c)\
.限制(n)\
.带柱(“柱”,亮(c))\
.groupBy(“列”)\
阿格先生(
收集清单(
结构(
第(c)列.cast(“字符串”).别名(“内容”),
“计数”)
).别名(“内容”)
)
对于df列中的c
)
)
此函数将遍历输入数据框中的每一列,
df
,并计算每个值的出现次数。然后我们将计数(降序)和列值本身(按字母顺序)保存在
orderBy
中,只保留前
n行(
limit(n)

接下来,将值收集到一个结构数组中,最后将每个列的结果合并在一起。由于
联合
要求每个数据帧具有相同的模式,因此需要将列值转换为字符串

n=3
df1=变换(df,n)
df1.show(truncate=False)
#+-------+------------------------------------+
#|第|列内容|
#+-------+------------------------------------+
#|动物[猫,1],[狗,1],[大象,1]]|
#|食物[香蕉,2],[肉,2],[鱼,1]]|
#|家|[[丛林,2],[沙漠,1],[花园,1]]|
#+-------+------------------------------------+
这与您要求的输出不完全相同,但可能足以满足您的需要。(Spark没有您描述的元组。)以下是新模式:

df1.printSchema()
#根
#|--列:字符串(nullable=false)
#|--内容:数组(nullable=true)
#| |--元素:struct(containsnall=true)
#| | |--内容:字符串(nullable=true)
#| | |--count:long(nullable=false)

这是可以做到的,但这并不是spark设计的真正问题类型。您可以独立地处理每一列,并
union
合并结果。你怎么断领带?为什么猫、狗、大象的计数都是1?我更喜欢用我的代码来说明我面临的问题。我不明白你为什么说它没用。@pault谢谢你的评论。我是新手,所以我还需要学习。是的,我想我可以独立处理专栏,但我不确定这是最好的解决方案。我按字母顺序断绝关系。这就是为什么我没有展示狮子和猴子。谢谢你的解决方案,它似乎完全满足了我的需要。然而,这会导致一个错误,
Union只能在具有兼容列类型的表上执行。表2第二列的数组
。我不明白布尔类型是从哪里来的。太好了!谢谢!唯一的问题是我有
动物|[[Content:Cat,count:1],[Content:Dog,count:1],[Content;大象,count:1]
可以删除结构中的标题吗?即使我删除了别名,仍然有一个标题。@Maxbester您可以将
结构更改为
数组(在pyspark.sql.functions import array
中的
之后),这将给您留下一个
WrappedArray
。我不知道为什么这对你很重要-最终目标是什么?好的,我会试试。对不起,我以为我在最初的问题中解释了目标。实际上,其目的是验证数据集的创建。我想确保每个列中的数据都是相关的。显然,我的数据集比我举的例子要大得多。