Performance 在ApacheSpark中使用统计方法完成表时,如何提高性能?
我有一个包含10个字段和5000行的数据集。我想用Spark和Scala中的一些统计方法来完成这个数据集。如果一个字段由连续值组成,我用该字段的平均值填充该字段中的空单元格,如果它由离散值组成,我将最频繁的值放入该字段中。这是我的密码:Performance 在ApacheSpark中使用统计方法完成表时,如何提高性能?,performance,scala,apache-spark,Performance,Scala,Apache Spark,我有一个包含10个字段和5000行的数据集。我想用Spark和Scala中的一些统计方法来完成这个数据集。如果一个字段由连续值组成,我用该字段的平均值填充该字段中的空单元格,如果它由离散值组成,我将最频繁的值放入该字段中。这是我的密码: for(col <- cols){ val datacount = table.select(col).rdd.map(r => r(0)).filter(_ == null).count() if(datacount >
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))
}
}
}
for(colr(0)).filter(==null).count()
如果(数据计数>0)
{
if(continuous_lst contains col)//将数据的平均值设置为空值
{
var avg=table.select(mean(col)).first()(0).asInstanceOf[Double]
df=df.na.填充(平均值,序号(列))
}
else if(discrete_lst contains col)//将最频繁的分类值设置为空值
{
val group_df=df.groupBy(col.count)()
val sorted=group_df.orderBy(desc(“count”)).take(1)
val most_frequency=sorted.map(t=>t(0))
val most\u frequency=most\u frequency(0)。toString.toDouble.toInt
val type\uu=ctype.filter(t=>t.\u1==col)
val类型=类型映射(t=>t.\u2)
df=df.na.填充(最频繁,顺序(列))
}
}
}
问题是这段代码处理这些数据的速度非常慢。我使用spark submit
和executor memory 8G
参数。在将数据发送到此函数之前,我使用了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
列的列表。如果它们是
则想法相同,但需要进行一些调整李>字符串的列表
- 请注意,我使用了
和map
来计算列的最频繁值。在某些情况下,这可能比分组和聚合要好。(通过一次计算所有离散列的最频繁值,这里可能有改进的余地?)李>reduce
- 此外,我使用了
替换空值,而不是coalesce
。这也可能导致一些改进。(有关中的fill
功能的更多信息)李>合并
- 我现在无法测试,所以可能缺少一些我没有看到的东西
- 请注意,我使用了