[英]Calculate the standard deviation of grouped data in a Spark DataFrame
我有從csv獲取並轉換為DataFrame的用戶日志,以便利用SparkSQL查詢功能。 一個用戶每小時會創建多個條目,我想為每個用戶收集一些基本統計信息; 實際上,它只是用戶實例的數量,平均值以及眾多列的標准偏差。 通過使用groupBy($“ user”)和帶有SparkSQL函數的聚合器來計數和平均,我能夠快速獲取均值和計數信息:
val meanData = selectedData.groupBy($"user").agg(count($"logOn"),
avg($"transaction"), avg($"submit"), avg($"submitsPerHour"), avg($"replies"),
avg($"repliesPerHour"), avg($"duration"))
但是,我似乎找不到一種同樣優雅的方法來計算標准偏差。 到目前為止,我只能通過映射字符串,雙對並使用StatCounter()。stdev實用工具來計算它:
val stdevduration = duration.groupByKey().mapValues(value =>
org.apache.spark.util.StatCounter(value).stdev)
但是,這將返回一個RDD,我想嘗試將其全部保留在DataFrame中,以便對返回的數據進行進一步的查詢。
Spark 1.6+
您可以使用stddev_pop
計算總體標准偏差,並使用stddev
/ stddev_samp
計算無偏樣本標准偏差:
import org.apache.spark.sql.functions.{stddev_samp, stddev_pop}
selectedData.groupBy($"user").agg(stdev_pop($"duration"))
Spark 1.5及以下 ( 原始答案 ):
不是那么漂亮和有偏見(與describe
返回的值相同),而是使用公式:
您可以執行以下操作:
import org.apache.spark.sql.functions.sqrt
selectedData
.groupBy($"user")
.agg((sqrt(
avg($"duration" * $"duration") -
avg($"duration") * avg($"duration")
)).alias("duration_sd"))
您當然可以創建一個減少混亂的函數:
import org.apache.spark.sql.Column
def mySd(col: Column): Column = {
sqrt(avg(col * col) - avg(col) * avg(col))
}
df.groupBy($"user").agg(mySd($"duration").alias("duration_sd"))
也可以使用Hive UDF:
df.registerTempTable("df")
sqlContext.sql("""SELECT user, stddev(duration)
FROM df
GROUP BY user""")
接受的代碼有錯別字(如MRez指出的),因此無法編譯。 以下代碼段可以正常工作並經過測試。
對於Spark 2.0+ :
import org.apache.spark.sql.functions._
val _avg_std = df.groupBy("user").agg(
avg(col("duration").alias("avg")),
stddev(col("duration").alias("stdev")),
stddev_pop(col("duration").alias("stdev_pop")),
stddev_samp(col("duration").alias("stdev_samp"))
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.