Apache spark 如何计算Spark数据帧中的行中值

Apache spark 如何计算Spark数据帧中的行中值,apache-spark,pyspark,apache-spark-sql,Apache Spark,Pyspark,Apache Spark Sql,我有以下格式的Spark数据帧 df=spark.createDataFrame([(1,2,3),(1,4100),(20,30,50)],['a','b','c']) df.show() 输入: df = spark.createDataFrame([(1,2,3),(100,1,10),(30,20,50)],['a','b','c']) import numpy as np from pyspark.sql.functions import udf from pyspark.sql.

我有以下格式的Spark数据帧

df=spark.createDataFrame([(1,2,3),(1,4100),(20,30,50)],['a','b','c'])
df.show()
输入:

df = spark.createDataFrame([(1,2,3),(100,1,10),(30,20,50)],['a','b','c'])

import numpy as np
from pyspark.sql.functions import udf
from pyspark.sql.types import DoubleType

def my_median(*args):
    return float(np.median(list(args)))

udf_median = udf(my_median, DoubleType())

df.withColumn('median', udf_median('a','b','c')).show()

我想添加一个新的列“median”,作为“a”、“b”、“c”列的中位数。如何在PySpark中实现这一点

预期输出:

df = spark.createDataFrame([(1,2,3),(100,1,10),(30,20,50)],['a','b','c'])

import numpy as np
from pyspark.sql.functions import udf
from pyspark.sql.types import DoubleType

def my_median(*args):
    return float(np.median(list(args)))

udf_median = udf(my_median, DoubleType())

df.withColumn('median', udf_median('a','b','c')).show()


我正在使用Spark 2.3.1使用
udf
定义一个用户定义的函数,然后使用
withColumn
将指定的列添加到数据框中:

from numpy import median
from pyspark.sql.functions import col, udf
from pyspark.sql.types import IntegerType

def my_median(a, b, c):
    return int(median([int(a),int(b),int(c)]))

udf_median = udf(my_median, IntegerType())

df_t = df.withColumn('median', udf_median(df['a'], df['b'], df['c']))
df_t.show()

没有内置函数,但您可以使用现有组件轻松编写一个

Spark<2.4中的
#用sort_数组替换array_sort
#感谢@RaphaelRoth指出这一点
从pyspark.sql.functions导入数组、数组\排序、楼层、列、大小
从pyspark.sql导入列
def百分位数(p,*args):
def列(c):
如果存在(c列):
返回c
elif isinstance(c,str):
返回列(c)
其他:
raise TypeError(“args应该str或Column,got{}.”格式(type(c)))
xs=array_sort(数组(*[col_ux)表示参数中的x]))
n=尺寸(xs)
h=(n-1)*p
i=地板(h)铸件(“int”)
x0,x1=xs[i],xs[i+1]
返回x0+(h-i)*(x1-x0)
用法示例:

df.withColumn(“中值”,百分位数(0.5,*df.columns)).show()
+---+---+---+------+
|a | b | c |中位数|
+---+---+---+------+
|  1|  2|  3|   2.0|
|  1|  4|100|   4.0|
| 20| 30| 50|  30.0|
+---+---+---+------+
同样的事情也可以在Scala中完成:

import org.apache.spark.sql.functions_
导入org.apache.spark.sql.Column
def百分位数(p:Double,args:Column*)={
val xs=array_sort(数组(args:*))
val n=大小(xs)
val h=(n-1)*p
val i=地板(h)铸件(“内部”)
val(x0,x1)=(xs(i),xs(i+1))
x0+(h-i)*(x1-x0)
}
val df=Seq((1,2,3),(1,4100),(20,30,50)).toDF(“a”,“b”,“c”)
df.带列(“中位数”,百分位数(0.5,$“a”,“$“b”,“$“c”))。显示
+---+---+---+------+
|a | b | c |中位数|
+---+---+---+------+
|  1|  2|  3|   2.0|
|  1|  4|100|   4.0|
| 20| 30| 50|  30.0|
+---+---+---+------+
<>在<强> Python 中,您也可以考虑向量化的UDF——一般来说,它可能比内置函数慢,但优于非矢量化<代码> UDF:

从pyspark.sql.functions导入pandas\u udf,PandasUDFType
从pyspark.sql.types导入DoubleType
作为pd进口熊猫
将numpy作为np导入
def/U百分位数(p=0.5):

assert 0我稍微修改了OmG的答案,使UDF对于“n”个列的数量而不是仅仅3个列是动态的

代码:

df = spark.createDataFrame([(1,2,3),(100,1,10),(30,20,50)],['a','b','c'])

import numpy as np
from pyspark.sql.functions import udf
from pyspark.sql.types import DoubleType

def my_median(*args):
    return float(np.median(list(args)))

udf_median = udf(my_median, DoubleType())

df.withColumn('median', udf_median('a','b','c')).show()
输出:

df = spark.createDataFrame([(1,2,3),(100,1,10),(30,20,50)],['a','b','c'])

import numpy as np
from pyspark.sql.functions import udf
from pyspark.sql.types import DoubleType

def my_median(*args):
    return float(np.median(list(args)))

udf_median = udf(my_median, DoubleType())

df.withColumn('median', udf_median('a','b','c')).show()

@RaphaelRoth别担心。仅供参考,我添加了Scala等效物。谢谢
array\u sort
只是在spark 2.4中添加的,
sort\u array
应该也能工作吧