Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark Pyspark dataframe:如何按组应用scipy.optimize函数_Apache Spark_Dataframe_Group By_Pyspark_Apache Spark Sql - Fatal编程技术网

Apache spark Pyspark dataframe:如何按组应用scipy.optimize函数

Apache spark Pyspark dataframe:如何按组应用scipy.optimize函数,apache-spark,dataframe,group-by,pyspark,apache-spark-sql,Apache Spark,Dataframe,Group By,Pyspark,Apache Spark Sql,我有一段代码,它运行良好,但使用pandas数据帧分组处理。 但是,由于文件很大(>7000万组),我需要将代码转换为使用PYSPARK数据帧。 以下是使用pandas dataframe和小示例数据的原始代码: import pandas as pd import numpy as np from scipy.optimize import minimize df = pd.DataFrame({ 'y0': np.random.randn(20), 'y1': np.random.rand

我有一段代码,它运行良好,但使用pandas数据帧分组处理。 但是,由于文件很大(>7000万组),我需要将代码转换为使用PYSPARK数据帧。 以下是使用pandas dataframe和小示例数据的原始代码:

import pandas as pd
import numpy as np
from scipy.optimize import minimize

df = pd.DataFrame({
'y0': np.random.randn(20),
'y1': np.random.randn(20),
'x0': np.random.randn(20), 
'x1': np.random.randn(20),
'grpVar': ['a', 'b'] * 10})

# Starting values
startVal = np.ones(2)*(1/2)

#Constraint  Sum of coefficients = 0
cons = ({'type':'eq', 'fun': lambda x: 1 - sum(x)})

# Bounds on coefficients
bnds = tuple([0,1] for x in startVal)

# Define a function to calculate sum of squared differences
def SumSqDif(a, df):
    return np.sum((df['y0'] - a[0]*df['x0'])**2 + (df['y1'] - a[1]*df['x1'])  **2)

# Define a function to call minimize function 
def RunMinimize(data, startVal, bnds, cons):
    ResultByGrp = minimize(SumSqDif, startVal, method='SLSQP',
    bounds=bnds, constraints = cons, args=(data))
return ResultByGrp.x

# Do the calculation by applyng the function by group:
# Create GroupBy object
grp_grpVar = df.groupby('grpVar')

Results = grp_grpVar.apply(RunMinimize, startVal=startVal, bnds=bnds, cons=cons))
现在我正在尝试使用pySpark数据帧 为了测试代码,我将pandas数据帧转换为pyspark数据帧

sdf = sqlContext.createDataFrame(df)
type(sdf)
#  <class 'pyspark.sql.dataframe.DataFrame'>

# Create GroupBy object
Sgrp_grpVar = sdf.groupby('grpVar')

# Redefine functions
def sSumSqDif(a, sdf):
    return np.sum((sdf['y0'] - a[0]*sdf['x0'])**2 + (sdf['y1'] - a[1]*sdf['x1'])**2)

def sRunMinimize(data=sdf, startVal=startVal, bnds=bnds, cons=cons):
    ResultByGrp = minimize(sSumSqDif, startVal, method='SLSQP',
                       bounds=bnds, constraints = cons, args=(data))
return ResultByGrp.x

from pyspark.sql.functions import UserDefinedFunction
from pyspark.sql.types import DoubleType
from pyspark.sql.types import StringType

udf = UserDefinedFunction(sRunMinimize , StringType())

Results = Sgrp_grpVar.agg(sRunMinimize()) 
sdf=sqlContext.createDataFrame(df)
类型(sdf)
#  
#创建GroupBy对象
Sgrp_grpVar=sdf.groupby('grpVar'))
#重新定义函数
def sSumSqDif(a,sdf):
返回np.sum((sdf['y0']-a[0]*sdf['x0'])**2+(sdf['y1']-a[1]*sdf['x1'])**2)
def sRunMinimize(数据=sdf,startVal=startVal,bnds=bnds,cons=cons):
ResultByGrp=最小化(sSumSqDif,startVal,方法='SLSQP',
边界=bnds,约束=cons,参数=(数据))
返回结果bygrp.x
从pyspark.sql.functions导入UserDefinedFunction
从pyspark.sql.types导入DoubleType
从pyspark.sql.types导入StringType
udf=UserDefinedFunction(srunnimize,StringType())
结果=Sgrp_grpVar.agg(sRunMinimize())
但是,在我尝试定义用户定义的函数udf之后,我得到了以下错误-请参见下文。 非常感谢您对我纠正错误或提出替代方法的任何帮助

