当前位置: 首页 > 面试题库 >

在withColumn下将数据框列和外部列表传递给udf

乐正镜
2023-03-14
问题内容

我有一个具有以下结构的Spark数据框。bodyText_token具有标记(已处理/单词集)。而且我有一个嵌套的已定义关键字列表

root
 |-- id: string (nullable = true)
 |-- body: string (nullable = true)
 |-- bodyText_token: array (nullable = true)

keyword_list=[['union','workers','strike','pay','rally','free','immigration',],
['farmer','plants','fruits','workers'],['outside','field','party','clothes','fashions']]

我需要检查每个关键字列表下有多少标记,并将结果添加为现有数据框的新列。例如:如果tokens =["become", "farmer","rally","workers","student"] 结果为->[1,2,0]

以下功能按预期工作。

def label_maker_topic(tokens,topic_words):
    twt_list = []
    for i in range(0, len(topic_words)):
        count = 0
        #print(topic_words[i])
        for tkn in tokens:
            if tkn in topic_words[i]:
                count += 1
        twt_list.append(count)

    return twt_list

我在下面使用udfwithColumn访问该函数,但出现错误。我认为这与将外部列表传递给udf有关。有没有一种方法可以将外部列表和dataframe列传递给udf,并向dataframe中添加新列?

topicWord = udf(label_maker_topic,StringType())
myDF=myDF.withColumn("topic_word_count",topicWord(myDF.bodyText_token,keyword_list))

问题答案:

最干净的解决方案是使用闭包传递其他参数:

def make_topic_word(topic_words):
     return udf(lambda c: label_maker_topic(c, topic_words))

df = sc.parallelize([(["union"], )]).toDF(["tokens"])

(df.withColumn("topics", make_topic_word(keyword_list)(col("tokens")))
    .show())

这不需要更改keyword_list或使用UDF包装功能。您也可以使用此方法传递任意对象。例如,这可以用于传递sets有效查找的列表。

如果要使用当前的UDF并topic_words直接传递,则必须先将其转换为列文字:

from pyspark.sql.functions import array, lit

ks_lit = array(*[array(*[lit(k) for k in ks]) for ks in keyword_list])
df.withColumn("ad", topicWord(col("tokens"), ks_lit)).show()

根据您的数据和要求,可以选择其他更有效的解决方案,这些解决方案不需要UDF(爆炸+聚合+折叠)或查找(散列+向量运算)。



 类似资料:
  • 问题内容: 我想按值将列表传递给函数。默认情况下,列表和其他复杂对象通过引用传递给函数。这是一些目标: 可以写得短些吗?换句话说,我不想更改 ad 。 问题答案: 您可以使用,但是对于包含列表(或其他可变对象)的列表,您应该使用: 等价于或,并返回列表的浅表副本。 何时使用:

  • 问题内容: 我想在我的课程中传递默认参数,但是不知何故我遇到了问题: 如果现在尝试实例化,则会出现以下错误: 我究竟做错了什么? 问题答案: 从该文档: 要使用的参数是: default_factory: 如果提供, 则必须为零参数可调用对象 ,当此字段需要默认值时将被调用。除其他用途外,这可用于指定具有可变默认值的字段,如下所述。同时指定default和default_factory是错误的。

  • 我需要用不同对象的列表填充几个子报表。基本上,假设我有以下内容:< br >二手车子报表< br >新车子报表< br > 我用字符串形式的变量创建了一个vehicle bean类,并为其创建了getter和setter方法。然后在我的数据源中,我传入一个< code >列表 我在主报表中创建了一个字段详细信息行作为类型列表。然后,我将以下内容传递给子报表数据源表达式,new 有什么方法可以将 从

  • 我正在从 JRBeanCollectionDataSource 生成报告。此报告是关于客户的订单的。 这是我的代码 当客户时,需要生成包含客户详细信息和客户订单列表的报告。由于接受一个集合,这就是我所做的。 如何提取< code>Customer中的< code>CustomerOrder列表并将其作为子报表传递?

  • 问题内容: 我正在尝试从SQL导出到.csv,如果我对其进行硬编码以接受一定数量的参数,则它可以正常工作。问题是,我想允许用户请求任意数量的参数,并将它们传递给where子句。该代码应该使这一点更加清楚。 所以我想我要做的是将列表传递给where子句,而不是显式的:dates#变量。例如,一个人可以使用参数“ 2012-01-0412:00、2012-02-04 12:00、2012-03-04

  • 有没有比传递分隔字符串并稍后解析它更优雅的方法来传递可选的整数列表到?我也有一个位置论点。 不工作,因为试图获取并抱怨它不是整数。 理想情况下,我想与其中一个执行 或者类似的东西,但也能