【问题标题】:Data analysis on a subset with scala使用 scala 对子集进行数据分析
【发布时间】:2017-09-21 02:18:21
【问题描述】:

我刚开始学习 Scala 并探索它可以做事的方式,现在我正在尝试学习实现一些更复杂的数据分析。

我有一个加载到程序中的文本文件中不同国家不同城市的天气数据。到目前为止,我已经弄清楚了如何计算简单的事情,例如一个国家/地区每天的平均温度,或者整个文件中按国家/地区分组的每个城市的平均温度,使用 Maps/Mapvalues 将键绑定到我正在寻找的值为。

现在希望能够指定一个时间窗口(例如一周),然后从那里按国家/地区分组,计算出该时间窗口内每个城市的平均温度等信息。为简单起见,我将日期设为简单的 INT,而不是使用 MM/DD/YY 格式。

在另一种语言中,我可能会使用循环来执行此操作,但我不太确定执行此操作的最佳“Scala”方式。起初我以为可能是“滑动”或“分组”,但发现这会完全拆分列表,因此我无法指定任意日期来计算一周。我已经为我的方法提供了示例代码,该方法计算了整个时间段内每个城市的平均温度

def citytempaverages(): Map[String, Map[String, Double]] = {
  weatherpatterns.groupBy(_.country)
    .mapValues(_.groupBy(_.city)
  .mapValues(cityavg => cityavg.map(_.temperature).sum    /cityavg.length))

使用地图来解决这个新问题是否仍然有意义,或者集合 API 中的另一种方法更适合?

更新 #1:所以我建立了一个这样的集合:

def dailycities(): Map[Int, Map[String,Map[String, List[Double]]]] = {
  weatherpatterns.groupBy(_.day)
  .mapValues(_.groupBy(_.country).mapValues(_.groupBy(_.city)
  .mapValues(_.map(_.temperature))))
}

然后使用 filterKeys 和 Set 函数创建了一个新地图,以返回我正在寻找的日期的列表。所以我想现在只需格式化即可正确得出平均值。

【问题讨论】:

  • 能否请您附上您的WeatherPattern 数据类型的示例记录?
  • 在文本文件的 sn-p 中?坚持下去,如果是这样,我可以做到。
  • 我看到你在 weatherpatterns 的元素上调用了像 .day.country 和 ... 这样的属性,所以我认为 WeatherPattern 应该是一个代表一行的案例类文件内容。
  • 哦对了,是这样的:case class WeatherPattern(day: Int, country: String, city: String, temperature: Double)

标签: scala


【解决方案1】:

我不会将其称为 scala 中执行此操作的最佳方式。在这种情况下,任何最小化迭代的方法都是最好的 imo:

def averageOfDay(country: String, city: String, day: Int) = {
  val temps = weatherPatterns.collect {
    case WeatherPattern(`day`, `country`, `city`, temp) => temp
  }
  temps.sum / temps.length
}

编辑

我刚刚注意到您主要需要一个计算所有城市和国家/地区的平均值的操作。在这种情况下,我会说不是在每个操作中形成国家->城市->温度的层次关系,而是选择预先构建层次结构然后对其进行操作:

case class DailyTemperature(day: Int, temperature: Double)

object DailyTemperature {
  def sequence(patterns: List[WeatherPattern]): List[DailyTemperature] =
    patterns.map(p => DailyTemperature(p.day,p.temperature))
}

case class CityTempInfo(city: String, dailyTemperatures: List[DailyTemperature])

object CityTempInfo {
  def sequence(patterns: List[WeatherPattern]): List[CityTempInfo] =
    patterns.groupBy(_.city).map {
      case (city, ps) => CityTempInfo(city,DailyTemperature.sequence(ps))
    }.toList

}

case class CountryTempInfo(country: String, citiesInfo: List[CityTempInfo])

object CountryTempInfo {
  def sequence(patterns: List[WeatherPattern]) =
    patterns.groupBy(_.country).map {
      case (country, ps) => CountryTempInfo(country, CityTempInfo.sequence(ps))
    }.toList
}

现在有你的国家树 -> 城市 -> 临时你打电话给CountryTempInfo.sequence 并将你的WeatherPatterns 列表提供给它。您想对DailyTemperatureCityTempInfoCountryTempInfo 进行操作的任何其他方法都可以在它们各自的类上定义。

【讨论】:

    【解决方案2】:

    当您说您使用“简单整数”作为日期时,我不确定您的确切含义,但如果它是合理的,例如“自纪元以来的天数”,您可以很容易地想出一个分组函数,映射到周:

     def weakOf(n: Int, start: Int) = (start + n) / 7
     patterns
       .groupBy { p => (weakOf(p.day, startDay), p.country, p.city) }
       .mapValues(_.map(_.temperature))
       .mapValues { s => s.sum / s.size }
    

    【讨论】:

      猜你喜欢
      • 2015-03-13
      • 2016-07-16
      • 2017-02-04
      • 1970-01-01
      • 2019-10-16
      • 2018-02-16
      • 2013-11-06
      • 2018-12-26
      • 1970-01-01
      相关资源
      最近更新 更多