我面对的是一个有50,000多行和大约30-100列的DataFrame。数据是数字的,我希望为每一列“创建”一个具有以下属性的案例类:
并将此数据结构保存到Map (col_name -> ColData case-class)中。
我将使用这个玩具示例来演示:
// 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|
+----+----+----+----+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))
})但我觉得它是缓慢和低效的。
。
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?
谢谢!
发布于 2022-08-11 13:25:00
第一种方法效率低下,因为您最终会多次遍历数据帧(与列的次数一样多)。第二条稍微好一点,但仍然有三条横线。
为什么不在一次扫描中做所有的事情呢?
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)
}.toMaphttps://stackoverflow.com/questions/73321031
复制相似问题