[英]How can I improve the performance when completing a table with statistical methods in Apache-Spark?
我有一個包含10個字段和5000行的數據集。 我想用Scala中的Spark使用一些統計方法來完成此數據集。 如果該字段包含連續值,則用該字段的平均值填充該字段中的空單元格;如果該字段包含離散值,則將最頻繁使用的值放在該字段中。 這是我的代碼:
for(col <- cols){
val datacount = table.select(col).rdd.map(r => r(0)).filter(_ == null).count()
if(datacount > 0)
{
if (continuous_lst contains col) // put mean of data to null values
{
var avg = table.select(mean(col)).first()(0).asInstanceOf[Double]
df = df.na.fill(avg, Seq(col))
}
else if(discrete_lst contains col) // put most frequent categorical value to null values
{
val group_df = df.groupBy(col).count()
val sorted = group_df.orderBy(desc("count")).take(1)
val most_frequent = sorted.map(t => t(0))
val most_frequent_ = most_frequent(0).toString.toDouble.toInt
val type__ = ctype.filter(t => t._1 == col)
val type_ = type__.map(t => t._2)
df = df.na.fill(most_frequent_, Seq(col))
}
}
}
問題在於此代碼對該數據的處理非常緩慢。 我使用帶有executor memory 8G
參數的spark-submit
。 在將數據發送到此函數之前,我使用repartition(4)參數。
我應該處理更大的數據集。 那么如何加快此代碼的速度呢?
謝謝你的幫助。
這是一個建議:
import org.apache.spark.sql.funcitons._
def most_frequent(df: DataFrame, col: Column) = {
df.select(col).map { case Row(colVal) => (colVal, 1) }
.reduceByKey(_ + _)
.reduce({case ((val1, cnt1), (val2, cnt2)) => if (cnt1 > cnt2) (val1, cnt1) else (val2, cnt2)})._1
}
val new_continuous_cols = continuous_lst.map {
col => coalesce(col, mean(col)).as(col.toString)
}.toArray
val new_discrete_cols = discrete_lst.map {
col => coalesce(col, lit(most_frequent(table, col)).as(col.toString))
}.toArray
val all_new_cols = new_continuous_cols ++ new_discrete_cols
val newDF = table.select(all_new_cols: _*)
注意事項:
continuous_lst
和discrete_lst
是Column
列表。 如果它們是String
的列表,則想法是相同的,但需要進行一些調整。 map
和reduce
來計算列的最頻繁值。 在某些情況下,這可能比按分組進行匯總更好。 (也許通過一次計算所有離散列的最頻繁值在這里有改進的空間嗎?); coalesce
來代替,而不是空值, fill
。 這也可以帶來一些改善。 (有關scaladoc API中 coalesce
功能的更多信息);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.