0x08 大数据分析,七层基本功

摘要:欲练数据神功,必先挥刀……,嗯,先扎好马步吧!编写SQL语句,是数据统计分析最基本的能力了。以为SQL的自定义功能太弱了,或者你以为就算是Hive调用外部脚本也麻烦了,那么咱们上当前最热的Spark图片描述
00 引言
2016就要来了,避不及,躲不开。新一年来以前,仍是有一件值得高兴的事情,那即是年终奖了。java

公司大了,什么样的人都有。嗯嗯……,说错了,是人大了,什么样的公司都进。嗯嗯……,仍是不对。是公司大了,员工多了,要统计每一个员工每一年写的代码数量。以此来分配年终奖了。python

假设有以下数据示例,第一列为员工的ID,第二列为年份,第三列为代码数。sql

126882,2005,5
126882,2013,16
127305,2010,2
127305,2014,29
128194,2012,1
128194,2013,161shell

欲练数据神功,必先挥刀……,嗯,先扎好马步吧。下面的7个步骤,是练好数据基本功的一些方法。数据库

01 MySQL版本
编写SQL语句,是数据统计分析最基本的能力了。通常统计分析中,掌握好join语句分析便可,其它数据库相关的备份、恢复、存储过程之类的,基本上不多用到。编程

用一个join来实现需求,取出数据:数组

select a.*
from table as a join table as b on a.id=b.id
where a.count>b.count;

本例中是本身和本身join,最简单的inner join,将两个表中按id相同的行进行关联起来,最后按条件进行筛选须要的数据便可。须要注意,MySQL中的临时表,是没有办法本身join本身的。ruby

02 Bash版本
咱们一般会以SQL为经常使用工具,若是SQL不能知足你的需求,或者实现起来比较麻烦,你能够导出成csv格式的文本文件。bash

Shell命令比一般想像的要强大,用好Shell命令,不少时候也能够方便的处理问题。数据结构

join -t',' -1 1 -2 1 data.csv data.csv | awk -F',' '$3>$5{print $1,$4,$5}'

这条命令看起来估计算最简洁了的,但仍是用了两个命令。join也是一个很是神奇的命令,能够完成关系数据库的join功能,包括left join,right join,outer join,inner join。
本例中指定了链接的字段,参数“-1 1 -2 1”分别指定第一个、第二个文件的第1个字段做为关联字段。将链接的数据使用awk进行简单的过滤处理。join命令至关于SQL中的join的功能,而附带的awk至关于SQL中的where条件,进行数据筛选。

03 Awk版本
在shell命令行下,还有一个强大的数据处理工具:AWK,强大到能独立完成不少数据处理和分析的任务,后面会有单独的篇章来介绍,请持续关注。

#!/usr/local/bin/awk -f
BEGIN{FS=","}
{
    id = int($1)
    year = int($2)
    count = int($3)
    print id,year,count

    if(yc[id]["count"] < count){
        yc[id]["year"] = year
        yc[id]["count"] = count
    }
}
END{
    for(x in yc){
        printf("%s,%s,%s\n", x, yc[x]["year"], yc[x]["count"])
    }
}

上面一段简单的Awk代码,把Awk的一些基本概念都用上了。也算是“麻雀虽小,五脏俱全”了。涉及Awk的三段式代码结构,数组与赋值,条件判断与循环等编程基础概念。

由于awk是按行读入文件,所以咱们的思想就是将当前的最大的值存储起来,再读入下一行,若是比当前最大值大,就更新,不然继续读入一行。

处理文件文件的方式,天然与数据库的join思想不同,但你须要习惯这种方式,由于这种处理文件文件的方式,也是不少NoSQL的处理方式。

04 Python版本
前面几篇文章都安利了Python,处理这种简单的统计,咱们也能够用Python来试试。

import sys

last_id = None
for line in sys.stdin:
    idx, year, count = line.strip().split(',')

    if idx == last_id:
        if count > most_count:
            most_year, most_count = year, count
    else:
        if last_id:
            print '%s,%s,%s' %(last_id, most_year, most_count)
        last_id = idx
        most_count = 0
if idx == last_id:
    print '%s,%s,%s' %(last_id, most_year, most_count)

处理的方式仍是同样,按行读取文件并存储和记录,但逻辑实现起来感受稍微有点绕而已。没有用数组或字典之类的来存储数据。

