如何在Scala IntelliJ中处理这些大数据?

时间:2019-02-02 12:37:26

标签: scala intellij-idea

已经有几天了,我开始在IntelliJ上学习Scala,我自己一个人学习。请承担我的菜鸟错误。我有一个超过10,000行和13列的csv文件。

列的标题为:

类别|评分|评论|尺寸安装|类型价格内容分级|类型|最后更新|当前版本Android版本

我确实设法通过以下代码读取并显示了csv文件:

import scala.io.Source


object task {
  def main(args: Array[String]): Unit = {
    for(line <- Source.fromFile("D:/data.csv"))
    {
      println(line)
    }
  }
}

此问题是此代码显示一个字母或数字,移至下一行并显示下一个字母或数字。它不会在一行中显示一行。

我想根据其分配的评论和评分优先级,找出每个类别(ART_AND_DESIGN,AUTO_AND_VEHICLES,BEAUTY…)的最佳应用。优先级分别定义为“审阅”列的60%和“评级”列的40%。通过使用这些分配的优先级值,为每个类别(ART_AND_DESIGN,AUTO_AND_VEHICLES,BEAUTY…)计算一个值。此值将帮助我们找到每个类别中最好的应用程序。您可以按如下方式使用优先级公式方程式。

优先级=((((rating / max_rating)* 100)* 0.4)+(((reviews / max_reviews)* 100)* 0.6))

此处max_rating是同一类别(如类别(“ ART_AND_DESIGN”))中给定数据的最高评分,最高评分为“ 4.7”,max_reviews是同一类别(如类别(“ ART_AND_DESIGN”))中应用的最高评价,最高评分为“ 295221” 。因此,类别(“ ART_AND_DESIGN”)的第一个数据记录的优先级值为:

评分= 4.1,评论= 159,

max_rating = 4.7,max_reviews = 295221

我的问题是,如何将每个列存储在数组中?这就是我计划计算数据的方式。如果还有其他方法可以解决上述问题,我欢迎您提出建议。

如果有人愿意,我可以上传一小部分数据。

1 个答案:

答案 0 :(得分:3)

Source默认为您提供一个字节Iterator。要遍历行,请使用.getLines

 Source.fromFile(fileName)
   .getLines
   .foreach(println)

要将行拆分为数组,请使用split(假设列值不包含分隔符):

  val arrays = Source.fromFile(fileName).getLines.map(_.split("|"))

最好避免使用原始数组。创建案例类可以编写更好,更易读的代码:

   case class AppData(
     category: String,
     rating: Int,
     reviews: Int, 
     size: Int,
     installs: Int, 
     `type`: String, 
     price: Double,
     contentRating: Int, 
     generes: Seq[String], 
     lastUpdated: Long,
     version: String,
     androidVersion: String
  ) {
     def priority(maxRating: Int, maxReview: Int) = 
       if(maxRatings == 0 || maxReviews == 0) 0 else 
         (rating * 0.4 / maxRating + reviews * 0.6 /maxReview) * 100
  }

  object AppData {
    def apply(str: String) = {
       val fields = str.split("|")
       assert(fields.length == 12)
       AppData(
         fields(0),
         fields(1).toInt,   
         fields(2).toInt,
         fields(3).toInt,
         fields(4).toInt,
         fields(5),
         fields(6).toDouble,
         fields(7).toInt,
         fields(8).split(",").toSeq,
         fields(9).toLong,
         fields(10),
         fields(11)
       )
    }
  }

现在,您可以整齐地做自己想做的事情:

  // Read the data, parse it and group by category
  // This gives you a map of categories to a seq of apps 
  val byCategory = Source.fromFile(fileName)
    .map(AppData)
    .groupBy(_.category)

  // Now, find out max ratings and reviews for each category
  // This could be done even nicer with another case class and 
  // a monoid, but tuple/fold will do too 
  // It is tempting to use `.mapValues` here, but that's not a good idea
  // because .mapValues is LAZY, it will recompute the max every time 
  // the value is accessed!
  val maxes = byVategory.map { case (cat, data) => 
     cat -> 
        data.foldLeft(0 -> 0) { case ((maxRatings, maxReviews), in) => 
          (maxRatings max in.rating, maxReviews max in.reviews)
        }
  }.withDefault( _ => (0,0))

  // And finally go through your categories, and find best for each, 
  // that's it!
  val bestByCategory = byCategory.map { case(cat, apps) => 
    cat -> apps.maxBy { _.priority.tupled(maxes(cat)) }
  }