Python PySpark按浮点数划分数据帧数组
我有一个数据帧Python PySpark按浮点数划分数据帧数组,python,apache-spark,dataframe,pyspark,Python,Apache Spark,Dataframe,Pyspark,我有一个数据帧dfDistance。样本: DataIndex CenterIndex distances array 65 0 115.63 [115.63,115.01,114.14] 65 1 115.01 [115.63,115.01,114.14] 65 2 114.14 [115.63,
dfDistance
。样本:
DataIndex CenterIndex distances array
65 0 115.63 [115.63,115.01,114.14]
65 1 115.01 [115.63,115.01,114.14]
65 2 114.14 [115.63,115.01,114.14]
我想创建一个新列,该列等于数组中的值按元素除以距离中的相应值。我尝试了以下方法:
temp = dfDistance.select("DataIndex", "CenterIndex", "distances", (np.divide(dfDistance.array, dfDistance.distances)))
它给了我这个错误:
"cannot resolve '(`array` / `distances`)' due to data type mismatch: differing types in '(`array` / `distances`)' (array<float> and float).
它工作并给出了这个结果:[1.0.99463807 0.98711407]
。为什么它在PySpark情况下不工作,我应该如何修改代码使其工作?它在外部工作的原因是您使用的是本机Python类型(list
和float
)。另一方面,在PySpark中,您使用的是列对象,它们的行为方式不同
无论如何,我认为最简单的方法就是使用UDF。我试着浏览PySpark文档,但奇怪的是,找不到任何直接作用于数组的方法。例如:
from pyspark.sql import functions as F
from pyspark.sql.types import ArrayType, DoubleType
def normalise(a, dist):
return [element / dist for element in a]
dfDistance.withColumn('normalised', F.udf(normalise, ArrayType(DoubleType()))(df['array'], df['distances']))
另一方面,如果需要归一化和,可以使用分解:
distance_sum = dfDistance.select('array', F.explode('array')).groupby('array').sum()
dfDistance.join(distance_sum, on='array', how='left').withColumn('normalised_sum', F.col('sum(col)') / F.col('distances')).drop('sum(col)')
你又救了我,谢谢你!正如您所看到的,我是Python/Spark新手,因此,请您解释一下,为什么在udf中编写ArrayType(DoubleType())?我不明白这个部分。@daibriF.udf
接受两个参数:函数及其返回类型。默认情况下,所有UDF都返回字符串(StringType
)。但是,我们需要一个双精度数组,所以我们需要指定ArrayType(DoubleType)
。因此,如果我想返回sum作为结果而不是array,那么我应该有F.udf(normalise,DoubleType())(df['array'],df['distance'])?函数本身看起来像:返回和([element/dist for element in a])?@daibri-Yup,你可以这样做。不过,可能有一种更有效的基于分解的方法。
distance_sum = dfDistance.select('array', F.explode('array')).groupby('array').sum()
dfDistance.join(distance_sum, on='array', how='left').withColumn('normalised_sum', F.col('sum(col)') / F.col('distances')).drop('sum(col)')