关于数据帧的Spark MinMaxScaler

时间:2018-04-26 12:32:38

标签: python apache-spark normalization

假设我有以下数据框

+---+-----+-------+
|day| time| result|                 
+---+-----+-------+
|  1| 6   |  0.5  |
|  1| 7   |  10.2 |
|  1| 8   |   5.7 |
|  2| 6   |  11.0 |
|  2| 10  |  22.3 |
+---+-----+-------+

我喜欢将每天的结果标准化,同时保留属于每个结果的时间。我喜欢使用MinMaxScaler我假设我已经将值投射到每天的密集向量,但我如何保留时间值?

1 个答案:

答案 0 :(得分:3)

  

我喜欢规范化结果(...)我喜欢使用MinMaxScaler

这两个要求是互斥的。 MinMaxScaler不能用于对群组进行操作。您可以使用窗口函数

from pyspark.sql.functions import min, max, col
from pyspark.sql.window import Window

df = spark.createDataFrame(
    [(1, 6, 0.5), (1, 7, 10.2), (1, 8, 5.7), (2, 6, 11.0), (2, 10, 22.3)], 
    ("day", "time", "result"))

w = Window.partitionBy("day")

scaled_result = (col("result") - min("result").over(w)) / (max("result").over(w) - min("result").over(w))

df.withColumn("scaled_result", scaled_result).show()
# +---+----+------+------------------+                                            
# |day|time|result|     scaled_result|
# +---+----+------+------------------+
# |  1|   6|   0.5|               0.0|
# |  1|   7|  10.2|               1.0|
# |  1|   8|   5.7|0.5360824742268042|
# |  2|   6|  11.0|               0.0|
# |  2|  10|  22.3|               1.0|
# +---+----+------+------------------+

或分组,汇总和加入:

minmax_result = df.groupBy("day").agg(min("result").alias("min_result"), max("result").alias("max_result"))

minmax_result.join(df, ["day"]).select(
    "day", "time", "result", 
     ((col("result") - col("min_result")) / (col("max_result") - col("min_result"))).alias("scaled_result")
).show()
# +---+----+------+------------------+                                            
# |day|time|result|     scaled_result|
# +---+----+------+------------------+
# |  1|   6|   0.5|               0.0|
# |  1|   7|  10.2|               1.0|
# |  1|   8|   5.7|0.5360824742268042|
# |  2|   6|  11.0|               0.0|
# |  2|  10|  22.3|               1.0|
# +---+----+------+------------------+