diff --git a/chapters/05-analytics-project.md b/chapters/03-analytics-project.md similarity index 100% rename from chapters/05-analytics-project.md rename to chapters/03-analytics-project.md diff --git a/chapters/07-create-your-project.md b/chapters/04-create-your-project.md similarity index 100% rename from chapters/07-create-your-project.md rename to chapters/04-create-your-project.md diff --git a/chapters/06-create-pull-request.md b/chapters/05-create-pull-request.md similarity index 100% rename from chapters/06-create-pull-request.md rename to chapters/05-create-pull-request.md diff --git a/chapters/08-build-github-project.md b/chapters/06-build-github-project.md similarity index 100% rename from chapters/08-build-github-project.md rename to chapters/06-build-github-project.md diff --git a/chapters/09-create-project-documents.md b/chapters/07-create-project-documents.md similarity index 100% rename from chapters/09-create-project-documents.md rename to chapters/07-create-project-documents.md diff --git a/chapters/10-tdd-with-autotest.md b/chapters/08-tdd-with-autotest.md similarity index 100% rename from chapters/10-tdd-with-autotest.md rename to chapters/08-tdd-with-autotest.md diff --git a/chapters/11-refactor-project.md b/chapters/09-refactor-project.md similarity index 100% rename from chapters/11-refactor-project.md rename to chapters/09-refactor-project.md diff --git a/chapters/12-streak-your-github.md b/chapters/10-streak-your-github.md similarity index 100% rename from chapters/12-streak-your-github.md rename to chapters/10-streak-your-github.md diff --git a/chapters/13-find-github-project.md b/chapters/11-find-github-project.md similarity index 100% rename from chapters/13-find-github-project.md rename to chapters/11-find-github-project.md diff --git a/chapters/03-analytics-01.md b/chapters/12-analytics-01.md similarity index 100% rename from chapters/03-analytics-01.md rename to chapters/12-analytics-01.md diff --git a/chapters/04-analytics-02.md b/chapters/13-analytics-02.md similarity index 100% rename from chapters/04-analytics-02.md rename to chapters/13-analytics-02.md diff --git a/github-roam.md b/github-roam.md index b5311a7..1def642 100644 --- a/github-roam.md +++ b/github-roam.md @@ -356,783 +356,6 @@ git push -u origin master ``` -#Github项目分析一 - -##生成图表 - -如何分析用户的数据是一个有趣的问题,特别是当我们有大量的数据的时候。除了``matlab``,我们还可以用``numpy``+``matplotlib`` - -数据可以在这边寻找到 - -[https://github.com/gmszone/ml](https://github.com/gmszone/ml) - -最后效果图 - - - -要解析的json文件位于``data/2014-01-01-0.json``,大小6.6M,显然我们可能需要用每次只读一行的策略,这足以解释为什么诸如sublime打开的时候很慢,而现在我们只需要里面的json数据中的创建时间。。 - -==,这个文件代表什么? - -**2014年1月1日零时到一时,用户在github上的操作,这里的用户指的是很多。。一共有4814条数据,从commit、create到issues都有。** - -###数据解析 - -```python -import json -for line in open(jsonfile): - line = f.readline() -``` - -然后再解析json - -```python -import dateutil.parser - -lin = json.loads(line) -date = dateutil.parser.parse(lin["created_at"]) -``` - -这里用到了``dateutil``,因为新鲜出炉的数据是string需要转换为``dateutil``,再到数据放到数组里头。最后有就有了``parse_data`` - -```python -def parse_data(jsonfile): - f = open(jsonfile, "r") - dataarray = [] - datacount = 0 - - for line in open(jsonfile): - line = f.readline() - lin = json.loads(line) - date = dateutil.parser.parse(lin["created_at"]) - datacount += 1 - dataarray.append(date.minute) - - minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)] - f.close() - return minuteswithcount -``` - -下面这句代码就是将上面的解析为 - -```python -minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)] -``` - -这样的数组以便于解析 - -```python -[(0, 92), (1, 67), (2, 86), (3, 73), (4, 76), (5, 67), (6, 61), (7, 71), (8, 62), (9, 71), (10, 70), (11, 79), (12, 62), (13, 67), (14, 76), (15, 67), (16, 74), (17, 48), (18, 78), (19, 73), (20, 89), (21, 62), (22, 74), (23, 61), (24, 71), (25, 49), (26, 59), (27, 59), (28, 58), (29, 74), (30, 69), (31, 59), (32, 89), (33, 67), (34, 66), (35, 77), (36, 64), (37, 71), (38, 75), (39, 66), (40, 62), (41, 77), (42, 82), (43, 95), (44, 77), (45, 65), (46, 59), (47, 60), (48, 54), (49, 66), (50, 74), (51, 61), (52, 71), (53, 90), (54, 64), (55, 67), (56, 67), (57, 55), (58, 68), (59, 91)] -``` - -###Matplotlib - -开始之前需要安装``matplotlib - -```bash -sudo pip install matplotlib -``` -然后引入这个库 - - import matplotlib.pyplot as plt - -如上面的那个结果,只需要 - -
- plt.figure(figsize=(8,4))
- plt.plot(x, y,label = files)
- plt.legend()
- plt.show()
-
-
-最后代码可见
-
-
-```python
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import json
-import dateutil.parser
-import numpy as np
-import matplotlib.mlab as mlab
-import matplotlib.pyplot as plt
-
-
-def parse_data(jsonfile):
- f = open(jsonfile, "r")
- dataarray = []
- datacount = 0
-
- for line in open(jsonfile):
- line = f.readline()
- lin = json.loads(line)
- date = dateutil.parser.parse(lin["created_at"])
- datacount += 1
- dataarray.append(date.minute)
-
- minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
- f.close()
- return minuteswithcount
-
-
-def draw_date(files):
- x = []
- y = []
- mwcs = parse_data(files)
- for mwc in mwcs:
- x.append(mwc[0])
- y.append(mwc[1])
-
- plt.figure(figsize=(8,4))
- plt.plot(x, y,label = files)
- plt.legend()
- plt.show()
-
-draw_date("data/2014-01-01-0.json")
-```
-
-##每周分析
-
-继上篇之后,我们就可以分析用户的每周提交情况,以得出用户的真正的工具效率,每个程序员的工作时间可能是不一样的,如
-
-
-
-这是我的每周情况,显然如果把星期六移到前面的话,随着工作时间的增长,在github上的使用在下降,作为一个
-
- a fulltime hacker who works best in the evening (around 8 pm).
-
-不过这个是osrc的分析结果。
-
-###python github 每周情况分析
-
-看一张分析后的结果
-
-
-
-结果正好与我的情况相反?似乎图上是这么说的,但是数据上是这样的情况。
-
- data
- ├── 2014-01-01-0.json
- ├── 2014-02-01-0.json
- ├── 2014-02-02-0.json
- ├── 2014-02-03-0.json
- ├── 2014-02-04-0.json
- ├── 2014-02-05-0.json
- ├── 2014-02-06-0.json
- ├── 2014-02-07-0.json
- ├── 2014-02-08-0.json
- ├── 2014-02-09-0.json
- ├── 2014-02-10-0.json
- ├── 2014-02-11-0.json
- ├── 2014-02-12-0.json
- ├── 2014-02-13-0.json
- ├── 2014-02-14-0.json
- ├── 2014-02-15-0.json
- ├── 2014-02-16-0.json
- ├── 2014-02-17-0.json
- ├── 2014-02-18-0.json
- ├── 2014-02-19-0.json
- └── 2014-02-20-0.json
-
-我们获取是每天晚上0点时的情况,至于为什么是0点,我想这里的数据量可能会比较少。除去1月1号的情况,就是上面的结果,在只有一周的情况时,总会以为因为在国内那时是假期,但是总觉得不是很靠谱,国内的程序员虽然很多,会在github上活跃的可能没有那么多,直至列出每一周的数据时。
-
- 6570, 7420, 11274, 12073, 12160, 12378, 12897,
- 8474, 7984, 12933, 13504, 13763, 13544, 12940,
- 7119, 7346, 13412, 14008, 12555
-
-###Python 数据分析
-
-重写了一个新的方法用于计算提交数,直至后面才意识到其实我们可以算行数就够了,但是方法上有点hack
-
-```python
-def get_minutes_counts_with_id(jsonfile):
- datacount, dataarray = handle_json(jsonfile)
- minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
- return minuteswithcount
-
-
-def handle_json(jsonfile):
- f = open(jsonfile, "r")
- dataarray = []
- datacount = 0
-
- for line in open(jsonfile):
- line = f.readline()
- lin = json.loads(line)
- date = dateutil.parser.parse(lin["created_at"])
- datacount += 1
- dataarray.append(date.minute)
-
- f.close()
- return datacount, dataarray
-
-
-def get_minutes_count_num(jsonfile):
- datacount, dataarray = handle_json(jsonfile)
- return datacount
-
-
-def get_month_total():
- """
-
- :rtype : object
- """
- monthdaycount = []
- for i in range(1, 20):
- if i < 10:
- filename = 'data/2014-02-0' + i.__str__() + '-0.json'
- else:
- filename = 'data/2014-02-' + i.__str__() + '-0.json'
- monthdaycount.append(get_minutes_count_num(filename))
- return monthdaycount
-```
-
-接着我们需要去遍历每个结果,后面的后面会发现这个效率真的是太低了,为什么木有多线程?
-
-###Python Matplotlib图表
-
-让我们的matplotlib来做这些图表的工作
-
-```python
-if __name__ == '__main__':
- results = pd.get_month_total()
- print results
-
- plt.figure(figsize=(8, 4))
- plt.plot(results.__getslice__(0, 7), label="first week")
- plt.plot(results.__getslice__(7, 14), label="second week")
- plt.plot(results.__getslice__(14, 21), label="third week")
- plt.legend()
- plt.show()
-```
-
-蓝色的是第一周,绿色的是第二周,蓝色的是第三周就有了上面的结果。
-
-我们还需要优化方法,以及多线程的支持。
-
-
-
-#Github项目分析二
-
-
-让我们分析之前的程序,然后再想办法做出优化。网上看到一篇文章[http://www.huyng.com/posts/python-performance-analysis/](http://www.huyng.com/posts/python-performance-analysis/)讲的就是分析这部分内容的。
-
-##Time Python分析
-
-分析程序的运行时间
-
-```bash
-$time python handle.py
-```
-
-结果便是,但是对于我们的分析没有一点意义
-
-```
- real 0m43.411s
- user 0m39.226s
- sys 0m0.618s
-```
-
-###line_profiler python
-
-```bash
-sudo ARCHFLAGS="-Wno-error=unused-command-line-argument-hard-error-in-future" easy_install line_profiler
-```
-
-然后在我们的``parse_data.py``的``handle_json``前面加上``@profile``
-
-```python
-@profile
-def handle_json(jsonfile):
- f = open(jsonfile, "r")
- dataarray = []
- datacount = 0
-
- for line in open(jsonfile):
- line = f.readline()
- lin = json.loads(line)
- date = dateutil.parser.parse(lin["created_at"])
- datacount += 1
- dataarray.append(date.minute)
-
- f.close()
- return datacount, dataarray
-```
-
-Line_profiler带了一个分析脚本``kernprof.py``,so
-
-```bash
-kernprof.py -l -v handle.py
-```
-
-我们便会得到下面的结果
-
-```
-Wrote profile results to handle.py.lprof
-Timer unit: 1e-06 s
-
-File: parse_data.py
-Function: handle_json at line 15
-Total time: 127.332 s
-
-Line # Hits Time Per Hit % Time Line Contents
-==============================================================
- 15 @profile
- 16 def handle_json(jsonfile):
- 17 19 636 33.5 0.0 f = open(jsonfile, "r")
- 18 19 21 1.1 0.0 dataarray = []
- 19 19 16 0.8 0.0 datacount = 0
- 20
- 21 212373 730344 3.4 0.6 for line in open(jsonfile):
- 22 212354 2826826 13.3 2.2 line = f.readline()
- 23 212354 13848171 65.2 10.9 lin = json.loads(line)
- 24 212354 109427317 515.3 85.9 date = dateutil.parser.parse(lin["created_at"])
- 25 212354 238112 1.1 0.2 datacount += 1
- 26 212354 260227 1.2 0.2 dataarray.append(date.minute)
- 27
- 28 19 349 18.4 0.0 f.close()
- 29 19 20 1.1 0.0 return datacount, dataarray
-```
-
-于是我们就发现我们的瓶颈就是从读取``created_at``,即创建时间。。。以及解析json,反而不是我们关心的IO,果然``readline``很强大。
-
-###memory_profiler
-
-首先我们需要install memory_profiler:
-
-```bash
-$ pip install -U memory_profiler
-$ pip install psutil
-```
-
-如上,我们只需要在``handle_json``前面加上``@profile``
-
-```bash
-python -m memory_profiler handle.py
-```
-
-于是
-
-```
-Filename: parse_data.py
-
-Line # Mem usage Increment Line Contents
-================================================
- 13 39.930 MiB 0.000 MiB @profile
- 14 def handle_json(jsonfile):
- 15 39.930 MiB 0.000 MiB f = open(jsonfile, "r")
- 16 39.930 MiB 0.000 MiB dataarray = []
- 17 39.930 MiB 0.000 MiB datacount = 0
- 18
- 19 40.055 MiB 0.125 MiB for line in open(jsonfile):
- 20 40.055 MiB 0.000 MiB line = f.readline()
- 21 40.066 MiB 0.012 MiB lin = json.loads(line)
- 22 40.055 MiB -0.012 MiB date = dateutil.parser.parse(lin["created_at"])
- 23 40.055 MiB 0.000 MiB datacount += 1
- 24 40.055 MiB 0.000 MiB dataarray.append(date.minute)
- 25
- 26 f.close()
- 27 return datacount, dataarray
-```
-
-###objgraph python
-
-安装objgraph
-
-```bash
-pip install objgraph
-```
-
-我们需要调用他
-
-```python
-import pdb;
-```
-
-以及在需要调度的地方加上
-
-```python
-pdb.set_trace()
-```
-
-接着会进入``command``模式
-
-```python
-(pdb) import objgraph
-(pdb) objgraph.show_most_common_types()
-```
-
-然后我们可以找到。。
-
-```
-function 8259
-dict 2137
-tuple 1949
-wrapper_descriptor 1625
-list 1586
-weakref 1145
-builtin_function_or_method 1117
-method_descriptor 948
-getset_descriptor 708
-type 705
-```
-
-也可以用他生成图形,貌似这里是用``dot``生成的,加上``python-xdot``
-
-很明显的我们需要一个数据库。
-
-如果我们每次都要花同样的时间去做一件事,去扫那些数据的话,那么这是最好的打发时间的方法。
-
-##python SQLite3 查询数据
-
-我们创建了一个名为``userdata.db``的数据库文件,然后创建了一个表,里面有owner,language,eventtype,name url
-
-```python
-def init_db():
- conn = sqlite3.connect('userdata.db')
- c = conn.cursor()
- c.execute('''CREATE TABLE userinfo (owner text, language text, eventtype text, name text, url text)''')
-```
-
-接着我们就可以查询数据,这里从结果讲起。
-
-```python
-def get_count(username):
- count = 0
- userinfo = []
- condition = 'select * from userinfo where owener = \'' + str(username) + '\''
- for zero in c.execute(condition):
- count += 1
- userinfo.append(zero)
-
- return count, userinfo
-```
-
-当我查询``gmszone``的时候,也就是我自己就会有如下的结果
-
-```bash
-(u'gmszone', u'ForkEvent', u'RESUME', u'TeX', u'https://github.com/gmszone/RESUME')
-(u'gmszone', u'WatchEvent', u'iot-dashboard', u'JavaScript', u'https://github.com/gmszone/iot-dashboard')
-(u'gmszone', u'PushEvent', u'wechat-wordpress', u'Ruby', u'https://github.com/gmszone/wechat-wordpress')
-(u'gmszone', u'WatchEvent', u'iot', u'JavaScript', u'https://github.com/gmszone/iot')
-(u'gmszone', u'CreateEvent', u'iot-doc', u'None', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'CreateEvent', u'iot-doc', u'None', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
-109
-````
-
-一共有109个事件,有``Watch``,``Create``,``Push``,``Fork``还有其他的,
-项目主要有``iot``,``RESUME``,``iot-dashboard``,``wechat-wordpress``,
-接着就是语言了,``Tex``,``Javascript``,``Ruby``,接着就是项目的url了。
-
-值得注意的是。
-
-```bash
--rw-r--r-- 1 fdhuang staff 905M Apr 12 14:59 userdata.db
-```
-
-这个数据库文件有**905M**,不过查询结果相当让人满意,至少相对于原来的结果来说。
-
-Python自带了对SQLite3的支持,然而我们还需要安装SQLite3
-
-```bash
-brew install sqlite3
-```
-
-或者是
-
-```bash
-sudo port install sqlite3
-```
-
-或者是Ubuntu的
-
-```bash
-sudo apt-get install sqlite3
-```
-
-openSUSE自然就是
-
-```bash
-sudo zypper install sqlite3
-```
-
-不过,用yast2也很不错,不是么。。
-
-###数据导入
-
-需要注意的是这里是需要python2.7,起源于对gzip的上下文管理器的支持问题
-
-```python
-def handle_gzip_file(filename):
- userinfo = []
- with gzip.GzipFile(filename) as f:
- events = [line.decode("utf-8", errors="ignore") for line in f]
-
- for n, line in enumerate(events):
- try:
- event = json.loads(line)
- except:
-
- continue
-
- actor = event["actor"]
- attrs = event.get("actor_attributes", {})
- if actor is None or attrs.get("type") != "User":
- continue
-
- key = actor.lower()
-
- repo = event.get("repository", {})
- info = str(repo.get("owner")), str(repo.get("language")), str(event["type"]), str(repo.get("name")), str(
- repo.get("url"))
- userinfo.append(info)
-
- return userinfo
-
-def build_db_with_gzip():
- init_db()
- conn = sqlite3.connect('userdata.db')
- c = conn.cursor()
-
- year = 2014
- month = 3
-
- for day in range(1,31):
- date_re = re.compile(r"([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]+)\.json.gz")
-
- fn_template = os.path.join("march",
- "{year}-{month:02d}-{day:02d}-{n}.json.gz")
- kwargs = {"year": year, "month": month, "day": day, "n": "*"}
- filenames = glob.glob(fn_template.format(**kwargs))
-
- for filename in filenames:
- c.executemany('INSERT INTO userinfo VALUES (?,?,?,?,?)', handle_gzip_file(filename))
-
- conn.commit()
- c.close()
-```
-
-``executemany``可以插入多条数据,对于我们的数据来说,一小时的文件大概有五六千个会符合我们上面的安装,也就是有``actor``又有``type``才是我们需要记录的数据,我们只需要统计用户的那些事件,而非全部的事件。
-
-我们需要去遍历文件,然后找到合适的部分,这里只是要找``2014-03-01``到``2014-03-31``的全部事件,而光这些数据的gz文件就有1.26G,同上面那些解压为json文件显得不合适,只能用遍历来处理。
-
-这里参考了osrc项目中的写法,或者说直接复制过来。
-
-首先是正规匹配
-
-```python
-date_re = re.compile(r"([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]+)\.json.gz")
-```
-
-不过主要的还是在于``glob.glob``
-
-> glob是python自己带的一个文件操作相关模块,用它可以查找符合自己目的的文件,就类似于Windows下的文件搜索,支持通配符操作。
-
-这里也就用上了``gzip.GzipFile``又一个不错的东西。
-
-最后代码可以见
-
-[github.com/gmszone/ml](http://github.com/gmszone/ml)
-
-更好的方案?
-
-##Redis
-
-查询用户事件总数
-
-```python
-import redis
-r = redis.StrictRedis(host='localhost', port=6379, db=0)
-pipe = pipe = r.pipeline()
-pipe.zscore('osrc:user',"gmszone")
-pipe.execute()
-```
-
-系统返回了``227.0``,试试别人。
-
-```bash
->>> pipe.zscore('osrc:user',"dfm")
-
+ plt.figure(figsize=(8,4))
+ plt.plot(x, y,label = files)
+ plt.legend()
+ plt.show()
+
+
+最后代码可见
+
+
+```python
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import json
+import dateutil.parser
+import numpy as np
+import matplotlib.mlab as mlab
+import matplotlib.pyplot as plt
+
+
+def parse_data(jsonfile):
+ f = open(jsonfile, "r")
+ dataarray = []
+ datacount = 0
+
+ for line in open(jsonfile):
+ line = f.readline()
+ lin = json.loads(line)
+ date = dateutil.parser.parse(lin["created_at"])
+ datacount += 1
+ dataarray.append(date.minute)
+
+ minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
+ f.close()
+ return minuteswithcount
+
+
+def draw_date(files):
+ x = []
+ y = []
+ mwcs = parse_data(files)
+ for mwc in mwcs:
+ x.append(mwc[0])
+ y.append(mwc[1])
+
+ plt.figure(figsize=(8,4))
+ plt.plot(x, y,label = files)
+ plt.legend()
+ plt.show()
+
+draw_date("data/2014-01-01-0.json")
+```
+
+##每周分析
+
+继上篇之后,我们就可以分析用户的每周提交情况,以得出用户的真正的工具效率,每个程序员的工作时间可能是不一样的,如
+
+
+
+这是我的每周情况,显然如果把星期六移到前面的话,随着工作时间的增长,在github上的使用在下降,作为一个
+
+ a fulltime hacker who works best in the evening (around 8 pm).
+
+不过这个是osrc的分析结果。
+
+###python github 每周情况分析
+
+看一张分析后的结果
+
+
+
+结果正好与我的情况相反?似乎图上是这么说的,但是数据上是这样的情况。
+
+ data
+ ├── 2014-01-01-0.json
+ ├── 2014-02-01-0.json
+ ├── 2014-02-02-0.json
+ ├── 2014-02-03-0.json
+ ├── 2014-02-04-0.json
+ ├── 2014-02-05-0.json
+ ├── 2014-02-06-0.json
+ ├── 2014-02-07-0.json
+ ├── 2014-02-08-0.json
+ ├── 2014-02-09-0.json
+ ├── 2014-02-10-0.json
+ ├── 2014-02-11-0.json
+ ├── 2014-02-12-0.json
+ ├── 2014-02-13-0.json
+ ├── 2014-02-14-0.json
+ ├── 2014-02-15-0.json
+ ├── 2014-02-16-0.json
+ ├── 2014-02-17-0.json
+ ├── 2014-02-18-0.json
+ ├── 2014-02-19-0.json
+ └── 2014-02-20-0.json
+
+我们获取是每天晚上0点时的情况,至于为什么是0点,我想这里的数据量可能会比较少。除去1月1号的情况,就是上面的结果,在只有一周的情况时,总会以为因为在国内那时是假期,但是总觉得不是很靠谱,国内的程序员虽然很多,会在github上活跃的可能没有那么多,直至列出每一周的数据时。
+
+ 6570, 7420, 11274, 12073, 12160, 12378, 12897,
+ 8474, 7984, 12933, 13504, 13763, 13544, 12940,
+ 7119, 7346, 13412, 14008, 12555
+
+###Python 数据分析
+
+重写了一个新的方法用于计算提交数,直至后面才意识到其实我们可以算行数就够了,但是方法上有点hack
+
+```python
+def get_minutes_counts_with_id(jsonfile):
+ datacount, dataarray = handle_json(jsonfile)
+ minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
+ return minuteswithcount
+
+
+def handle_json(jsonfile):
+ f = open(jsonfile, "r")
+ dataarray = []
+ datacount = 0
+
+ for line in open(jsonfile):
+ line = f.readline()
+ lin = json.loads(line)
+ date = dateutil.parser.parse(lin["created_at"])
+ datacount += 1
+ dataarray.append(date.minute)
+
+ f.close()
+ return datacount, dataarray
+
+
+def get_minutes_count_num(jsonfile):
+ datacount, dataarray = handle_json(jsonfile)
+ return datacount
+
+
+def get_month_total():
+ """
+
+ :rtype : object
+ """
+ monthdaycount = []
+ for i in range(1, 20):
+ if i < 10:
+ filename = 'data/2014-02-0' + i.__str__() + '-0.json'
+ else:
+ filename = 'data/2014-02-' + i.__str__() + '-0.json'
+ monthdaycount.append(get_minutes_count_num(filename))
+ return monthdaycount
+```
+
+接着我们需要去遍历每个结果,后面的后面会发现这个效率真的是太低了,为什么木有多线程?
+
+###Python Matplotlib图表
+
+让我们的matplotlib来做这些图表的工作
+
+```python
+if __name__ == '__main__':
+ results = pd.get_month_total()
+ print results
+
+ plt.figure(figsize=(8, 4))
+ plt.plot(results.__getslice__(0, 7), label="first week")
+ plt.plot(results.__getslice__(7, 14), label="second week")
+ plt.plot(results.__getslice__(14, 21), label="third week")
+ plt.legend()
+ plt.show()
+```
+
+蓝色的是第一周,绿色的是第二周,蓝色的是第三周就有了上面的结果。
+
+我们还需要优化方法,以及多线程的支持。
+
+
+
+#Github项目分析二
+
+
+让我们分析之前的程序,然后再想办法做出优化。网上看到一篇文章[http://www.huyng.com/posts/python-performance-analysis/](http://www.huyng.com/posts/python-performance-analysis/)讲的就是分析这部分内容的。
+
+##Time Python分析
+
+分析程序的运行时间
+
+```bash
+$time python handle.py
+```
+
+结果便是,但是对于我们的分析没有一点意义
+
+```
+ real 0m43.411s
+ user 0m39.226s
+ sys 0m0.618s
+```
+
+###line_profiler python
+
+```bash
+sudo ARCHFLAGS="-Wno-error=unused-command-line-argument-hard-error-in-future" easy_install line_profiler
+```
+
+然后在我们的``parse_data.py``的``handle_json``前面加上``@profile``
+
+```python
+@profile
+def handle_json(jsonfile):
+ f = open(jsonfile, "r")
+ dataarray = []
+ datacount = 0
+
+ for line in open(jsonfile):
+ line = f.readline()
+ lin = json.loads(line)
+ date = dateutil.parser.parse(lin["created_at"])
+ datacount += 1
+ dataarray.append(date.minute)
+
+ f.close()
+ return datacount, dataarray
+```
+
+Line_profiler带了一个分析脚本``kernprof.py``,so
+
+```bash
+kernprof.py -l -v handle.py
+```
+
+我们便会得到下面的结果
+
+```
+Wrote profile results to handle.py.lprof
+Timer unit: 1e-06 s
+
+File: parse_data.py
+Function: handle_json at line 15
+Total time: 127.332 s
+
+Line # Hits Time Per Hit % Time Line Contents
+==============================================================
+ 15 @profile
+ 16 def handle_json(jsonfile):
+ 17 19 636 33.5 0.0 f = open(jsonfile, "r")
+ 18 19 21 1.1 0.0 dataarray = []
+ 19 19 16 0.8 0.0 datacount = 0
+ 20
+ 21 212373 730344 3.4 0.6 for line in open(jsonfile):
+ 22 212354 2826826 13.3 2.2 line = f.readline()
+ 23 212354 13848171 65.2 10.9 lin = json.loads(line)
+ 24 212354 109427317 515.3 85.9 date = dateutil.parser.parse(lin["created_at"])
+ 25 212354 238112 1.1 0.2 datacount += 1
+ 26 212354 260227 1.2 0.2 dataarray.append(date.minute)
+ 27
+ 28 19 349 18.4 0.0 f.close()
+ 29 19 20 1.1 0.0 return datacount, dataarray
+```
+
+于是我们就发现我们的瓶颈就是从读取``created_at``,即创建时间。。。以及解析json,反而不是我们关心的IO,果然``readline``很强大。
+
+###memory_profiler
+
+首先我们需要install memory_profiler:
+
+```bash
+$ pip install -U memory_profiler
+$ pip install psutil
+```
+
+如上,我们只需要在``handle_json``前面加上``@profile``
+
+```bash
+python -m memory_profiler handle.py
+```
+
+于是
+
+```
+Filename: parse_data.py
+
+Line # Mem usage Increment Line Contents
+================================================
+ 13 39.930 MiB 0.000 MiB @profile
+ 14 def handle_json(jsonfile):
+ 15 39.930 MiB 0.000 MiB f = open(jsonfile, "r")
+ 16 39.930 MiB 0.000 MiB dataarray = []
+ 17 39.930 MiB 0.000 MiB datacount = 0
+ 18
+ 19 40.055 MiB 0.125 MiB for line in open(jsonfile):
+ 20 40.055 MiB 0.000 MiB line = f.readline()
+ 21 40.066 MiB 0.012 MiB lin = json.loads(line)
+ 22 40.055 MiB -0.012 MiB date = dateutil.parser.parse(lin["created_at"])
+ 23 40.055 MiB 0.000 MiB datacount += 1
+ 24 40.055 MiB 0.000 MiB dataarray.append(date.minute)
+ 25
+ 26 f.close()
+ 27 return datacount, dataarray
+```
+
+###objgraph python
+
+安装objgraph
+
+```bash
+pip install objgraph
+```
+
+我们需要调用他
+
+```python
+import pdb;
+```
+
+以及在需要调度的地方加上
+
+```python
+pdb.set_trace()
+```
+
+接着会进入``command``模式
+
+```python
+(pdb) import objgraph
+(pdb) objgraph.show_most_common_types()
+```
+
+然后我们可以找到。。
+
+```
+function 8259
+dict 2137
+tuple 1949
+wrapper_descriptor 1625
+list 1586
+weakref 1145
+builtin_function_or_method 1117
+method_descriptor 948
+getset_descriptor 708
+type 705
+```
+
+也可以用他生成图形,貌似这里是用``dot``生成的,加上``python-xdot``
+
+很明显的我们需要一个数据库。
+
+如果我们每次都要花同样的时间去做一件事,去扫那些数据的话,那么这是最好的打发时间的方法。
+
+##python SQLite3 查询数据
+
+我们创建了一个名为``userdata.db``的数据库文件,然后创建了一个表,里面有owner,language,eventtype,name url
+
+```python
+def init_db():
+ conn = sqlite3.connect('userdata.db')
+ c = conn.cursor()
+ c.execute('''CREATE TABLE userinfo (owner text, language text, eventtype text, name text, url text)''')
+```
+
+接着我们就可以查询数据,这里从结果讲起。
+
+```python
+def get_count(username):
+ count = 0
+ userinfo = []
+ condition = 'select * from userinfo where owener = \'' + str(username) + '\''
+ for zero in c.execute(condition):
+ count += 1
+ userinfo.append(zero)
+
+ return count, userinfo
+```
+
+当我查询``gmszone``的时候,也就是我自己就会有如下的结果
+
+```bash
+(u'gmszone', u'ForkEvent', u'RESUME', u'TeX', u'https://github.com/gmszone/RESUME')
+(u'gmszone', u'WatchEvent', u'iot-dashboard', u'JavaScript', u'https://github.com/gmszone/iot-dashboard')
+(u'gmszone', u'PushEvent', u'wechat-wordpress', u'Ruby', u'https://github.com/gmszone/wechat-wordpress')
+(u'gmszone', u'WatchEvent', u'iot', u'JavaScript', u'https://github.com/gmszone/iot')
+(u'gmszone', u'CreateEvent', u'iot-doc', u'None', u'https://github.com/gmszone/iot-doc')
+(u'gmszone', u'CreateEvent', u'iot-doc', u'None', u'https://github.com/gmszone/iot-doc')
+(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
+(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
+(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
+109
+````
+
+一共有109个事件,有``Watch``,``Create``,``Push``,``Fork``还有其他的,
+项目主要有``iot``,``RESUME``,``iot-dashboard``,``wechat-wordpress``,
+接着就是语言了,``Tex``,``Javascript``,``Ruby``,接着就是项目的url了。
+
+值得注意的是。
+
+```bash
+-rw-r--r-- 1 fdhuang staff 905M Apr 12 14:59 userdata.db
+```
+
+这个数据库文件有**905M**,不过查询结果相当让人满意,至少相对于原来的结果来说。
+
+Python自带了对SQLite3的支持,然而我们还需要安装SQLite3
+
+```bash
+brew install sqlite3
+```
+
+或者是
+
+```bash
+sudo port install sqlite3
+```
+
+或者是Ubuntu的
+
+```bash
+sudo apt-get install sqlite3
+```
+
+openSUSE自然就是
+
+```bash
+sudo zypper install sqlite3
+```
+
+不过,用yast2也很不错,不是么。。
+
+###数据导入
+
+需要注意的是这里是需要python2.7,起源于对gzip的上下文管理器的支持问题
+
+```python
+def handle_gzip_file(filename):
+ userinfo = []
+ with gzip.GzipFile(filename) as f:
+ events = [line.decode("utf-8", errors="ignore") for line in f]
+
+ for n, line in enumerate(events):
+ try:
+ event = json.loads(line)
+ except:
+
+ continue
+
+ actor = event["actor"]
+ attrs = event.get("actor_attributes", {})
+ if actor is None or attrs.get("type") != "User":
+ continue
+
+ key = actor.lower()
+
+ repo = event.get("repository", {})
+ info = str(repo.get("owner")), str(repo.get("language")), str(event["type"]), str(repo.get("name")), str(
+ repo.get("url"))
+ userinfo.append(info)
+
+ return userinfo
+
+def build_db_with_gzip():
+ init_db()
+ conn = sqlite3.connect('userdata.db')
+ c = conn.cursor()
+
+ year = 2014
+ month = 3
+
+ for day in range(1,31):
+ date_re = re.compile(r"([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]+)\.json.gz")
+
+ fn_template = os.path.join("march",
+ "{year}-{month:02d}-{day:02d}-{n}.json.gz")
+ kwargs = {"year": year, "month": month, "day": day, "n": "*"}
+ filenames = glob.glob(fn_template.format(**kwargs))
+
+ for filename in filenames:
+ c.executemany('INSERT INTO userinfo VALUES (?,?,?,?,?)', handle_gzip_file(filename))
+
+ conn.commit()
+ c.close()
+```
+
+``executemany``可以插入多条数据,对于我们的数据来说,一小时的文件大概有五六千个会符合我们上面的安装,也就是有``actor``又有``type``才是我们需要记录的数据,我们只需要统计用户的那些事件,而非全部的事件。
+
+我们需要去遍历文件,然后找到合适的部分,这里只是要找``2014-03-01``到``2014-03-31``的全部事件,而光这些数据的gz文件就有1.26G,同上面那些解压为json文件显得不合适,只能用遍历来处理。
+
+这里参考了osrc项目中的写法,或者说直接复制过来。
+
+首先是正规匹配
+
+```python
+date_re = re.compile(r"([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]+)\.json.gz")
+```
+
+不过主要的还是在于``glob.glob``
+
+> glob是python自己带的一个文件操作相关模块,用它可以查找符合自己目的的文件,就类似于Windows下的文件搜索,支持通配符操作。
+
+这里也就用上了``gzip.GzipFile``又一个不错的东西。
+
+最后代码可以见
+
+[github.com/gmszone/ml](http://github.com/gmszone/ml)
+
+更好的方案?
+
+##Redis
+
+查询用户事件总数
+
+```python
+import redis
+r = redis.StrictRedis(host='localhost', port=6379, db=0)
+pipe = pipe = r.pipeline()
+pipe.zscore('osrc:user',"gmszone")
+pipe.execute()
+```
+
+系统返回了``227.0``,试试别人。
+
+```bash
+>>> pipe.zscore('osrc:user',"dfm")
+git remote add origin git@github.com:phodal/github-roam.git
git push -u origin master
-如何分析用户的数据是一个有趣的问题,特别是当我们有大量的数据的时候。除了matlab,我们还可以用numpy+matplotlib
数据可以在这边寻找到
- -最后效果图
-
要解析的json文件位于data/2014-01-01-0.json,大小6.6M,显然我们可能需要用每次只读一行的策略,这足以解释为什么诸如sublime打开的时候很慢,而现在我们只需要里面的json数据中的创建时间。。
==,这个文件代表什么?
-2014年1月1日零时到一时,用户在github上的操作,这里的用户指的是很多。。一共有4814条数据,从commit、create到issues都有。
-import json
-for line in open(jsonfile):
- line = f.readline()然后再解析json
-import dateutil.parser
-
-lin = json.loads(line)
-date = dateutil.parser.parse(lin["created_at"])这里用到了dateutil,因为新鲜出炉的数据是string需要转换为dateutil,再到数据放到数组里头。最后有就有了parse_data
def parse_data(jsonfile):
- f = open(jsonfile, "r")
- dataarray = []
- datacount = 0
-
- for line in open(jsonfile):
- line = f.readline()
- lin = json.loads(line)
- date = dateutil.parser.parse(lin["created_at"])
- datacount += 1
- dataarray.append(date.minute)
-
- minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
- f.close()
- return minuteswithcount下面这句代码就是将上面的解析为
-minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]这样的数组以便于解析
-[(0, 92), (1, 67), (2, 86), (3, 73), (4, 76), (5, 67), (6, 61), (7, 71), (8, 62), (9, 71), (10, 70), (11, 79), (12, 62), (13, 67), (14, 76), (15, 67), (16, 74), (17, 48), (18, 78), (19, 73), (20, 89), (21, 62), (22, 74), (23, 61), (24, 71), (25, 49), (26, 59), (27, 59), (28, 58), (29, 74), (30, 69), (31, 59), (32, 89), (33, 67), (34, 66), (35, 77), (36, 64), (37, 71), (38, 75), (39, 66), (40, 62), (41, 77), (42, 82), (43, 95), (44, 77), (45, 65), (46, 59), (47, 60), (48, 54), (49, 66), (50, 74), (51, 61), (52, 71), (53, 90), (54, 64), (55, 67), (56, 67), (57, 55), (58, 68), (59, 91)]开始之前需要安装``matplotlib
-sudo pip install matplotlib然后引入这个库
- import matplotlib.pyplot as plt
-如上面的那个结果,只需要
-
- plt.figure(figsize=(8,4))
- plt.plot(x, y,label = files)
- plt.legend()
- plt.show()
-
-最后代码可见
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import json
-import dateutil.parser
-import numpy as np
-import matplotlib.mlab as mlab
-import matplotlib.pyplot as plt
-
-
-def parse_data(jsonfile):
- f = open(jsonfile, "r")
- dataarray = []
- datacount = 0
-
- for line in open(jsonfile):
- line = f.readline()
- lin = json.loads(line)
- date = dateutil.parser.parse(lin["created_at"])
- datacount += 1
- dataarray.append(date.minute)
-
- minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
- f.close()
- return minuteswithcount
-
-
-def draw_date(files):
- x = []
- y = []
- mwcs = parse_data(files)
- for mwc in mwcs:
- x.append(mwc[0])
- y.append(mwc[1])
-
- plt.figure(figsize=(8,4))
- plt.plot(x, y,label = files)
- plt.legend()
- plt.show()
-
-draw_date("data/2014-01-01-0.json")继上篇之后,我们就可以分析用户的每周提交情况,以得出用户的真正的工具效率,每个程序员的工作时间可能是不一样的,如
-
这是我的每周情况,显然如果把星期六移到前面的话,随着工作时间的增长,在github上的使用在下降,作为一个
- a fulltime hacker who works best in the evening (around 8 pm).
-不过这个是osrc的分析结果。
-看一张分析后的结果
-
结果正好与我的情况相反?似乎图上是这么说的,但是数据上是这样的情况。
-data
-├── 2014-01-01-0.json
-├── 2014-02-01-0.json
-├── 2014-02-02-0.json
-├── 2014-02-03-0.json
-├── 2014-02-04-0.json
-├── 2014-02-05-0.json
-├── 2014-02-06-0.json
-├── 2014-02-07-0.json
-├── 2014-02-08-0.json
-├── 2014-02-09-0.json
-├── 2014-02-10-0.json
-├── 2014-02-11-0.json
-├── 2014-02-12-0.json
-├── 2014-02-13-0.json
-├── 2014-02-14-0.json
-├── 2014-02-15-0.json
-├── 2014-02-16-0.json
-├── 2014-02-17-0.json
-├── 2014-02-18-0.json
-├── 2014-02-19-0.json
-└── 2014-02-20-0.json
-我们获取是每天晚上0点时的情况,至于为什么是0点,我想这里的数据量可能会比较少。除去1月1号的情况,就是上面的结果,在只有一周的情况时,总会以为因为在国内那时是假期,但是总觉得不是很靠谱,国内的程序员虽然很多,会在github上活跃的可能没有那么多,直至列出每一周的数据时。
- 6570, 7420, 11274, 12073, 12160, 12378, 12897,
- 8474, 7984, 12933, 13504, 13763, 13544, 12940,
- 7119, 7346, 13412, 14008, 12555
-重写了一个新的方法用于计算提交数,直至后面才意识到其实我们可以算行数就够了,但是方法上有点hack
-def get_minutes_counts_with_id(jsonfile):
- datacount, dataarray = handle_json(jsonfile)
- minuteswithcount = [(x, dataarray.count(x)) for x in set(dataarray)]
- return minuteswithcount
-
-
-def handle_json(jsonfile):
- f = open(jsonfile, "r")
- dataarray = []
- datacount = 0
-
- for line in open(jsonfile):
- line = f.readline()
- lin = json.loads(line)
- date = dateutil.parser.parse(lin["created_at"])
- datacount += 1
- dataarray.append(date.minute)
-
- f.close()
- return datacount, dataarray
-
-
-def get_minutes_count_num(jsonfile):
- datacount, dataarray = handle_json(jsonfile)
- return datacount
-
-
-def get_month_total():
- """
-
- :rtype : object
- """
- monthdaycount = []
- for i in range(1, 20):
- if i < 10:
- filename = 'data/2014-02-0' + i.__str__() + '-0.json'
- else:
- filename = 'data/2014-02-' + i.__str__() + '-0.json'
- monthdaycount.append(get_minutes_count_num(filename))
- return monthdaycount接着我们需要去遍历每个结果,后面的后面会发现这个效率真的是太低了,为什么木有多线程?
-让我们的matplotlib来做这些图表的工作
-if __name__ == '__main__':
- results = pd.get_month_total()
- print results
-
- plt.figure(figsize=(8, 4))
- plt.plot(results.__getslice__(0, 7), label="first week")
- plt.plot(results.__getslice__(7, 14), label="second week")
- plt.plot(results.__getslice__(14, 21), label="third week")
- plt.legend()
- plt.show()蓝色的是第一周,绿色的是第二周,蓝色的是第三周就有了上面的结果。
-我们还需要优化方法,以及多线程的支持。
-让我们分析之前的程序,然后再想办法做出优化。网上看到一篇文章http://www.huyng.com/posts/python-performance-analysis/讲的就是分析这部分内容的。
-分析程序的运行时间
-$time python handle.py结果便是,但是对于我们的分析没有一点意义
- real 0m43.411s
- user 0m39.226s
- sys 0m0.618s
-sudo ARCHFLAGS="-Wno-error=unused-command-line-argument-hard-error-in-future" easy_install line_profiler然后在我们的parse_data.py的handle_json前面加上@profile
@profile
-def handle_json(jsonfile):
- f = open(jsonfile, "r")
- dataarray = []
- datacount = 0
-
- for line in open(jsonfile):
- line = f.readline()
- lin = json.loads(line)
- date = dateutil.parser.parse(lin["created_at"])
- datacount += 1
- dataarray.append(date.minute)
-
- f.close()
- return datacount, dataarrayLine_profiler带了一个分析脚本kernprof.py,so
kernprof.py -l -v handle.py我们便会得到下面的结果
-Wrote profile results to handle.py.lprof
-Timer unit: 1e-06 s
-
-File: parse_data.py
-Function: handle_json at line 15
-Total time: 127.332 s
-
-Line # Hits Time Per Hit % Time Line Contents
-==============================================================
- 15 @profile
- 16 def handle_json(jsonfile):
- 17 19 636 33.5 0.0 f = open(jsonfile, "r")
- 18 19 21 1.1 0.0 dataarray = []
- 19 19 16 0.8 0.0 datacount = 0
- 20
- 21 212373 730344 3.4 0.6 for line in open(jsonfile):
- 22 212354 2826826 13.3 2.2 line = f.readline()
- 23 212354 13848171 65.2 10.9 lin = json.loads(line)
- 24 212354 109427317 515.3 85.9 date = dateutil.parser.parse(lin["created_at"])
- 25 212354 238112 1.1 0.2 datacount += 1
- 26 212354 260227 1.2 0.2 dataarray.append(date.minute)
- 27
- 28 19 349 18.4 0.0 f.close()
- 29 19 20 1.1 0.0 return datacount, dataarray
-于是我们就发现我们的瓶颈就是从读取created_at,即创建时间。。。以及解析json,反而不是我们关心的IO,果然readline很强大。
首先我们需要install memory_profiler:
-$ pip install -U memory_profiler
-$ pip install psutil如上,我们只需要在handle_json前面加上@profile
python -m memory_profiler handle.py于是
-Filename: parse_data.py
-
-Line # Mem usage Increment Line Contents
-================================================
- 13 39.930 MiB 0.000 MiB @profile
- 14 def handle_json(jsonfile):
- 15 39.930 MiB 0.000 MiB f = open(jsonfile, "r")
- 16 39.930 MiB 0.000 MiB dataarray = []
- 17 39.930 MiB 0.000 MiB datacount = 0
- 18
- 19 40.055 MiB 0.125 MiB for line in open(jsonfile):
- 20 40.055 MiB 0.000 MiB line = f.readline()
- 21 40.066 MiB 0.012 MiB lin = json.loads(line)
- 22 40.055 MiB -0.012 MiB date = dateutil.parser.parse(lin["created_at"])
- 23 40.055 MiB 0.000 MiB datacount += 1
- 24 40.055 MiB 0.000 MiB dataarray.append(date.minute)
- 25
- 26 f.close()
- 27 return datacount, dataarray
-安装objgraph
-pip install objgraph我们需要调用他
-import pdb;以及在需要调度的地方加上
-pdb.set_trace()接着会进入command模式
(pdb) import objgraph
-(pdb) objgraph.show_most_common_types()然后我们可以找到。。
-function 8259
-dict 2137
-tuple 1949
-wrapper_descriptor 1625
-list 1586
-weakref 1145
-builtin_function_or_method 1117
-method_descriptor 948
-getset_descriptor 708
-type 705
-也可以用他生成图形,貌似这里是用dot生成的,加上python-xdot
很明显的我们需要一个数据库。
-如果我们每次都要花同样的时间去做一件事,去扫那些数据的话,那么这是最好的打发时间的方法。
-我们创建了一个名为userdata.db的数据库文件,然后创建了一个表,里面有owner,language,eventtype,name url
def init_db():
- conn = sqlite3.connect('userdata.db')
- c = conn.cursor()
- c.execute('''CREATE TABLE userinfo (owner text, language text, eventtype text, name text, url text)''')接着我们就可以查询数据,这里从结果讲起。
-def get_count(username):
- count = 0
- userinfo = []
- condition = 'select * from userinfo where owener = \'' + str(username) + '\''
- for zero in c.execute(condition):
- count += 1
- userinfo.append(zero)
-
- return count, userinfo当我查询gmszone的时候,也就是我自己就会有如下的结果
(u'gmszone', u'ForkEvent', u'RESUME', u'TeX', u'https://github.com/gmszone/RESUME')
-(u'gmszone', u'WatchEvent', u'iot-dashboard', u'JavaScript', u'https://github.com/gmszone/iot-dashboard')
-(u'gmszone', u'PushEvent', u'wechat-wordpress', u'Ruby', u'https://github.com/gmszone/wechat-wordpress')
-(u'gmszone', u'WatchEvent', u'iot', u'JavaScript', u'https://github.com/gmszone/iot')
-(u'gmszone', u'CreateEvent', u'iot-doc', u'None', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'CreateEvent', u'iot-doc', u'None', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
-(u'gmszone', u'PushEvent', u'iot-doc', u'TeX', u'https://github.com/gmszone/iot-doc')
-109一共有109个事件,有Watch,Create,Push,Fork还有其他的, 项目主要有iot,RESUME,iot-dashboard,wechat-wordpress, 接着就是语言了,Tex,Javascript,Ruby,接着就是项目的url了。
值得注意的是。
--rw-r--r-- 1 fdhuang staff 905M Apr 12 14:59 userdata.db这个数据库文件有905M,不过查询结果相当让人满意,至少相对于原来的结果来说。
-Python自带了对SQLite3的支持,然而我们还需要安装SQLite3
-brew install sqlite3或者是
-sudo port install sqlite3或者是Ubuntu的
-sudo apt-get install sqlite3openSUSE自然就是
-sudo zypper install sqlite3不过,用yast2也很不错,不是么。。
-需要注意的是这里是需要python2.7,起源于对gzip的上下文管理器的支持问题
-def handle_gzip_file(filename):
- userinfo = []
- with gzip.GzipFile(filename) as f:
- events = [line.decode("utf-8", errors="ignore") for line in f]
-
- for n, line in enumerate(events):
- try:
- event = json.loads(line)
- except:
-
- continue
-
- actor = event["actor"]
- attrs = event.get("actor_attributes", {})
- if actor is None or attrs.get("type") != "User":
- continue
-
- key = actor.lower()
-
- repo = event.get("repository", {})
- info = str(repo.get("owner")), str(repo.get("language")), str(event["type"]), str(repo.get("name")), str(
- repo.get("url"))
- userinfo.append(info)
-
- return userinfo
-
-def build_db_with_gzip():
- init_db()
- conn = sqlite3.connect('userdata.db')
- c = conn.cursor()
-
- year = 2014
- month = 3
-
- for day in range(1,31):
- date_re = re.compile(r"([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]+)\.json.gz")
-
- fn_template = os.path.join("march",
- "{year}-{month:02d}-{day:02d}-{n}.json.gz")
- kwargs = {"year": year, "month": month, "day": day, "n": "*"}
- filenames = glob.glob(fn_template.format(**kwargs))
-
- for filename in filenames:
- c.executemany('INSERT INTO userinfo VALUES (?,?,?,?,?)', handle_gzip_file(filename))
-
- conn.commit()
- c.close()executemany可以插入多条数据,对于我们的数据来说,一小时的文件大概有五六千个会符合我们上面的安装,也就是有actor又有type才是我们需要记录的数据,我们只需要统计用户的那些事件,而非全部的事件。
我们需要去遍历文件,然后找到合适的部分,这里只是要找2014-03-01到2014-03-31的全部事件,而光这些数据的gz文件就有1.26G,同上面那些解压为json文件显得不合适,只能用遍历来处理。
这里参考了osrc项目中的写法,或者说直接复制过来。
-首先是正规匹配
-date_re = re.compile(r"([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]+)\.json.gz")不过主要的还是在于glob.glob
--glob是python自己带的一个文件操作相关模块,用它可以查找符合自己目的的文件,就类似于Windows下的文件搜索,支持通配符操作。
-
这里也就用上了gzip.GzipFile又一个不错的东西。
最后代码可以见
- -更好的方案?
-查询用户事件总数
-import redis
-r = redis.StrictRedis(host='localhost', port=6379, db=0)
-pipe = pipe = r.pipeline()
-pipe.zscore('osrc:user',"gmszone")
-pipe.execute()系统返回了227.0,试试别人。
>>> pipe.zscore('osrc:user',"dfm")
-<redis.client.StrictPipeline object at 0x104fa7f50>
->>> pipe.execute()
-[425.0]
->>>看看主要是在哪一天提交的
->>> pipe.hgetall('osrc:user:gmszone:day')
-<redis.client.StrictPipeline object at 0x104fa7f50>
->>> pipe.execute()
-[{'1': '51', '0': '41', '3': '17', '2': '34', '5': '28', '4': '22', '6': '34'}]结果大致如下图所示:
-
看看主要的事件是?
->>> pipe.zrevrange("osrc:user:gmszone:event".format("gmszone"), 0, -1,withscores=True)
-<redis.client.StrictPipeline object at 0x104fa7f50>
->>> pipe.execute()
-[[('PushEvent', 154.0), ('CreateEvent', 41.0), ('WatchEvent', 18.0), ('GollumEvent', 8.0), ('MemberEvent', 3.0), ('ForkEvent', 2.0), ('ReleaseEvent', 1.0)]]
->>>
-
蓝色的就是push事件,黄色的是create等等。
-到这里我们算是知道了OSRC的数据库部分是如何工作的。
-主要代码如下所示
-def get_vector(user, pipe=None):
-
- r = redis.StrictRedis(host='localhost', port=6379, db=0)
- no_pipe = False
- if pipe is None:
- pipe = pipe = r.pipeline()
- no_pipe = True
-
- user = user.lower()
- pipe.zscore(get_format("user"), user)
- pipe.hgetall(get_format("user:{0}:day".format(user)))
- pipe.zrevrange(get_format("user:{0}:event".format(user)), 0, -1,
- withscores=True)
- pipe.zcard(get_format("user:{0}:contribution".format(user)))
- pipe.zcard(get_format("user:{0}:connection".format(user)))
- pipe.zcard(get_format("user:{0}:repo".format(user)))
- pipe.zcard(get_format("user:{0}:lang".format(user)))
- pipe.zrevrange(get_format("user:{0}:lang".format(user)), 0, -1,
- withscores=True)
-
- if no_pipe:
- return pipe.execute()结果在上一篇中显示出来了,也就是
-[227.0, {'1': '51', '0': '41', '3': '17', '2': '34', '5': '28', '4': '22', '6': '34'}, [('PushEvent', 154.0), ('CreateEvent', 41.0), ('WatchEvent', 18.0), ('GollumEvent', 8.0), ('MemberEvent', 3.0), ('ForkEvent', 2.0), ('ReleaseEvent', 1.0)], 0, 0, 0, 11, [('CSS', 74.0), ('JavaScript', 60.0), ('Ruby', 12.0), ('TeX', 6.0), ('Python', 6.0), ('Java', 5.0), ('C++', 5.0), ('Assembly', 5.0), ('C', 3.0), ('Emacs Lisp', 2.0), ('Arduino', 2.0)]]
-有意思的是在这里生成了和自己相近的人
-['alesdokshanin', 'hjiawei', 'andrewreedy', 'christj6', '1995eaton']
-osrc最有意思的一部分莫过于flann,当然说的也是系统后台的设计的一个很关键及有意思的部分。
-邻近算法是在这个分析过程中一个很有意思的东西。
---邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法可以说是整个数据挖掘分类技术中最简单的方法了。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用她最接近的k个邻居来代表。
-
换句话说,我们需要一些样本来当作我们的分析资料,这里东西用到的就是我们之前的。
-[227.0, {'1': '51', '0': '41', '3': '17', '2': '34', '5': '28', '4': '22', '6': '34'}, [('PushEvent', 154.0), ('CreateEvent', 41.0), ('WatchEvent', 18.0), ('GollumEvent', 8.0), ('MemberEvent', 3.0), ('ForkEvent', 2.0), ('ReleaseEvent', 1.0)], 0, 0, 0, 11, [('CSS', 74.0), ('JavaScript', 60.0), ('Ruby', 12.0), ('TeX', 6.0), ('Python', 6.0), ('Java', 5.0), ('C++', 5.0), ('Assembly', 5.0), ('C', 3.0), ('Emacs Lisp', 2.0), ('Arduino', 2.0)]]
-在代码中是构建了一个points.h5的文件来分析每个用户的points,之后再记录到hdf5文件中。
-[ 0.00438596 0.18061674 0.2246696 0.14977974 0.07488987 0.0969163
- 0.12334802 0.14977974 0. 0.18061674 0. 0. 0.
- 0.00881057 0. 0. 0.03524229 0. 0.
- 0.01321586 0. 0. 0. 0.6784141 0.
- 0.07929515 0.00440529 1. 1. 1. 0.08333333
- 0.26431718 0.02202643 0.05286344 0.02643172 0. 0.01321586
- 0.02202643 0. 0. 0. 0. 0. 0.
- 0. 0. 0.00881057 0. 0. 0. 0.
- 0. 0. 0. 0. 0. 0. 0.
- 0. 0. 0. 0. 0.00881057]
-这里分析到用户的大部分行为,再找到与其行为相近的用户,主要的行为有下面这些:
-osrc中用于解析的代码
-def parse_vector(results):
- points = np.zeros(nvector)
- total = int(results[0])
-
- points[0] = 1.0 / (total + 1)
-
- # Week means.
- for k, v in results[1].iteritems():
- points[1 + int(k)] = float(v) / total
-
- # Event types.
- n = 8
- for k, v in results[2]:
- points[n + evttypes.index(k)] = float(v) / total
-
- # Number of contributions, connections and languages.
- n += nevts
- points[n] = 1.0 / (float(results[3]) + 1)
- points[n + 1] = 1.0 / (float(results[4]) + 1)
- points[n + 2] = 1.0 / (float(results[5]) + 1)
- points[n + 3] = 1.0 / (float(results[6]) + 1)
-
- # Top languages.
- n += 4
- for k, v in results[7]:
- if k in langs:
- points[n + langs.index(k)] = float(v) / total
- else:
- # Unknown language.
- points[-1] = float(v) / total
-
- return points这样也就返回我们需要的点数,然后我们可以用get_points来获取这些
def get_points(usernames):
- r = redis.StrictRedis(host='localhost', port=6379, db=0)
- pipe = r.pipeline()
-
- results = get_vector(usernames)
- points = np.zeros([len(usernames), nvector])
- points = parse_vector(results)
- return points就会得到我们的相应的数据,接着找找和自己邻近的,看看结果。
-[ 0.01298701 0.19736842 0. 0.30263158 0.21052632 0.19736842
- 0. 0.09210526 0. 0.22368421 0.01315789 0. 0.
- 0. 0. 0. 0.01315789 0. 0.
- 0.01315789 0. 0. 0. 0.73684211 0. 0.
- 0. 1. 1. 1. 0.2 0.42105263
- 0.09210526 0. 0. 0. 0. 0.23684211
- 0. 0. 0.03947368 0. 0. 0. 0.
- 0. 0. 0. 0. 0. 0. 0.
- 0. 0. 0. 0. 0. 0. 0.
- 0. 0. 0. 0. ]
-真看不出来两者有什么相似的地方 。。。。
之前曾经分析过一些Github的用户行为,现在我们先来说说Github上的Star吧。(截止: 2015年3月9日23时。)