Spark RDD.map在spark数据框中使用withColumn方法

时间:2017-07-02 03:12:45

标签: python apache-spark pyspark

我有以下代码:

from pyspark import *;
from pyspark.sql import *;
from pyspark.sql.functions import udf
from pyspark.sql.types import StringType, StructType, StructField, IntegerType, DoubleType
import math;

sc = SparkContext.getOrCreate();
spark = SparkSession.builder.master('local').getOrCreate();


schema = StructType([
    StructField("INDEX", IntegerType(), True),
    StructField("SYMBOL", StringType(), True),
    StructField("DATETIMETS", StringType(), True),
    StructField("PRICE", DoubleType(), True),
    StructField("SIZE", IntegerType(), True),
])

df = spark\
    .createDataFrame(
        data=[(0,'A','2002-12-02 9:30:20',19.75,30200),
             (1,'A','2002-12-02 9:31:20',19.75,30200),             
             (8,'A','2004-12-02 10:36:20',1.0,30200),
             (9,'A','2006-12-02 22:41:20',20.0,30200),
             (10,'A','2006-12-02 22:42:20',40.0,30200)],
        schema=schema);

然后我在不使用spark的情况下进行一些计算。 这很好。

def without_spark(price):    
    first_summation = sum(map(lambda n: math.sqrt(price), range(1,10)));
    return first_summation;

u_without_spark = udf(without_spark, DoubleType())

df.withColumn("NEW_COL", u_without_spark('PRICE')).show()

No Spark Output

以下使用rdd并行化的代码不会。

def with_spark(price):    
    rdd = sc.parallelize(1, 10)
    first_summation = rdd.map(lambda n: math.sqrt(price));
    return first_summation.sum();

u_with_spark = udf(with_spark, DoubleType())

df.withColumn("NEW_COL", u_with_spark('PRICE')).show()

Spark Error

我想做的不可能吗? 有更快的方法吗?

感谢您的帮助

2 个答案:

答案 0 :(得分:0)

您无法在UDF中调用任何RDD方法。

创建UDF时,它会在worker上运行。 RDD或数据帧操作只能在驱动程序上运行,因此不允许在UDF中使用。

好像你的目标是做一个UDAF(用户定义的聚合方法)。这不能从pyspark完成。你有两种选择。使用collect_list,然后在结果数组上执行UDF,或者在scala中编写UDAF并将其包装为pyspark。

答案 1 :(得分:0)

  
    

然后我在不使用spark

的情况下进行一些计算   

创建dataframe时,您使用了 SparkSession ,因此您已经在使用 spark udfwithColumn spark dataframe 的api,用于转换dataframe

Dataframes本质上是分布式的,即dataframes上的所有转换都在工作节点中完成。因此,使用udf withColumn的{​​{1}}都是在工作节点上完成的。您在驱动程序节点中创建了transformationsparkContext),但无法在转换中使用。

  
    

我想做的不可能吗?有更快的方法吗?

  

您尝试从转化中访问sc时,第二次实施是错误的。

您的第一种方法似乎工作正常并且已经使用了spark。所以我想你不需要寻找其他选择。