1. 引言
统计某日发布的二手物品在随后七天内, 交易完成时间是一天的类目分布占比.
也就是有哪些类目当天发布当天就有人买了.
2. 分析
- 利用管道模型聚合数据
collection.aggregate(pipeline)
有这么多过虑管道, 每个管道都是一个字典的结构, 常用的为$match``$group``$sort``$limit
database -> pipeline -> data
不同管道有不同的作用, 有的负责筛选匹配, 有的负责聚合整合统计, 还有的负责重新分组重新命名, 之后各管道叠加起来
3. 实现
In [1] :
from pymongo import MongoClient
from string import punctuation
from datetime import timedelta, date
import charts
In [2] :
client = MongoClient('10.66.17.17', 27017)
database = client['ganji']
item_info = database['item_info']
In [3] :
# 查看下源数据
[i for i in item_info.find().limit(3)]
Out [3] :
[{'_id': ObjectId('5698f524a98063dbe9e91ca8'),
'area': ['朝阳', '高碑店'],
'cates': ['北京58同城', '北京二手市场', '北京二手家电', '北京二手冰柜'],
'look': '-',
'price': 450,
'pub_date': '2016.01.12',
'time': 0,
'title': '【图】95成新小冰柜转让 - 朝阳高碑店二手家电 - 北京58同城',
'url': 'http://bj.58.com/jiadian/24541664530488x.shtml'},
{'_id': ObjectId('5698f525a98063dbe4e91ca8'),
'area': ['朝阳', '定福庄'],
'cates': ['北京58同城', '北京二手市场', '北京二手家电', '北京二手洗衣机'],
'look': '-',
'price': 1500,
'pub_date': '2016.01.14',
'time': 2,
'title': '【图】洗衣机,小冰箱,小冰柜,冷饮机 - 朝阳定福庄二手家电 - 北京58同城',
'url': 'http://bj.58.com/jiadian/24349380911041x.shtml'},
{'_id': ObjectId('5698f525a98063dbe7e91ca8'),
'area': ['朝阳', '望京'],
'cates': ['北京58同城', '北京二手市场', '北京二手台式机/配件'],
'look': '-',
'price': 1500,
'pub_date': '2015.12.27',
'time': 3,
'title': '【图】三星 A5 白色 没有打开过 - 朝阳望京台式机/配件 - 北京58同城',
'url': 'http://bj.58.com/diannao/24475337853109x.shtml'}]
In [4] :
# 定义pipeline模型
pipeline = [
# 大于某个日期小于某个日期且3天内完成成交的
# {'$match': {'$and': [{'pub_date': {'$gt': '2015.12.24', '$lt': '2015.12.26'}}, {'time': 3}]}},
# 发布日期为'2015.12.24'且3天内完成成交的
{'$match': {'$and': [{'pub_date': '2015.12.24'}, {'time': 3}]}},
# 以源数据的'price'字段分组, 且统计其出现次数, 出现一次则加1, '$sum'后的数字是多少就加多少
{'$group': {'_id': '$price', 'counts': {'$sum': 1}}},
# 排序, 指定以什么字段排序, 1为从低到高, -1为从高到低
{'$sort': {'counts': -1}},
# 限制显示多少条数据
{'$limit': 10},
]
In [5] :
[i for i in item_info.aggregate(pipeline)]
Out [5] :
[{'_id': 0, 'counts': 14},
{'_id': 1000, 'counts': 11},
{'_id': 300, 'counts': 7},
{'_id': 100, 'counts': 6},
{'_id': 50, 'counts': 5},
{'_id': 1800, 'counts': 5},
{'_id': 700, 'counts': 4},
{'_id': 200, 'counts': 4},
{'_id': 350, 'counts': 4},
{'_id': 3000, 'counts': 3}]
In [6] :
# 定义pipeline模型
pipeline2 = [
{'$match': {'$and': [{'pub_date': '2015.12.28'}, {'time': 1}]}},
{'$group': {'_id': {'$slice': ['$cates', 2, 1]}, 'counts': {'$sum': 1}}},
{'$sort': {'counts': -1}},
]
In [7] :
# 打印看下管道模型的输出结果
[i for i in item_info.aggregate(pipeline2)]
Out [7] :
[{'_id': ['北京二手家电'], 'counts': 40},
{'_id': ['北京二手服装/鞋帽/箱包'], 'counts': 21},
{'_id': ['北京二手母婴/儿童用品'], 'counts': 18},
{'_id': ['北京二手图书/音像/软件'], 'counts': 17},
{'_id': ['北京二手台式机/配件'], 'counts': 15},
{'_id': ['北京二手办公用品/设备'], 'counts': 14},
{'_id': ['北京二手文体/户外/乐器'], 'counts': 12},
{'_id': ['北京二手数码产品'], 'counts': 10},
{'_id': ['北京二手手机'], 'counts': 8},
{'_id': ['北京二手笔记本'], 'counts': 6},
{'_id': ['北京其他二手物品'], 'counts': 6},
{'_id': ['北京二手平板电脑'], 'counts': 5}]
In [8] :
# 定义函数方便快速生成图表数据
def time_data_gen(date, time):
# 定义管道模型
pipeline = [
{'$match': {'$and': [{'pub_date': date}, {'time': time}]}},
{'$group': {'_id': {'$slice': ['$cates', 2, 1]}, 'counts': {'$sum': 1}}},
{'$sort': {'counts': -1}},
]
# 生成所有数据
for i in item_info.aggregate(pipeline):
yield [i['_id'][0], i['counts']]
# 输出看下结果
[i for i in time_data_gen('2015.12.28', 1)]
Out [8] :
[['北京二手家电', 40],
['北京二手服装/鞋帽/箱包', 21],
['北京二手母婴/儿童用品', 18],
['北京二手图书/音像/软件', 17],
['北京二手台式机/配件', 15],
['北京二手办公用品/设备', 14],
['北京二手文体/户外/乐器', 12],
['北京二手数码产品', 10],
['北京二手手机', 8],
['北京二手笔记本', 6],
['北京其他二手物品', 6],
['北京二手平板电脑', 5]]
In [9] :
# 图表参数
options = {
'char': {'zoomType': 'xy'},
'title': {'text': '发帖量统计, 好看又好玩'},
'subtitle': {'text': '某日发布的二手物品在随后七天内, 交易完成时间是一天的类目分布占比'},
}
In [10] :
# 图表数据
serises = {
'type': 'pie',
'data': [i for i in time_data_gen('2015.12.28', 1)],
'name': 'One day',
}
# 输出饼状图表
charts.plot(serises, show='inline', options=options)
Out [10] :
4. 总结
- 管道模型就像是一层层的管子, 从数据库中通过管道取出数据
- 这些过滤管道, 每一个都是字典的结构