Python学习:JData入门小程序解析

最近在打算学习用Python来分析处理数据,这里做一下记录,让以后复习方便一些。Python我安装的是Anaconda3,里边包含了很多科学计算用的包,比如numpy、matplotlib、pandas、Scipy等。IDE用的是PyCharm。

学习pandas我看了一些视频,但总是感觉还是不尽人意,然后还是选择去官网看文档,正好看到一个翻译的中文的文档,对英语不好的人来说还是挺不错,链接:https://apachecn.github.io/pandas-doc-zh/10min.html

当然,看文档是记不住那么多函数的,所以我打算找了个实战例子来巩固自己的学习成果。正好老师给我推荐了个已经过气的去年的JData大赛的题目。但是看了一下题目,额……有种无从下手的感觉,所以还是看看大佬们的代码学习学习。

这是一位好心大佬daoliker提供的入门程序:https://github.com/daoliker/JData
数据集:链接:https://pan.baidu.com/s/1i5dXf5LQk-qG8qClQ_6DeA
提取码:4t6n

里边有好几个.py文件,让我来一个个分析吧

商品数据特征统计分析

经过一番百度,得知.py文件的执行顺序为:

python create_item_table.py
python explore_data.py
python create_user_table.py

这一步的目的,是把文件中的数据按照商品和用户两个维度进行聚合

create_item_table.py

根据经验,解读程序都是先从main开始的:

if __name__ == "__main__":
    item_base = get_from_jdata_product()
    item_behavior = merge_action_data()
    item_comment = get_from_jdata_comment()
    ……
1.获取商品信息

第一个函数get_from_jdata_product()
定义如下:

def get_from_jdata_product():
    df_item = pd.read_csv(PRODUCT_FILE, header=0)
    return df_item

很简单的一个函数,就是读取PRODUCT_FILE文件内容,其内容格式如下(前面一部分):


  • sku_id 商品编号 脱敏
  • a1 属性1 枚举,-1表示未知
  • a2 属性2 枚举,-1表示未知
  • a3 属性3 枚举,-1表示未知
  • cate 品类ID 脱敏
  • brand 品牌ID 脱敏
2.对行为信息进行一些处理

第二个函数merge_action_data():

可以看到这个函数先是获取get_from_action_data处理过的每个月用户对商品的行为数据,用来计算以下这些统计特征:

  • buy_addcart_ratio(购买加购转化率),
  • buy_browse_ratio(购买浏览转化率),
  • buy_click_ratio(购买点击转化率),
  • buy_favor_ratio(购买收藏转化率)
def merge_action_data():
    df_ac = []
    df_ac.append(get_from_action_data(fname=ACTION_201602_FILE))
    df_ac.append(get_from_action_data(fname=ACTION_201603_FILE))
    df_ac.append(get_from_action_data(fname=ACTION_201603_EXTRA_FILE))
    df_ac.append(get_from_action_data(fname=ACTION_201604_FILE))

    df_ac = pd.concat(df_ac, ignore_index=True)
    df_ac = df_ac.groupby(['sku_id'], as_index=False).sum()

    df_ac['buy_addcart_ratio'] = df_ac['buy_num'] / df_ac['addcart_num']
    df_ac['buy_browse_ratio'] = df_ac['buy_num'] / df_ac['browse_num']
    df_ac['buy_click_ratio'] = df_ac['buy_num'] / df_ac['click_num']
    df_ac['buy_favor_ratio'] = df_ac['buy_num'] / df_ac['favor_num']

    df_ac.ix[df_ac['buy_addcart_ratio'] > 1., 'buy_addcart_ratio'] = 1.
    df_ac.ix[df_ac['buy_browse_ratio'] > 1., 'buy_browse_ratio'] = 1.
    df_ac.ix[df_ac['buy_click_ratio'] > 1., 'buy_click_ratio'] = 1.
    df_ac.ix[df_ac['buy_favor_ratio'] > 1., 'buy_favor_ratio'] = 1.

    return df_ac

那么get_from_action_data干了啥?
get_from_action_data()函数,它是对ACTION_XXX_FILE文件进行一些统计,ACTION_XXX_FILE内容格式如下:


  • user_id 用户编号 脱敏
  • sku_id 商品编号 脱敏
  • time 行为时间
  • model_id 点击模块编号,如果是点击脱敏
  • type 1.浏览(指浏览商品详情页); 2.加入购物车;3.购物车删除;4.下单;5.关注;6.点击
  • cate 品类ID 脱敏
  • brand 品牌ID 脱敏

