Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala——如何从原始数据创建映射以计算不同的值_Scala - Fatal编程技术网

Scala——如何从原始数据创建映射以计算不同的值

Scala——如何从原始数据创建映射以计算不同的值,scala,Scala,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,face

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。一旦我有了这个数据结构,我就可以迭代映射并计算不同的映射值。 有人能告诉我如何生成数据结构吗


谢谢

为了清晰起见,放弃标题行,可能的实现方式如下:

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
}
通过创建一组元组
(日期、uid、站点)
,我们为特定日期的站点的每个唯一用户收集一个项

然后,
groupBy
方法按
(日期,站点)
收集,将同一日期和站点的N个项目转换为一个地图条目,其中包含与相应日期和站点的唯一用户数相对应的项目数

最终的
mapValue
方法实现了预期的结果:

Map((2014-07-16,yahoo) -> 1, (2014-07-14,facebook) -> 2, (2014-07-14,google) -> 2, (2014-07-14,yahoo) -> 1)

我希望我理解正确。这里有一个完整的例子

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)})}

在@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列表,就像您想要的那样

1。你的输入数据有多大?2.您以后是否需要跨日期统计不同的用户数?每天大约有一百万行,并且需要跨日期统计不同的用户数。谢谢是的,这取决于@user2727704想要什么样的数据结构。我还假设
success
的数量与此无关,因为不同用户的数量与此无关。除了b.map(u.success)。sum之外,还有其他方法可以在uid上应用count distinct,因为我可能并不总是有一个success字段。谢谢如果您希望“success”字段像date和site一样使用(充当过滤器),最好的方法是将其包含在第一个元组中(在groupby中)。非常感谢。。从你的回答中学到了一些关于Scala的新东西。谢谢Kigyo,肯定回答了我的问题。由于我将解析外部文件的原始数据,构造数据对象是否会增加额外的开销?还有其他选择吗?