Pyspark Pypark填充缺失/分组平均值错误

Pyspark Pypark填充缺失/分组平均值错误,pyspark,apache-spark-sql,databricks,Pyspark,Apache Spark Sql,Databricks,我有一个Spark数据帧,其中一个缺失,另一个值错误 from pyspark.sql import Row from pyspark.sql.types import StringType, DoubleType, StructType, StructField # fruit sales data data = [Row(id='01', fruit='Apple', qty=5.0), Row(id='02', fruit='Apple', qty=1.0),

我有一个Spark数据帧,其中一个缺失,另一个值错误

from pyspark.sql import Row
from pyspark.sql.types import StringType, DoubleType, StructType, StructField
# fruit sales data
data = [Row(id='01', fruit='Apple', qty=5.0),
        Row(id='02', fruit='Apple', qty=1.0),
        Row(id='03', fruit='Apple', qty=None),
        Row(id='04', fruit='Pear', qty=6.0),
        Row(id='05', fruit='Pear', qty=2.0),
        Row(id='06', fruit='Mango', qty=6.0),
        Row(id='07', fruit='Mango', qty=-4.0),
        Row(id='08', fruit='Mango', qty=2.0)]
# create dataframe
df = spark.createDataFrame(data)
df.show()
+-----+---+----+
|fruit| id| qty|
+-----+---+----+
|Apple| 01| 5.0|
|Apple| 02| 1.0|
|Apple| 03|null|
| Pear| 04| 6.0|
| Pear| 05| 2.0|
|Mango| 06| 6.0|
|Mango| 07|-4.0|
|Mango| 08| 2.0|
+-----+---+----+
按整列平均值进行填充很简单。但是我怎样才能做分组平均呢?为了举例说明,我希望第3行中的
null
Apple
替换为
mean(quaty)
——在本例中为(5+1)/2=3。类似地,
-4.0
是第7行中的错误值(无负数量),我想用(6+2)/2=4替换

在纯Python中,我会这样做:

def replace_with_grouped_mean(df, value, column, to_groupby):
    invalid_mask = (df[column] == value)
    # get the mean without the invalid value
    means_by_group = (df[~invalid_mask].groupby(to_groupby)[column].mean())
    # get an array of the means for all of the data
    means_array = means_by_group[df[to_groupby].values].values
    # assign the invalid values to means
    df.loc[invalid_mask, column] = means_array[invalid_mask]
    return df
并最终做到:

x = replace_with_grouped_mean(df=df, value=-4, column='qty', to_groupby='fruit')

然而,我不太确定如何在PySpark中实现这一点。感谢您的帮助/指点

注意点:当我们执行分组方式时,将忽略
Null
的行。如果我们有3行,其中一行的值为
Null
,那么平均值应除以2,而不是3,因为第3行的值为
Null
。这里的关键是使用函数

from pyspark.sql.functions import avg, col, when
from pyspark.sql.window import Window
w = Window().partitionBy('fruit')

#Replace negative values of 'qty' with Null, as we don't want to consider them while averaging.
df = df.withColumn('qty',when(col('qty')<0,None).otherwise(col('qty')))
df = df.withColumn('qty',when(col('qty').isNull(),avg(col('qty')).over(w)).otherwise(col('qty')))
df.show()
+-----+---+---+
|fruit| id|qty|
+-----+---+---+
| Pear| 04|6.0|
| Pear| 05|2.0|
|Mango| 06|6.0|
|Mango| 07|4.0|
|Mango| 08|2.0|
|Apple| 01|5.0|
|Apple| 02|1.0|
|Apple| 03|3.0|
+-----+---+---+
从pyspark.sql.functions导入平均值,col,当
从pyspark.sql.window导入窗口
w=Window().partitionBy('fruit')
用“NULL”代替“QTY”的负值,因为我们不想在平均时考虑它们。

df=df.withColumn('qty',when(col('qty')谢谢,在这里我想我需要更详细的东西。我需要更深入地了解
窗口()
功能。许多人可能会使用聚合
.agg()
mean
存储在另一个
dataframe
中,然后
join
两个
dataframe
,由于无序排列,这隐含着冗长和低效。
Windows()
更加高效和简洁。如果使用mode进行分类特征,如何进行插补?