spark学习6-spark模拟hive的列转行和行转列

继续上一篇学习spark

本次将通过一个实际场景来综合学习下spark如何实现hive中的列转行和行转列(关于hive的)列转行和行转列介绍见: http://blog.csdn.net/jthink_/article/details/38853573)

问题描述

假设我们有这样的交易记录,如下:
@6259656412068037	@822039695680011	7230	366.0	2015-06-18	1624	4030	0	@00400606	2015-06-18 16:24:28	S22	03	48224030	01059999	625965	02	01	1	12	156	00	N	宁德市普丽缇莎美容养生会所	2015-06
@4895928106642641	@822039695680011	7230	0.01	2015-06-18	1639	4030	0	@00400606	2015-06-18 16:39:33	S22	03	48224030	01059999	489592	02	01	1	01	156	00	N	宁德市普丽缇莎美容养生会所	2015-06
@6221552326194389	@822039695680011	7230	213.0	2015-05-03	1710	4030	0	@00400606	2015-05-03 17:10:50	S22	03	48224030	05105840	622155	02	01	1	12	156	00	N	宁德市普丽缇莎美容养生会所	2015-05
@3568398832346622	@822039695680011	7230	235.0	2015-05-03	1447	4030	0	@00400606	2015-05-03 14:47:08	S22	03	48224030	63030000	356839	02	01	1	04	156	00	N	宁德市普丽缇莎美容养生会所	2015-05
@6259651283230624	@822039695680011	7230	231.0	2015-05-03	1606	4030	0	@00400606	2015-05-03 16:06:16	S22	03	48224030	01059999	625965	02	01	1	12	156	00	N	宁德市普丽缇莎美容养生会所	2015-05

字段用\t分割,表示的含义依次是:卡号、商户号、商户类型、交易金额、交易日期、xx、xx、xx、机器id、交易时间戳、xx、xx、xx、xx、xx、xx、xx、xx、xx、xx、xx、xx、xx、xx、交易月份,其中xx是表示我们并不关注的字段
现在需要我们计算的指标描述如下:

观测月中,提取该PID下的流水,按天计算其两次交易间的刷卡间隔,以秒为单位。最后将这些间隔求平均后,按天分别输出例如:某PID在13年9月2日有3笔交易,时间戳为10:00:00,10:00:30,10:00:40,则其间隔为30,10,平均为20。以此类推,统计出该PID下当月有交易的日期下的所有平均间隔,枚举输出

问题分析

直接贴代码边解释边分析
    val trans = sc.textFile("/xxx/yangka/trans/yangka_sample_trans")
该代码读取出所有该数据
    val totalTrans = trans.map { tran =>
      val field = tran.split("\t")
      val pid = field(8)
      val ymd = field(4)
      val time = field(9)
      (pid + "_" + ymd, time)
    }.combineByKey(
      x => (sdf.parse(x).getTime / 1000).toString,
      (x: String, y: String) => x + "," + (sdf.parse(y).getTime / 1000).toString,
      (x: String, y: String) => x + "," + y
    ).map { line =>
      val dates = line._2.split(",").sorted
      if (dates.length <= 1) {
        (line._1, "0")
      } else {
        var values: String = ""
        for (i <- 0 to dates.length - 1) {
          if (i != dates.length - 1) {
            val seconds = dates(i + 1).toLong - dates(i).toLong
            values += seconds.toString + ","
          }
        }
        val tmp = values.substring(0, values.length - 1).split(",")
        (line._1, (tmp.foldLeft(0)(_ + _.toInt).toDouble / tmp.length).toString)
      }
    }
该代码块稍微复杂,解释如下:
1-6行是做了一个简单的map,取出我们有用的字段,最后的输出格式为( @00400606_2015-06-18, 2015-06-18 16:24:28)
7-10行用了一个函数combineByKey,我们先看下combineByKey如何使用 ,见 http://www.iteblog.com/archives/1291,最后我们得到这样的格式( @00400606_2015-06-18, "13000000,1321312,41241231"),KV的value是一堆用逗号隔开的时间戳,我们提到的行转列就是这么实现了
剩下的代码对一堆时间戳进行排序,然后用scala的foldLeft计算平均数
至此问题解决了,至于列转行其实很简单,用map就可以了,不多说了

总结

总结下最近的spark学习,由于自己之前是做hadoop、hive、hbase开发的,所以拿到手的问题自然会先想到用hive怎么做,然后再按照步骤用spark来实现,这也是一种不错的解决方法,总结而言scala集合操作、spark的常用transform算子要比较熟悉。

你可能感兴趣的:(大数据,hadoop,mapreduce,spark)