udf=UserDefinedFunction(srunnimize,StringType()) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 文件“/usr/hdp/current/spark2 client/python/pyspark/sql/functions.py”,第1760行,在init
self.\u judf=self.\u create\u judf(name)….

您正在尝试编写一个用户定义的聚合函数,该函数无法在pyspark中完成

您可以编写一个
UDF
,用于收集每个组中的数据,作为列表:

首先是设置:

将熊猫作为pd导入
将numpy作为np导入
从scipy.optimize导入最小化
将pyspark.sql.functions作为psf导入
从pyspark.sql.types导入*
df=pd.DataFrame({
“y0”:np.random.randn(20),
“y1”:np.random.randn(20),
“x0”:np.random.randn(20),
'x1':np.random.randn(20),
'grpVar':['a','b']*10})
sdf=sqlContext.createDataFrame(df)
#起始值
startVal=np.ones(2)*(1/2)
#系数的约束和=0
cons=({'type':'eq','fun':lambda x:1-sum(x)})
#系数的界
bnds=元组([0,1]表示startVal中的x)
我们将广播这些变量,因为我们需要在聚合数据帧的每一行上调用它们,它会将值复制到每个节点,这样它们就不必在驱动程序上获取它们:

sc.broadcast(startVal)
sc.广播(bnds)
让我们使用
collect\u list
聚合数据,我们将更改周围数据的结构,使我们只有一列(您可以将每列收集到不同的列中,但随后必须修改将数据传递给函数的方式):

Sgrp\u grpVar=sdf\
.groupby(“grpVar”)\
.agg(psf.collect_list(psf.struct(“y0”、“y1”、“x0”、“x1”))。别名(“数据”))
Sgrp_grpVar.printSchema()
根
|--grpVar:string(nullable=true)
|--数据:数组(nullable=true)
||--元素:struct(containsnall=true)
|| |--y0:double(nullable=true)
|| |--y1:double(nullable=true)
|| |--x0:double(nullable=true)
|| |--x1:double(nullable=true)
我们现在可以创建我们的
UDF
,返回的数据类型对于pyspark来说太复杂了,
numpy数组
不受pyspark支持,因此我们需要对其进行一些更改:

def sSumSqDif(a,数据):
返回np.sum(
(数据['y0']-a[0]*数据['x0'])**2\
+(数据['y1']-a[1]*数据['x1'])**2)
def sRunMinimize(数据,startVal=startVal,bnds=bnds,cons=cons):
data=pd.DataFrame({k:v代表k,v在zip中([“y0”、“y1”、“x0”、“x1”],data)})
ResultByGrp=最小化(sSumSqDif,startVal,方法='SLSQP',
边界=bnds,约束=cons,参数=(数据))
返回结果bygrp.x.tolist()
srunnimize_udf=lambda startVal,bnds,cons:psf.udf(
lambda数据:sRunMinimize(数据、startVal、bnds、cons),
ArrayType(DoubleType())
)
我们现在可以将此功能应用于每个组中收集的数据:

Results=sdf\u agg.select(
“grpVar”,
sRunMinimize_udf(startVal、bnds、cons)(“数据”)。别名(“res”)
)
Results.show(truncate=False)
+------+-----------------------------------------+
|grpVar | res|
+------+-----------------------------------------+
|b |[0.4073139282953772,0.5926860717046227]|
|a |[0.8275186444565927,0.17248135554340727]|
+------+-----------------------------------------+

但我不认为pyspark是实现这一点的合适工具。

我的第一个观察结果是,不能将整个Spark数据帧作为参数发送给udf,只能发送数据帧的列。玛丽,非常感谢你的解决方案。我将用我的真实数据尝试它。它很大:大约6亿条记录/7000万组和12个变量(在我的示例中是x0..x6和y0..y6)。在您看来,如果pyspark不适合此问题,那么什么是合适的?Marie,在对大型数据集运行代码之前,我尝试了代码,因为它使用的是小型示例数据。在最后一步中,它给了我一个错误:回溯(最近的调用last):文件“”,第1行,在NameError中:未定义名称“sdf_agg”。您需要在所有节点上安装scikit learn或zip anaconda并使用--archive。您为每行调用的函数都需要加载这些模块。最佳解决方案是在每个节点上安装anaconda