还须要注意,这个程序是须要对文件进行按id排序的,由于代码处理的是连续的行,而且假定相同的id是在连续的行上。

固然,你确定会说,这个代码写得有些杂乱,不符合一般的思路。之因此写成这样,是由于咱们后面在分布式环境中还要用。

05 Hive版本
也许你会想,若是文件很大,很大,很大(重要的说三遍吗?),那么如何处理呢?立刻就2016了,那么你听过安利吗?哦不对,是大数据,一个已经被说到烂透了的词。单机不能知足你的需求,那么使用分布式。

假设Facebook有20亿用户,统计每一个用户在天天中,各自发的消息的最多的那天和发送的条数,假设全部用户,天天都发消息。20亿用户,按Facebook上线10年算,3600天,共72000亿条记录,够大了吧!分别找出每一个用户发消息最多的那天和发消息的次数。

且来看看,由Facebook开源出来的Hive数据仓库,如何处理!

-- 见MySQL版本

你没有看错,我也没有骗你,还真是和MySQL用一样的代码。固然,Hive有本身的优化之类的,暂时先无论。

这个地方,有个前提,你只须要把那72000亿条数据,存放到HDFS文件系统上,而后创建一个外部表和HDFS文件进行关联,而后输入和MySQL一样的语句,Hive引擎会天然将SQL语句转换为下层的map-reduce代码运行。

重要的是,你的Hadoop集群有多强大,这个Hive语句就能达到多强大。还不用本身写map-reduce程序,就是分析师最熟悉的SQL语句。

若是你以为Hive也是SQL语句,有些自定义的函数或者方法比较麻烦,那么Hive还能够调用外部的脚本,只要是可执行脚本都行:python、ruby、bash、scala、java、lisp随便你爱好。

06 Spark版本
若是你以为用Hive太Low了,跟不上时代的步伐了。或者,你以为SQL的自定义功能太弱了,或者你以为就算是调用外部脚本也很麻烦,那么咱们上当前最热的Spark。

from pyspark import SparkContext
sc = SparkContext()
data = sc.textFile('data.csv')
data = data.map(lambda x: x.split(',')).map(lambda x: (x[0], (x[1], int(x[2])))).groupByKey().mapValues(lambda value: sorted(value, lambda x, y: cmp(x[1], y[1]), reverse=True)[0])
for item in data.collect():
    print '%s,%s,%s' % (item[0], item[1][0], item[1][1])

Spark支持几种编程接口,Scala、Java、Python,最近也开始支持R了。

上面虽然连续用了好几个map,但原理却很是简单,和python的map功能相似。惟一用了一个groupByKey功能,将相同的id聚合在一块儿,剩下的属性放在一个列表里面。对这个列表进行排序,取count最多的次数和年份,最后输出。

逻辑够简单,代码也够简洁。Spark强大的便利利益于Scala强大的数据结构与数据处理能力。

07 map-reduce版本
若是你追求彻底的原生,或者追求彻底的可控性。但又不熟悉Java代码,那么仍是能够用Python来写map-reduce程序。

# mapper.py见python版本
# reducer.py见python版本

又一个大骗子!

经过Hadoop的Streaming接口来进行调用,只须要自定义mapper和reducer程序便可。上面的mapper和reducer能够直接用纯粹Python的单机版本。

输入是一些id,year,count行,输出仍是一样的数据结构。只是在程序中,把当前这个程序的输入中,每一个id最多的count和year找出来了。数据量已经减小了,每一个id只会保留最大的一条数据。

分布式最基本的原理就是数据分块,在map阶段,对每一个块的数据调用mapper程序,求出当前块里面每一个id的最大count和year找出来。把这些输出做为reducer的输入,再求一次最大值,那么找出的即是全局的最大值。

08 结尾
数据分析基本功,按上面七个方面,扎好了马步,离数据神功第一层也不远了。

不要兴奋,也许会忽然冒出来一个小姑娘,告诉你说:切,上面的功能我用Excel也能够完美的实现。

固然能够了,聪明如你,Excel还能实现比这强大得多的功能。

理论上来讲,上面全部工具都能完成任何统计分析需求。只是不一样的地方,实现的方式各有不一样,有的复杂,有的简单,有的快,有的慢而已。选择你以为最简单的方式,搞定任务便可。

相关文章
相关标签/搜索