Python 在PySpark中以分布式方式应用udf函数

Python 在PySpark中以分布式方式应用udf函数,python,apache-spark,pyspark,apache-spark-sql,spark-dataframe,Python,Apache Spark,Pyspark,Apache Spark Sql,Spark Dataframe,假设我有一个非常基本的Spark数据框,它由两列组成,其中一列包含我要修改的值 || value || lang || | 3 | en | | 4 | ua | 比如说,我想为每个特定的类创建一个新的列,在这个列中,我会向给定的值添加一个浮点数(虽然这与最后一个问题没有太大关系,但实际上我用sklearn做了一个预测,但是为了简单起见,让我们假设我们正在添加内容,想法是我正在以某种方式修改值)。因此,给定一个dictclasses={'1':2.0

假设我有一个非常基本的Spark数据框,它由两列组成,其中一列包含我要修改的值

|| value   || lang ||
| 3        |  en   |
| 4        |  ua   |
比如说,我想为每个特定的类创建一个新的列,在这个列中,我会向给定的值添加一个浮点数(虽然这与最后一个问题没有太大关系,但实际上我用sklearn做了一个预测,但是为了简单起见,让我们假设我们正在添加内容,想法是我正在以某种方式修改值)。因此,给定一个dict
classes={'1':2.0,'2':3.0}
我希望每个类都有一个列,在其中我将DF中的值添加到类的值,然后将其保存到csv:

class_1.csv
|| value   || lang ||  my_class |  modified  ||
| 3        |  en   |     1      |     5.0    |  # this is 3+2.0
| 4        |  ua   |     1      |     6.0    |  # this is 4+2.0

class_2.csv
|| value   || lang ||  my_class |  modified  ||
| 3        |  en   |     2      |     6.0    |  # this is 3+3.0
| 4        |  ua   |     2      |     7.0    |  # this is 4+3.0
到目前为止,我有以下代码可以工作并修改每个已定义类的值,但它是通过for循环完成的,我正在为它寻找更高级的优化:

import pyspark
from pyspark import SparkConf, SparkContext
from pyspark.sql import functions as F
from pyspark.sql.types import FloatType
from pyspark.sql.functions import udf
from pyspark.sql.functions import lit

# create session and context
spark = pyspark.sql.SparkSession.builder.master("yarn").appName("SomeApp").getOrCreate()
conf = SparkConf().setAppName('Some_App').setMaster("local[*]")
sc = SparkContext.getOrCreate(conf)

my_df = spark.read.csv("some_file.csv")

# modify the value here
def do_stuff_to_column(value, separate_class):
    # do stuff to column, let's pretend we just add a specific value per specific class that is read from a dictionary
    class_dict = {'1':2.0, '2':3.0}  # would be loaded from somewhere
    return float(value+class_dict[separate_class])

 # iterate over each given class later
 class_dict = {'1':2.0, '2':3.0}   # in reality have more than 10 classes

 # create a udf function
 udf_modify = udf(do_stuff_to_column, FloatType())

 # loop over each class
 for my_class in class_dict:
    # create the column first with lit
    my_df2 = my_df.withColumn("my_class", lit(my_class))
    # modify using udf function
    my_df2 = my_df2.withColumn("modified", udf_modify("value","my_class"))
    # write to csv now
    my_df2.write.format("csv").save("class_"+my_class+".csv")

所以问题是,有没有更好/更快的方法来实现这一点

我会使用某种形式的
连接
,在本例中是
交叉连接
。这里有一个MWE:

从pyspark.sql导入SparkSession
导入pyspark.sql.F函数
spark=SparkSession.builder.getOrCreate()
df=spark.createDataFrame([(3,'en'),(4,'ua'),['value','lang']))
classes=spark.createDataFrame([(1,2.),(2,3.)],['class_key','class_value']))
res=df.crossJoin(class).withColumn('modified',F.col('value'))+F.col('class_value'))
res.show()

为了保存为单独的CSV,我认为没有比使用循环更好的方法了。

您期望哪种优化?循环没有什么特别的错误-您有单独的接收器,这意味着单独的操作,并且每个操作都是正确分布的。您可以进行或应用一些人工更改(
union
+
partitionBy
),但我怀疑您是否能从中获得很多好处。您可能可以跳过
udf
(这可能是一个瓶颈),但为此,我们需要查看代码。@user9613318我希望找到某种方法来并行for循环,但找不到任何相关的内容。谢谢你的想法。你也可以检查一下。谢谢,我得问一下,MWE代表什么?