Scala新手并尝试读取输入原始数据,以便在多个字段上生成包含groupBy的地图。
示例原始数据:
date,uid,site,success
2014-07-14,userA,google,1
2014-07-14,userB,google,1
2014-07-14,userC,yahoo,1
2014-07-14,userD,facebook,1
我想报告每个日期的每个网站的不同用户数,即
2014-07-14,google,2
2014-07-14,yahoo,1
2014-07-14,facebook,1
为此,我试图在日期和站点字段上使用groupBy,其值为uid。一旦我有了这个数据结构,我就可以迭代地图并计算不同的地图值。 谁能指出我如何生成数据结构?
谢谢!
答案 0 :(得分:2)
我希望我能正确理解你。这是一个完整的例子。
case class Data(date: String, uid: String, site: String, success: Int)
val sampleData = List(
Data("2014-07-14","userA","google",1),
Data("2014-07-14","userA","google",1),
Data("2014-07-14","userB","google",1),
Data("2014-07-14","userC","yahoo",1),
Data("2014-07-14","userD","facebook",1)
)
sampleData.groupBy(_.date).map
{case (date, datelist) => (date, datelist.groupBy(_.site).map
{case (site, sitelist) => (site, sitelist.groupBy(_.uid).size)})}
输出为:Map(2014-07-14 -> Map(google -> 2, yahoo -> 1, facebook -> 1))
基本上,您会获得每个日期的地图,其中包含来自不同用户的网站访问权限。请注意,userA
的2次访问计为1。
sitelist.groupBy(_.uid).size
按uid
计算不同的访问次数。
编辑是的,没有额外的数据结构是可能的。你现在必须处理数组的索引。
val fileText = """2014-07-14,userA,google,1
2014-07-14,userA,google,1
2014-07-14,userA,google,1
2014-07-14,userB,google,1
2014-07-14,userC,yahoo,1
2014-07-14,userD,facebook,1""".stripMargin
fileText.lines.map(_.split(",")).toList.groupBy(_(0)).map
{case (date, datelist) => (date, datelist.groupBy(_(2)).map
{case (site, sitelist) => (site, sitelist.groupBy(_(1)).size)})}
答案 1 :(得分:1)
为清楚起见,丢弃标题行,可能的实现如下:
val text = """2014-07-14,userA,google,1
|2014-07-14,userA,google,1
|2014-07-14,userB,google,1
|2014-07-14,userC,yahoo,1
|2014-07-16,userC,yahoo,1
|2014-07-14,userD,facebook,1
|2014-07-14,userE,facebook,1
|""".stripMargin
val uniqueUsersByDateSite: Map[(String, String), Int] = text.lines.map {
line =>
val tokens = line.split(",")
(tokens(0), tokens(1), tokens(2))
}.toSet.groupBy {
tuple: (String, String, String) =>
(tuple._1, tuple._3)
}.mapValues {
_.size
}
通过创建一组元组(date, uid, site)
,我们会为特定日期的网站的每个唯一身份用户收集一个项目。
groupBy
方法然后按(date, site)
收集,将同一日期和网站的N个项目转换为地图条目,其中包含与相应日期的唯一身份用户数相对应的多个项目站点。
最终的mapValue
方法可以达到预期的效果:
Map((2014-07-16,yahoo) -> 1, (2014-07-14,facebook) -> 2, (2014-07-14,google) -> 2, (2014-07-14,yahoo) -> 1)
答案 2 :(得分:0)
回答贴@Kigyo似乎很不错,但我认为你可以延长一点: 所以,假设这个数据结构:
case class Data(date: String, uid: String, site: String, success: Int)
val sampleData = List(
Data("2014-07-14","userA","google",1),
Data("2014-07-14","userA","google",1),
Data("2014-07-14","userB","google",1),
Data("2014-07-14","userC","yahoo",1),
Data("2014-07-14","userD","facebook",1)
)
你可以通过以下方式实现目标:
list.groupBy((_.date , _.site)).collect{ case (a , b : List[Data]) =>(a._1 , a._2 , b.map(_.success).sum) } ;
返回一个Tuple3列表,就像你想要的那样