Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 用Spark Dataframe中另一个类别列的平均值替换列的空值_Database_Scala_Apache Spark_Apache Spark Sql - Fatal编程技术网

Database 用Spark Dataframe中另一个类别列的平均值替换列的空值

Database 用Spark Dataframe中另一个类别列的平均值替换列的空值,database,scala,apache-spark,apache-spark-sql,Database,Scala,Apache Spark,Apache Spark Sql,我有一个这样的数据集 id category value 1 A NaN 2 B NaN 3 A 10.5 5 A 2.0 6 B 1.0 我想用它们各自类别的平均值填充NAN值。如下图所示 id category value 1 A 4.16 2 B 0.5

我有一个这样的数据集

id    category     value
1     A            NaN
2     B            NaN
3     A            10.5
5     A            2.0
6     B            1.0
我想用它们各自类别的平均值填充NAN值。如下图所示

id    category     value
1     A            4.16
2     B            0.5
3     A            10.5
5     A            2.0
6     B            1.0
我试着用分组法计算每个类别的第一个平均值

val df2 = dataFrame.groupBy(category).agg(mean(value)).rdd.map{
      case r:Row => (r.getAs[String](category),r.get(1))
    }.collect().toMap
    println(df2)
我得到了每个类别的地图及其各自的平均值。
输出:地图(A->4.16,B->0.5)
现在我尝试在Sparksql中使用updatequery来填充列,但spqrkSql似乎不支持updatequery。我试图在dataframe中填充空值,但失败了。 我能做什么?我们可以在熊猫身上做同样的事情,如图所示 但是如何使用spark dataframe呢?确实,您不能更新数据帧,但可以使用
select
join
等函数对其进行转换。在这种情况下,您可以将分组结果保留为
DataFrame
,并将其(在
category
列上)连接到原始数据帧,然后执行将用平均值替换
NaN
s的映射:

import org.apache.spark.sql.functions._
import spark.implicits._

// calculate mean per category:
val meanPerCategory = dataFrame.groupBy("category").agg(mean("value") as "mean")

// use join, select and "nanvl" function to replace NaNs with the mean values:
val result = dataFrame
  .join(meanPerCategory, "category")
  .select($"category", $"id", nanvl($"value", $"mean")).show()
实际上,您不能更新数据帧,但可以使用
select
join
等函数对其进行转换。在这种情况下,您可以将分组结果保留为
DataFrame
,并将其(在
category
列上)连接到原始数据帧,然后执行将用平均值替换
NaN
s的映射:

import org.apache.spark.sql.functions._
import spark.implicits._

// calculate mean per category:
val meanPerCategory = dataFrame.groupBy("category").agg(mean("value") as "mean")

// use join, select and "nanvl" function to replace NaNs with the mean values:
val result = dataFrame
  .join(meanPerCategory, "category")
  .select($"category", $"id", nanvl($"value", $"mean")).show()

最简单的解决方案是使用groupby和join:

 val df2 = df.filter(!(isnan($"value"))).groupBy("category").agg(avg($"value").as("avg"))
 df.join(df2, "category").withColumn("value", when(col("value").isNaN, $"avg").otherwise($"value")).drop("avg")

请注意,如果存在一个包含所有NaN的类别,它将从结果中删除

最简单的解决方案是使用groupby和join:

 val df2 = df.filter(!(isnan($"value"))).groupBy("category").agg(avg($"value").as("avg"))
 df.join(df2, "category").withColumn("value", when(col("value").isNaN, $"avg").otherwise($"value")).drop("avg")

请注意,如果有一个包含所有NaN的类别,它将从结果中删除

我偶然发现了同样的问题,并看到了这篇文章。但尝试了另一种解决方案,即使用窗口函数。以下代码在pyspark 2.4.3上进行了测试(Spark 1.4中提供了窗口功能)。我相信这是一个更干净的解决方案。 这篇文章很古老,但希望这个答案能对其他人有所帮助

from pyspark.sql import Window
from pyspark.sql.functions import *

df = spark.createDataFrame([(1,"A", None), (2,"B", None), (3,"A",10.5), (5,"A",2.0), (6,"B",1.0)], ['id', 'category', 'value'])

category_window = Window.partitionBy("category")
value_mean = mean("value0").over(category_window)

result = df\
  .withColumn("value0", coalesce("value", lit(0)))\
  .withColumn("value_mean", value_mean)\
  .withColumn("new_value", coalesce("value", "value_mean"))\
  .select("id", "category", "new_value")

result.show()
产出将如预期(有疑问):


我偶然发现了同样的问题,并看到了这篇文章。但尝试了另一种解决方案,即使用窗口函数。以下代码在pyspark 2.4.3上进行了测试(Spark 1.4中提供了窗口功能)。我相信这是一个更干净的解决方案。 这篇文章很古老,但希望这个答案能对其他人有所帮助

from pyspark.sql import Window
from pyspark.sql.functions import *

df = spark.createDataFrame([(1,"A", None), (2,"B", None), (3,"A",10.5), (5,"A",2.0), (6,"B",1.0)], ['id', 'category', 'value'])

category_window = Window.partitionBy("category")
value_mean = mean("value0").over(category_window)

result = df\
  .withColumn("value0", coalesce("value", lit(0)))\
  .withColumn("value_mean", value_mean)\
  .withColumn("new_value", coalesce("value", "value_mean"))\
  .select("id", "category", "new_value")

result.show()
产出将如预期(有疑问):


要替换空值,必须将
nanvl
函数替换为
coalesce
。或者同时处理这两个问题:
coalesce($“value”,nanvl($“value”,$“mean”)
很抱歉应该是
coalesce(nanvl($“value”,$“mean”),$“mean”)
Y导入spark.implicits.\uu无法导入。
spark
SparkSession
-如果名称不同,请替换名称;如果您没有SparkSession,您应该有一个
SQLContext
-导入该上下文的隐式(例如
import SQLContext.implicits.\u
如果它的名称为
SQLContext
,则使用coalesce($“value”、$“mean”)、$“mean”)对空值使用gr8。但是当我尝试coalesce(nanvl($“value”,“$“mean”),$“mean”)时,它不会填充空值来替换空值,您必须将
nanvl
函数替换为
coalesce
。或者同时处理这两个问题:
coalesce($“value”,nanvl($“value”,$“mean”)
很抱歉应该是
coalesce(nanvl($“value”,$“mean”),$“mean”)
Y导入spark.implicits.\uu无法导入。
spark
SparkSession
-如果名称不同,请替换名称;如果您没有SparkSession,您应该有一个
SQLContext
-导入该上下文的隐式(例如
import SQLContext.implicits.\u
如果它的名称为
SQLContext
,则使用coalesce($“value”、$“mean”)、$“mean”)对空值使用gr8。但是当我尝试coalesce(nanvl($“value”,“$“mean”),$“mean”)时,它并没有填充空值,具体在哪里?还要执行df.printSchema()。我的假设是价值是双倍的…具体在哪里?还要执行df.printSchema()。我的假设是价值是两倍。。。