PySpark-Spark数据帧数组与Python列表不同吗?
如果我有一个SparkPySpark-Spark数据帧数组与Python列表不同吗?,python,apache-spark,dataframe,pyspark,apache-spark-sql,Python,Apache Spark,Dataframe,Pyspark,Apache Spark Sql,如果我有一个SparkDataFrame包含arrays,我可以通过一个UDF在这些数组上使用Python列表方法吗?如何将Spark数据帧数组转换为Python列表 下面是一个示例,其中包含一些UDF。我不知道为什么使用max有效,但使用len无效。最后,我想用原始数组列中的采样值创建一个新列。这也得到了一个错误,期待两个参数,奖金点,如果你可以帮助 我有以下SparkDataFrame: from pyspark.sql.functions import udf from pyspark.s
DataFrame
包含arrays
,我可以通过一个UDF在这些数组上使用Python列表方法吗?如何将Spark数据帧
数组
转换为Python列表
下面是一个示例,其中包含一些UDF。我不知道为什么使用max有效,但使用len
无效。最后,我想用原始数组列中的采样值创建一个新列。这也得到了一个错误,期待两个参数,奖金点,如果你可以帮助
我有以下SparkDataFrame
:
from pyspark.sql.functions import udf
from pyspark.sql import Row
from pyspark.sql.types import StringType
from pyspark.sql.types import IntegerType
from pyspark.sql.types import ArrayType
import random
df = sc.parallelize([Row(name='Joe',scores=[1.0,2.0,3.0]),
Row(name='Mary', scores=[3.0]),
Row(name='Mary', scores=[4.0,7.1])]).toDF()
>>> df.show()
+----+---------------+
|name| scores|
+----+---------------+
| Joe|[1.0, 2.0, 3.0]|
|Mary| [3.0]|
|Mary| [4.0, 7.1]|
+----+---------------+
>>> df
DataFrame[name: string, scores: array<double>]
def sampleWithReplacement(listIn,samples):
tempList = array()
count=0
while (count<samples):
tempList.append(random.sample(listIn,1)[0])
count=count+1
return tempList
def maxArray(listIn):
return max(listIn)
def lenArray(listIn):
return len(listIn)
sampUDF=udf(sampleWithReplacement,ArrayType())
maxUDF=udf(maxArray,IntegerType())
lenUDF=udf(lenArray,IntegerType())
>>> df.withColumn("maxCol",maxUDF(df.scores)).show()
+----+---------------+------+
|name| scores|maxCol|
+----+---------------+------+
| Joe|[1.0, 2.0, 3.0]| null|
|Mary| [3.0]| null|
|Mary| [4.0, 7.1]| null|
+----+---------------+------+
>>> df.withColumn("maxCol",lenUDF(df.scores)).show()
+----+---------------+------+
|name| scores|maxCol|
+----+---------------+------+
| Joe|[1.0, 2.0, 3.0]| 3|
|Mary| [3.0]| 1|
|Mary| [4.0, 7.1]| 2|
+----+---------------+------+
从pyspark.sql.functions导入udf
从pyspark.sql导入行
从pyspark.sql.types导入StringType
从pyspark.sql.types导入IntegerType
从pyspark.sql.types导入ArrayType
随机输入
df=sc.parallelize([Row(name='Joe',scores=[1.0,2.0,3.0]),
行(name='Mary',分数=[3.0]),
行(name='Mary',分数=[4.0,7.1]))。toDF()
>>>df.show()
+----+---------------+
|姓名|分数|
+----+---------------+
|乔|[1.0,2.0,3.0]|
|玛丽|[3.0]|
|玛丽|[4.0,7.1]|
+----+---------------+
>>>df
DataFrame[名称:字符串,分数:数组]
def样本替换(列表,样本):
templast=array()
计数=0
while(count>>df.withColumn(“maxCol”,maxUDF(df.scores)).show()
+----+---------------+------+
|姓名|分数|马克斯科尔|
+----+---------------+------+
|乔|[1.0,2.0,3.0]|空|
|玛丽|[3.0]|零|
|玛丽|[4.0,7.1]|零|
+----+---------------+------+
>>>df.withColumn(“maxCol”,lenUDF(df.scores)).show()
+----+---------------+------+
|姓名|分数|马克斯科尔|
+----+---------------+------+
|乔|[1.0,2.0,3.0]| 3|
|玛丽|[3.0]| 1|
|玛丽|[4.0,7.1]| 2|
+----+---------------+------+
TL;DR当您有选择时,始终首选内置函数而不是udf
。要计算长度,请使用大小
(别名为长度)
方法:
from pyspark.sql.functions import length, size
df.withColumn("len", size("scores"))
对于小型阵列,您可以尝试
from pyspark.sql.functions import sort_array
df.withColumn("max", sort_array("scores", False)[0])
当然,对于大型收藏来说,这不是一个好的选择
Spark数据帧数组与Python列表不同吗
在内部,它们是不同的,因为有Scala对象。在udf
中访问时,会有简单的Python列表。那么,出了什么问题
让我们看一下类型。scores
列是array
。当转换为Python类型时,会产生一个列表[float]
。当调用max
时,输出上会出现一个float
但是,您将返回类型声明为IntegerType
。因为float
无法转换为整数精度损失结果未定义,因此您将得到NULL
。返回类型的正确选择是DoubleType
或FloatType
:
maxf = udf(lambda xs: max(xs), FloatType())
maxd = udf(lambda xs: max(xs), DoubleType())
(sc
.parallelize([("Joe", [1.0, 2.0, 3.0])])
.toDF(["name", "scores"])
.select("*", maxf("scores"), maxd("scores")))
结果:
+----+---------------+----------------+----------------+
|姓名|分数|(分数)|(分数)|
+----+---------------+----------------+----------------+
|乔|[1.0,2.0,3.0]| 3.0 | 3.0|
+----+---------------+----------------+----------------+
和模式:
根目录
|--名称:字符串(nullable=true)
|--分数:数组(可空=真)
||--元素:双精度(containsnall=true)
|--(分数):浮动(可空=真)
|--(分数):双倍(可为空=真)
您是否知道如何将这种数组转换为字符串,而不必像org.apache.spark.sql.catalyst.expressions那样离开字段。UnsafeArrayData@xxxx
?将其转换为包含以“,”分隔的元素的字符串应该是完美的。