当前位置: 首页 > 知识库问答 >
问题:

基于需要外部API调用的现有列创建新Spark数据帧列的最佳方法是什么?

龙俊英
2023-03-14

我有一个数据帧,我正在基于Python的Jupyter笔记本中使用。我想根据现有列的内容添加一个附加列,其中新列的内容派生自对原始列运行外部 API 调用。

我尝试的解决方案是使用基于Python的UDF。第一个单元格包含如下内容:

def analysis(old_column):

    new_column = myapi.analyze(text=old_column)
    return(new_column)

analysis_udf = udf(analysis)

第二个单元格是:

df2 = df1.withColumn("col2",analysis_udf('col1'))
df2.select('col2').show(n=5)

我的数据帧相对较大,大约有70000行,其中col1可以有100到10000个字符的文本。当我在单元2中运行上面的代码时,它实际上似乎运行得相当快(分钟),并转储了df2数据帧的5行。所以我以为我在做生意。然而,我的下一个手机有以下代码:

df2.cache()
df2.filter(col('col2').isNull()).count()

此代码的目的是缓存新数据帧的内容以缩短对 DF 的访问时间,然后计算数据帧中有多少条目具有 UDF 生成的空值。令人惊讶的是(对我来说)这花了很多时间来运行,最终提供了6的输出。我不清楚为什么第二个细胞运行得很快,而第三个细胞运行缓慢。但是,如果 df2.select('col2').show(n=5) 调用会导致 UDF 在所有行上运行,并且该行的速度会很慢,然后访问数据帧新列的后续调用会很快。但事实并非如此,所以我当时认为缓存调用是导致UDF在所有行上运行的调用,因此现在任何后续调用都应该很快。所以添加了另一个单元格:

df2.show(n=5)

假设它会运行得很快,但同样,它花的时间比我预期的长得多,看起来也许UDF又开始运行了。(?)

我的问题是:

  1. 哪些Spark api调用实际导致udf运行(或重新运行),以及如何构建调用以仅运行一次UDF,以便使用UDF的python函数输出的文本创建新列。
  2. 我读到应该避免Python UDF,因为它们很慢(似乎是正确的),那么当我需要使用API调用来生成新列时,我有什么替代方案?

共有1个答案

戚兴思
2023-03-14

我认为df2.select('col2'). show(n=5)调用会导致UDF运行

这不是一个正确的假设。鉴于API的限制,Spark将评估尽可能少的数据。因为您使用Pythonudf,它将评估收集5行所需的最小分区数。

哪些火花api调用实际导致udf运行(或重新运行),以及如何构建调用以仅运行一次UDF,以便使用UDF的python函数输出的文本创建新列。

  • 任何评估,如果数据不再缓存(从内存中逐出)。
  • 可能是结果列的任何用法,除非 udf 被标记为非确定性。

我已经读到应该避免Python UDF,因为它们很慢(似乎是正确的),那么当我需要使用API调用来生成新列时,我有什么替代方案?

除非您想切换到Scala或RDD API,否则唯一的选择是pandas_udf,这稍微更有效,但只支持有限的类型子集。

 类似资料:
  • 我正在尝试查看我们是否可以使用 spark/scala 从 dataFrame 中某个列中的值创建新列。我有一个数据帧,其中包含以下数据 在上面的数据中,col1/col2/col3是列名,后跟它的值。列名和值由< code >,分隔。每组由< code>|分隔。 现在,我想做到这一点 感谢任何帮助。

  • 假设,我有以下数据帧: 与 col1 不同的值(p1、p2、p3)单独具有 id,将用作最终数据帧的列。在这里,id y 对于相同的 col1 值 p2 有两个 col2 值(b2 和 b3),因此,p2 将被视为数组类型列。因此,最终的数据帧将是 如何从第一个数据帧高效地实现第二个数据帧?

  • 我有两个熊猫数据框 步骤2:对于flag=1的行,AA_new将计算为var1(来自df2)*组“A”和val“AA”的df1的'cal1'值*组“A”和val“AA”的df1的'cal2'值,类似地,AB_new将计算为var1(来自df2)*组“A”和val“AB”的df1的'cal1'值*组“A”和val“AB”的df1的'cal2'值 我的预期输出如下所示: 以下基于其他stackflow

  • 我有一个pandas dataframe,需要根据dataframe中其他列的值创建新列。这是数据帧 人城市国家国家 美国伊利诺伊州芝加哥 美国亚利桑那州凤凰城B酒店 C美国加利福尼亚州圣地亚哥 我想根据state中的值创建两个新列 创建新列df[“城北”]=df[“城市”]其中state=“伊利诺伊” 创建新列df[“城市南部”]=df[“城市”],其中州不等于“伊利诺伊州” 我试过了 但是不等

  • 问题内容: 组织以下pandas数据框的最有效方法是什么: 数据= 变成字典一样? 问题答案: In [9]: pd.Series(df.Letter.values,index=df.Position).to_dict() Out[9]: {1: ‘a’, 2: ‘b’, 3: ‘c’, 4: ‘d’, 5: ‘e’} 速度比较(使用Wouter方法)

  • 我有一个游戏,在MySQL数据库中存储boss在简单模式和硬模式下的杀人记录。有14个老板。我想存储一个球员杀死一个老板的次数和难度。我有几个选择,我可以看到。。 为每个boss以及每个难度在表中创建一个单独的列。例如。 创建两个存储数字序列的字段,这些数字可以稍后提取出来,以便在PHP中进行比较。其中easykills是一个由28个字符组成的字符串,每2个字符就有一个计数器,用于计算boss被杀