由于.csv文件比较大(500M左右)直接操作reader对内存要求比较大,所以需要迭代来操作:

def get_from_action_data(fname, chunk_size=100000):
    reader = pd.read_csv(fname, header=0, iterator=True)
    chunks = []
    loop = True
    while loop:              #对reader进行迭代操作
        try:
            chunk = reader.get_chunk(chunk_size)[["sku_id", "type"]]
            chunks.append(chunk)
        except StopIteration:
            loop = False
            print("Iteration is stopped")

    df_ac = pd.concat(chunks, ignore_index=True)

    df_ac = df_ac.groupby(['sku_id'], as_index=False).apply(add_type_count)

    df_ac = df_ac.drop_duplicates('sku_id') # 去掉重复项
    return df_ac

可以看到这里只读取["sku_id", "type"]这两列,原因是只这两列就可以计算出这么一些信息:
browse_num(浏览数),
addcart_num(加购数),
delcart_num(删购数),
buy_num(购买数),
favor_num(收藏数),
click_num(点击数)

其计算过程在add_type_count(group)函数里边:

def add_type_count(group):  

    behavior_type = group['type'].astype(int)  
    #print(behavior_type.head(10))
    type_cnt = Counter(behavior_type)   #对各个type进行统计返回一个dict
    #print(type_cnt)

    group['browse_num'] = type_cnt[1]
    group['addcart_num'] = type_cnt[2]
    group['delcart_num'] = type_cnt[3]
    group['buy_num'] = type_cnt[4]
    group['favor_num'] = type_cnt[5]
    group['click_num'] = type_cnt[6]
   
    return group[['sku_id', 'browse_num', 'addcart_num',
                  'delcart_num', 'buy_num', 'favor_num',
                  'click_num']]

如果想知道每一步计算的结果是什么,可以在那一步之后加个print

而最后merge_action_data()返回的就是这么样的一个DataFrame

3.处理评论数据

第三个函数get_from_jdata_comment也是非常简单的,它处理的文件是COMMENT_FILE,其内容如下:

  • dt 截止到时间 粒度到天
  • sku_id 商品编号 脱敏
  • comment_num 累计评论数分段0表示无评论,1表示有1条评论,
    2表示有2-10条评论,
    3表示有11-50条评论,
    4表示大于50条评论
  • has_bad_comment 是否有差评0表示无,1表示有
  • bad_comment_rate 差评率差评数占总评论数的比重

函数定义:

def get_from_jdata_comment():
    df_cmt = pd.read_csv(COMMENT_FILE, header=0)
    df_cmt['dt'] = pd.to_datetime(df_cmt['dt'])
    # 查找最新评论索引
    idx = df_cmt.groupby(['sku_id'])['dt'].transform(max) == df_cmt['dt']
    df_cmt = df_cmt[idx]

    return df_cmt[['sku_id', 'comment_num',
                   'has_bad_comment', 'bad_comment_rate']]

可以看到这个函数做的事情就这么几个:读取文件数据、转换时间格式、返回最新的评论数据

csv文件里的时间一般都是是str的,为了便于处理所以需要把它转换成datetime类。

从表中可以看到一个商品的评论信息可能会有对应好几个时间的,我们只需要得到最新的评论信息就行了。而且返回值也不需要'dt'这一列了。

4.类SQL操作

经过这三个函数我们得到3个新的表 item_base、item_behavior、item_comment。

    item_base = get_from_jdata_product()
    item_behavior = merge_action_data()
    item_comment = get_from_jdata_comment()

item_base:


item_behavior :


item_comment:


接下来要做的就是把这些表给融合起来:

由于本程序的目的是生成商品数据特征表,所以必须保证商品数据的完整。
so
以下连接操作都是以item_base为基准主键'sku_id'为的左连接操作:

# SQL: left join
    item_behavior = pd.merge(
        item_base, item_behavior, on=['sku_id'], how='left')
    item_behavior = pd.merge(
        item_behavior, item_comment, on=['sku_id'], how='left')

    item_behavior.to_csv(ITEM_TABLE_FILE, index=False)

最后得到的表的内容如下:


以上都是本萌新的个人理解,如有错误欢迎指出

create_item_table.py全部代码:

#-*- coding: utf-8 -*-

import pandas as pd
import numpy as np
from collections import Counter

