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