将空值替换为pyspark中的中值

时间:2018-08-03 21:49:09

标签: replace null pyspark median

如何在数据集df下方的年龄和身高列中用中位数替换空值。

df = spark.createDataFrame([(1, 'John', 1.79, 28,'M', 'Doctor'),
                        (2, 'Steve', 1.78, 45,'M', None),
                        (3, 'Emma', 1.75, None, None, None),
                        (4, 'Ashley',1.6, 33,'F', 'Analyst'),
                        (5, 'Olivia', 1.8, 54,'F', 'Teacher'),
                        (6, 'Hannah', 1.82, None, 'F', None),
                        (7, 'William',None, 42,'M', 'Engineer'),
                        (None,None,None,None,None,None),
                        (8,'Ethan',1.55,38,'M','Doctor'),
                        (9,'Hannah',1.65,None,'F','Doctor'),
                       (10,'Xavier',1.64,43,None,'Doctor')]
                       , ['Id', 'Name', 'Height', 'Age', 'Gender', 'Profession'])

在帖子Replace missing values with mean - Spark Dataframe中,我使用了给定的功能 从pyspark.ml.feature导入Imputer

imputer = Imputer(
inputCols=df.columns, 
outputCols=["{}_imputed".format(c) for c in df.columns])

imputer.fit(df).transform(df)

这使我出错。

IllegalArgumentException:'要求失败:列ID的类型必须等于以下类型之一:[DoubleType,FloatType],但实际上是LongType类型。'

所以请帮忙。 谢谢

2 个答案:

答案 0 :(得分:0)

我会对更优雅的解决方案感兴趣,但我从数字中分别归类了类别。为了估算类别,我得到了最常见的值,并使用whenotherwise函数用它填补了空白:

import pyspark.sql.functions as F
for col_name in ['Name', 'Gender', 'Profession']:
    common = df.dropna().groupBy(col_name).agg(F.count("*")).orderBy('count(1)', ascending=False).first()[col_name]
    df = df.withColumn(col_name, F.when(F.isnull(col_name), common).otherwise(df[col_name]))

要在运行插补行之前对数字进行插补,我只需将Age和Id列转换为double即可避免数字字段出现问题,并将插补器限制为数字列。

from pyspark.ml.feature import Imputer
df = df.withColumn("Age", df['Age'].cast('double')).withColumn('Id', df['Id'].cast('double'))
imputer = Imputer(
inputCols=['Id', 'Height', 'Age'],
outputCols=['Id', 'Height', 'Age'])
imputer.fit(df).transform(df)

答案 1 :(得分:0)

可能是最初的转换错误(我有一些需要浮点数的字符串)。要将所有列转换为浮点数,请执行以下操作:

from pyspark.sql.functions import col
df = df.select(*(col(c).cast("float").alias(c) for c in df.columns))

那么您应该可以估算。注意:我将策略设置为中位数而不是均值。

from pyspark.ml.feature import Imputer

imputer = Imputer(
    inputCols=df.columns, 
    outputCols=["{}_imputed".format(c) for c in df.columns]
    ).setStrategy("median")

# Add imputation cols to df
df = imputer.fit(df).transform(df)