pyspark合并两个dataframe_PySpark中Pandas UDF的介绍

如何快速的在PySpark中跑原始的python代码

Introducing Pandas UDF for PySpark - The Databricks Blog​databricks.com
  1. Scalar Pandas UDFs(标量的pandas UDF函数)

在pyspark中假如要给一个dataframe的某一列执行+1的操作,以前的操作方式是

from pyspark.sql.functions import udf
#Use udf to define a row-at-a-time udf
@udf('double')
# Input/output are both a single double value
def plus_one(v):
    return v + 1
df.withColumn('v2',plus_one(df.v))

使用Pandas UDFs:

from pyspark.sql.functions import pandas_udf, PandasUDFType
# Use pandas_udf to define a Pandas UDF
@pandas_udf('double', PandasUDFType.SCALAR)
# Input/output are both a pandas.Series of doubles
def pandas_plus_one(v):
    return v+1
df.withColumn('v2',pandas_plus_one(df.v))在

在第一种方法中 row-at-a-time版本中,udf函数输入的是一个double类型的'v',结果也是double类型的'v+1',在pandas udf中,输入的是pandas.Series类型的'v',输出也是,所以pandas类型的速度是比第一种快很多的;

2. Cumulative Probability

下面这个例子是用户pandas UDF更具实战性的例子:使用scipy去计算一个值的累计正太分布概率值

import pandas as pd
from scipy import stats

@pandas_udf('double'):
def cdf(v):
    return pd.Series(stats.norm.cdf(v))

df.withColumn('cumulative_probability',cdf(df.v))

stats.norm.cdf 可以使用在一个标量或者是一个pandas.Series上面,然后上面的这个例子是用row-at-a-time UDFs写的

3. Grouped Map Pandas UDFs

python的使用者都非常熟悉 split-apply-combine的数据分析的模式,Grouped Map Pandas UDFs也可以在这个场景中使用

Grouped map Pandas UDFs首先将一个Spark DataFrame根据groupby的操作分成多个组,然后应用user-defined function(pandas.DataFrame -> pandas.DataFrame)到每个组,然后将这些结果合并成一个新的Spark DataFrame.

Grouped map Pandas UDFs和在标量上使用的pandas udf 使用相同的函数操作,但是他们也有一些不同点

  • Input of the user-defined function:
    • Scalar : pandas.Series
    • Grouped map : pandas.DataFrame
  • Output of the user-defined function
    • Scalar : pandas.Series
    • Grouped map : pandas.DataFrame
  • Grouping semantics:
    • Scalar : no grouping semantics
    • Grouped map : defined by "groupby" clause
  • Output size:
    • Scalar : same as input size
    • Grouped map : any size
  • Return types in the function decorator:
    • Scalar : a DataType that specifies the type of the returned pandas.Series
    • Grouped map : a StructType that specifies each column name and type of the returned pandas.DataFrame

下面将使用两个例子去演示grouped map Pandas UDFs的用法

Subtract Mean

这个例子展示了一个简单的grouped map Pandas UDFs的用法,减去每个组的组内均值

@pandas_udf(df.schema,PandasUDFType.GROUPED_MAP)
##Input/output are both a pandas.DataFrame
def subtract_mean(pdf):
    return pdf.assign(v = pdf.v - pdf.v.mean()

df.groupby('id').apply(subtract_mean)

在这个例子中,我们在每个组的v列上面减去了v的均值,分组的语法是根据groupby函数实现的,然后每个输入UDF函数的pandas.DataFrame有同样的id值,输入的schema和输出的schema在这个udf是一样的,所以直接用df.schema作为参数输入到pandas_udf里面

Grouped map Pandas UDFs 也被叫做standalone Python functions,然后可以用下面的方式来进行debug

sample = df.filter(id == 1).toPandas()
# Run as a standalone function on a pandas.DataFrame and verify result
subtract_mean.func(sample)
# Now run with Spark
df.groupby('id').apply(substract_mean)

Ordinary Least Squares Linear Regression

下面的例子展示怎么在每个组上面去拟合一个OLS 线性回归,对于每个组,我们计算beta b = (b1,b2) for X = (x1,x2) 根据统计模型 Y = bX + c

import statsmodels.api as sm
## df has four columns : id ,y ,x1, x2

group_column = 'id'
y_column = 'y'
x_columns = ['x1','x2']
schema = df.select(group_column,*x_columns).schema

@pandas_udf(schema, PandasUDFType.GROUPED_MAP)
# Input/output are both a pandas.DataFrame
def ols(pdf):
    group_key = pdf[group_column].iloc[0]
    y = pdf[y_column]
    X = pdf[x_columns]
    X = sm.add_constant(X)
    model = sm.OLS(y,X).fit()
    return pd.DataFrame([[group_key] + [model.params[i] for i in   x_columns]], columns=[group_column] + x_columns)
beta = df.groupby(group_column).apply(ols)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值