ACTION_201602_FILE = "data/JData_Action_201602.csv"
ACTION_201603_FILE = "data/JData_Action_201603.csv"
ACTION_201603_EXTRA_FILE = "data/JData_Action_201603_extra.csv"
ACTION_201604_FILE = "data/JData_Action_201604.csv"
COMMENT_FILE = "data/JData_Comment.csv"
PRODUCT_FILE = "data/JData_Product.csv"
USER_FILE = "data/JData_User.csv"
NEW_USER_FILE = "data/JData_User_New.csv"
ITEM_TABLE_FILE = "data/item_table.csv"


def get_from_jdata_product():
    df_item = pd.read_csv(PRODUCT_FILE, header=0)
    return df_item


# apply type count
def add_type_count(group):  

    behavior_type = group['type'].astype(int)  

    type_cnt = Counter(behavior_type)  

    group['browse_num'] = type_cnt[1]
    group['addcart_num'] = type_cnt[2]
    group['delcart_num'] = type_cnt[3]
    group['buy_num'] = type_cnt[4]
    group['favor_num'] = type_cnt[5]
    group['click_num'] = type_cnt[6]
    
    return group[['sku_id', 'browse_num', 'addcart_num',
                  'delcart_num', 'buy_num', 'favor_num',
                  'click_num']]


def get_from_action_data(fname, chunk_size=100000):
    reader = pd.read_csv(fname, header=0, iterator=True)
    chunks = []
    loop = True
    while loop:
        try:
            chunk = reader.get_chunk(chunk_size)[["sku_id", "type"]]
            chunks.append(chunk)
        except StopIteration:
            loop = False
            print("Iteration is stopped")

    df_ac = pd.concat(chunks, ignore_index=True)

    df_ac = df_ac.groupby(['sku_id'], as_index=False).apply(add_type_count)

    df_ac = df_ac.drop_duplicates('sku_id') # 去掉重复项

    return df_ac


def get_from_jdata_comment():
    df_cmt = pd.read_csv(COMMENT_FILE, header=0)
    df_cmt['dt'] = pd.to_datetime(df_cmt['dt'])
    # find latest comment index
    idx = df_cmt.groupby(['sku_id'])['dt'].transform(max) == df_cmt['dt']
    df_cmt = df_cmt[idx]

    return df_cmt[['sku_id', 'comment_num',
                   'has_bad_comment', 'bad_comment_rate']]


def merge_action_data():
    df_ac = []
    df_ac.append(get_from_action_data(fname=ACTION_201602_FILE))

    df_ac.append(get_from_action_data(fname=ACTION_201603_FILE))

    df_ac.append(get_from_action_data(fname=ACTION_201603_EXTRA_FILE))

    df_ac.append(get_from_action_data(fname=ACTION_201604_FILE))

    df_ac = pd.concat(df_ac, ignore_index=True)
    df_ac = df_ac.groupby(['sku_id'], as_index=False).sum()

    df_ac['buy_addcart_ratio'] = df_ac['buy_num'] / df_ac['addcart_num']
    df_ac['buy_browse_ratio'] = df_ac['buy_num'] / df_ac['browse_num']
    df_ac['buy_click_ratio'] = df_ac['buy_num'] / df_ac['click_num']
    df_ac['buy_favor_ratio'] = df_ac['buy_num'] / df_ac['favor_num']

    df_ac.ix[df_ac['buy_addcart_ratio'] > 1., 'buy_addcart_ratio'] = 1.
    df_ac.ix[df_ac['buy_browse_ratio'] > 1., 'buy_browse_ratio'] = 1.
    df_ac.ix[df_ac['buy_click_ratio'] > 1., 'buy_click_ratio'] = 1.
    df_ac.ix[df_ac['buy_favor_ratio'] > 1., 'buy_favor_ratio'] = 1.

    return df_ac


if __name__ == "__main__":

    item_base = get_from_jdata_product()
    
    item_behavior = merge_action_data()
   
    item_comment = get_from_jdata_comment()
   
    # SQL: left join
    item_behavior = pd.merge(
        item_base, item_behavior, on=['sku_id'], how='left')
    item_behavior = pd.merge(
        item_behavior, item_comment, on=['sku_id'], how='left')

    item_behavior.to_csv(ITEM_TABLE_FILE, index=False)

参考:
https://blog.csdn.net/liuhuoxingkong/article/details/70049019
https://github.com/daoliker/JData
https://apachecn.github.io/pandas-doc-zh/10min.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350