首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala :同时对DF的所有列进行操作,并高效地为每个列创建一个用例类。

Scala :同时对DF的所有列进行操作,并高效地为每个列创建一个用例类。
EN

Stack Overflow用户
提问于 2022-08-11 12:56:08
回答 1查看 51关注 0票数 0

我面对的是一个有50,000多行和大约30-100列的DataFrame。数据是数字的,我希望为每一列“创建”一个具有以下属性的案例类:

  • max值
  • min值
  • 标准差

并将此数据结构保存到Map (col_name -> ColData case-class)中。

我将使用这个玩具示例来演示:

代码语言:javascript
复制
// The desired case-class & desired map:
case class ColData(name: String, min: Double, max: Double, std_dev: Double) {}
var columnsData: Map[String, ColData] = Map.empty


// The toy example:
val df = Seq(
         (1, 20, 30, 4),
         (2, 30, 40, 5),
         (3, 10, 30, 2)
       ).toDF("col0", "col1", "col2", "col3")

+----+----+----+----+
|col0|col1|col2|col3|
+----+----+----+----+
|   1|  20|  30|   4|
|   2|  30|  40|   5|
|   3|  10|  30|   2|
+----+----+----+----+

  1. 已经尝试过这种方法:

代码语言:javascript
复制
df.columns.foreach(c => {
    var (min_c, max_c, std_dev_c) = df.select(min(c), max(c), stddev(c)).as[(Double, Double, Double)].first()
    columnsData = columnsData + (c -> ColData(c, min_c, max_c, std_dev_c))
})

但我觉得它是缓慢和低效的。

  1. ,我想到了这个方法(应该迭代DF的次数更少),但无法判断它是否更好:

代码语言:javascript
复制
val min_cols = df.select(cols.map(min):_*).first().toSeq.toArray.map(_.toString.toDouble)
val max_cols = df.select(cols.map(max):_*).first().toSeq.toArray.map(_.toString.toDouble)
val std_cols = df.select(cols.map(stddev):_*).first().toSeq.toArray.map(_.toString.toDouble)

var seq = Seq(min_cols, max_cols, std_cols).transpose

df.columns.foreach(c => {
    var chosen = seq(df.columns.indexOf(c))
    var (min, max, std_dev) = (chosen(0), chosen(1), chosen(2))
    columnsData = columnsData + (c -> ColData(c, min, max, std_dev))
})

我的问题

efficient?

  • Should,我使用缓存/持久化(在此之前)和未持久化(之后)来提高性能,还有其他方法可以快速完成吗?该如何做呢?

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-11 13:25:00

第一种方法效率低下,因为您最终会多次遍历数据帧(与列的次数一样多)。第二条稍微好一点,但仍然有三条横线。

为什么不在一次扫描中做所有的事情呢?

代码语言:javascript
复制
   df.select(
      df.columns.flatMap { c => Seq(min(c), max(c), stddev(c)) } :_*
   ).first
    .toSeq
    .grouped(3)
    .zip(df.columns.iterator)
    .collect { case (Seq(min: Number, max: Number, stddev: Number), col) => 
       col -> ColData(col, min.doubleValue, max.doubleValue, stddev.doubleValue) 
    }.toMap
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73321031

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档