【问题标题】:Forward filling in .NET for Spark前向填充 .NET for Spark
【发布时间】:2021-06-20 04:11:32
【问题描述】:

我正在查看 .NET (C#) 中 Spark DataFrame 的窗口函数。

我有一个 DataFrame df,其中包含 Year、Month、Day、Hour、Minute、ID、Type 和 Value 列:

| 2021 |  3  |  4  |  8  |  9  |  87  |  Type1  |  380.5  |

| 2021 |  3  |  4  |  8  |  10 | null |   null  |   null  |

| 2021 |  3  |  4  |  8  |  11 | null |   null  |   null  |

| 2021 |  3  |  4  |  8  |  12 | null |   null  |   null  |

| 2021 |  3  |  4  |  8  |  13 |  87  |  Type1  |    0.0  |

| 2021 |  3  |  4  |  8  |  14 |  87  |  Type1  |    0.0  |

我想根据年、月、日、小时、分钟用上一行的值填充空行(null),如下所示:

| 2021 |  3  |  4  |  8  |  9  |  87  |  Type1  |  380.5  |

| 2021 |  3  |  4  |  8  |  10 |  87  |  Type1  |  380.5  |

| 2021 |  3  |  4  |  8  |  11 |  87  |  Type1  |  380.5  |

| 2021 |  3  |  4  |  8  |  12 |  87  |  Type1  |  380.5  |

| 2021 |  3  |  4  |  8  |  13 |  87  |  Type1  |    0.0  |

| 2021 |  3  |  4  |  8  |  14 |  87  |  Type1  |    0.0  |

到目前为止,我在 scala 中找到了使用 Windows 和 Lag 函数的解决方案,但我不确定如何在 C# 中执行此操作。在 scala 中,窗口将被定义为:

val window = Window.orderBy("Year", "Month", "Day", "Hour", "Minute")

我想添加一个 newValue 列使用

var filledDataFrame = df.WithColumn("newValue", Functions.When(df["Value"].IsNull(), Functions.Lag(df["Value"], 1).Over(window)).Otherwise(df["Value"])

如何在 .NET 中为 Spark 定义一个窗口并使用 Lag 函数向前填充空值?

【问题讨论】:

    标签: c# dataframe apache-spark window-functions .net-spark


    【解决方案1】:

    要在 .NET for Apache Spark 中使用 Lag 和 Window,您已经非常接近并且需要:

    var spark = SparkSession.Builder().GetOrCreate();
    var df = spark.CreateDataFrame(new List<GenericRow>()
    {
        new GenericRow(new object[] {2021, 3, 4, 8, 9, 87, "Type1", 380.5}),
        new GenericRow(new object[] {2021, 3, 4, 8, 10, null, null, null}),
        new GenericRow(new object[] {2021, 3, 4, 8, 11, null, null, null}),
        new GenericRow(new object[] {2021, 3, 4, 8, 12, null, null, null}),
        new GenericRow(new object[] {2021, 3, 4, 8, 13, 87, "Type1", 0.0}),
        new GenericRow(new object[] {2021, 3, 4, 8, 14, 87, "Type1", 0.0})
    }, new StructType(new List<StructField>()
    {
        new StructField("Year", new IntegerType()),
        new StructField("Month", new IntegerType()),
        new StructField("Day", new IntegerType()),
        new StructField("Hour", new IntegerType()),
        new StructField("Minute", new IntegerType()),
        new StructField("ID", new IntegerType()),
        new StructField("Type", new StringType()),
        new StructField("Value", new DoubleType()),
    
    }));
    
    var window = Window.OrderBy("Year", "Month", "Day", "Hour", "Minute");
    var filledDataFrame = df.WithColumn("newValue",
        Functions.When(df["Value"].IsNull(),
                Functions.Lag(df["Value"], 1).Over(window))
            .Otherwise(df["Value"]));
    
    filledDataFrame.Show(1000, 10000);
    

    这将导致:

    +----+-----+---+----+------+----+-----+-----+--------+
    |Year|Month|Day|Hour|Minute|  ID| Type|Value|newValue|
    +----+-----+---+----+------+----+-----+-----+--------+
    |2021|    3|  4|   8|     9|  87|Type1|380.5|   380.5|
    |2021|    3|  4|   8|    10|null| null| null|   380.5|
    |2021|    3|  4|   8|    11|null| null| null|    null|
    |2021|    3|  4|   8|    12|null| null| null|    null|
    |2021|    3|  4|   8|    13|  87|Type1|  0.0|     0.0|
    |2021|    3|  4|   8|    14|  87|Type1|  0.0|     0.0|
    +----+-----+---+----+------+----+-----+-----+--------+
    

    但您可能想要Last 而不是Lag,因为您可以跳过空值:

    var spark = SparkSession.Builder().GetOrCreate();
    var df = spark.CreateDataFrame(new List<GenericRow>()
    {
        new GenericRow(new object[] {2021, 3, 4, 8, 9, 87, "Type1", 380.5}),
        new GenericRow(new object[] {2021, 3, 4, 8, 10, null, null, null}),
        new GenericRow(new object[] {2021, 3, 4, 8, 11, null, null, null}),
        new GenericRow(new object[] {2021, 3, 4, 8, 12, null, null, null}),
        new GenericRow(new object[] {2021, 3, 4, 8, 13, 87, "Type1", 0.0}),
        new GenericRow(new object[] {2021, 3, 4, 8, 14, 87, "Type1", 0.0})
    }, new StructType(new List<StructField>()
    {
        new StructField("Year", new IntegerType()),
        new StructField("Month", new IntegerType()),
        new StructField("Day", new IntegerType()),
        new StructField("Hour", new IntegerType()),
        new StructField("Minute", new IntegerType()),
        new StructField("ID", new IntegerType()),
        new StructField("Type", new StringType()),
        new StructField("Value", new DoubleType()),
    
    }));
    
    var window = Window.OrderBy("Year", "Month", "Day", "Hour", "Minute");
    var filledDataFrame = df.WithColumn("newValue",
        Functions.When(df["Value"].IsNull(),
            Functions.Last(df["Value"], true).Over(window))
            .Otherwise(df["Value"]));
    
    filledDataFrame.Show(1000, 10000);
    
    

    结果:

    +----+-----+---+----+------+----+-----+-----+--------+
    |Year|Month|Day|Hour|Minute|  ID| Type|Value|newValue|
    +----+-----+---+----+------+----+-----+-----+--------+
    |2021|    3|  4|   8|     9|  87|Type1|380.5|   380.5|
    |2021|    3|  4|   8|    10|null| null| null|   380.5|
    |2021|    3|  4|   8|    11|null| null| null|   380.5|
    |2021|    3|  4|   8|    12|null| null| null|   380.5|
    |2021|    3|  4|   8|    13|  87|Type1|  0.0|     0.0|
    |2021|    3|  4|   8|    14|  87|Type1|  0.0|     0.0|
    +----+-----+---+----+------+----+-----+-----+--------+
    
    

    希望对你有帮助!

    编辑

    (完成这项工作所需的 using 语句)

    using System;
    using System.Collections.Generic;
    using Microsoft.Spark.Sql;
    using Microsoft.Spark.Sql.Expressions;
    using Microsoft.Spark.Sql.Types;
    

    【讨论】:

    • 您好,埃德,感谢您的回答。我尝试了您的代码,即使我指定了using Microsoft.Spark.Sql.Expressions,它一开始也不起作用。我将window 定义为:var window = Microsoft.Spark.Sql.Expressions.Window.OrderBy("Year", "Month", "Day", "Hour", "Minute");,它现在完美运行!谢谢!
    • 啊,抱歉,我没有在顶部包含 using 语句!
    猜你喜欢
    • 2016-11-03
    • 2016-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-03
    • 1970-01-01
    相关资源
    最近更新 更多