1. 关于本notebook 1.1. 数据分析师可以驾驭的数据处理模板 Excel是数据分析师的必备工具,众多功能可以满足绝大多数的数据清洗、转换、统计计算、可视化展示。而Jupyter Notebook这类交互式数据探索和分析工具代表了一股不容忽视的潮流,借助于Python编程的强大力量,数据加工的能力和灵活性已经有相当明显的优势,尤其是程序代码和文字描述可以混合编排,数据探索和数据描述做完了,一篇研究报告也基本上成型了。 然而Python毕竟是一个全功能的编程语言,对于非编程出身的数据分析师来说,Pandas,Numpy,Matplotlib这些词让人望而生畏。本系列Notebook将设法解决这个问题,让非编程出身的数据分析师能够忽略复杂的编程过程,专注于数据处理和统计分析部分,就像使用Excel的公式一样驾驭Python。 所以,我们将尝试发布一系列Jupyter Notebook,像文档模板,一些基本的程序环境设置、文件操作等固化下来,在设定的分析场景下不需要改动程序代码。而数据处理部分的代码可以根据需要截取选用。每一项功能用一个code cell存代码,不需要的处理功能可以删除。 1.2. 本模板适应的场景 本模板可以处理GooSeeker网络爬虫软件采集京东商品详情页面的参数列表而得到的数据表,采集的原始页面如下:京东商品参数页面 本模板对采集结果数据表进行类似于Excel的处理,把采集到的每个商品的多条excel记录(对应多个参数),清洗成:每个商品一行,每个参数一列。 本Notebook按如下规则查找和处理excel数据表及字段: 1. 采集结果excel表放在data/raw中,当有多个excel文件存在时,处理第1个文件。下图是本模板自带的实例数据表:示例采集结果文件 2. 采集结果表中,需要有这几个字段:商品名称,价格,category,参数名,参数值,_fullpath(商品网址,会作为唯一性关键词):示例采集结果文件字段 3. 清洗处理后的excel表,保存在data/processed下 1.3. 使用方法 基本操作顺序是: 1. 使用GooSeeker网络爬虫软件采集京东商品详情页面的参数列表(以iphone13和oppo K10 Pro为例),并导出数据表 2. 将导出的数据表放在本notebook的data/raw文件夹中 3. 从头到尾执行本notebook的单元 注意:每个notebook项目目录都预先规划好了,具体参看Jupyter Notebook项目目录规划参考。如果要做多个分析项目,把整个模板目录专门拷贝一份给每个分析项目。 1.4. 简要技术说明 下文注明【编程细节】的文字,如果不太关心可以跳过,这样的文字往往是详细解释程序变量和函数的作用和用法。 本notebook主要采用Pandas程序库。用Pandas打开Excel表格,生成一个DataFrame类型的对象,这个对象提供了一系列数据表格探索的函数,类似于关系数据库的表格结构和数据的操作。 2. 数据源 数据源是使用GooSeeker网络爬虫软件采集京东商品详情页面的参数列表(以iphone13和oppo K10 Pro为例)。供参考和实验。 3. 修改历史 2022-05-18:第一版发布 4. 版权说明 本notebook是GooSeeker大数据分析团队开发的,本notebook中的代码可自由共享使用,包括转发、复制、修改、用于其他项目中。 5. 准备程序环境 导入必要的Python程序包,设定要分析的文件名变量。使用以下变量对应不同的GooSeeker采集结果表: file_jd_detail_para:采集导出的京东商品详细参数表 file_jd_detail_para_output:清洗后保存到data/processed下的数据表名 import pandas as pd import numpy as np import os %xmode Verbose # 存原始数据的目录 raw_data_dir = os.path.join(os.getcwd(), '..\\..\\data\\raw') # 存处理后的数据的目录 processed_data_dir = os.path.join(os.getcwd(), '..\\..\\data\\processed') filename_temp = pd.Series(['xlsx']) file_jd_detail_para = '' file_jd_detail_para_output = '' 输出结果: Exception reporting mode: Verbose # 这段代码看起来有些奇怪,这是因为GooSeeker的网络爬虫软件和分词软件会产生好几个输出文件 # 在我们的系列notebook中,给这些输出文件编了编号,在同一个notebook中可以同时处理多个文件,比如,进行合并 # 那么在raw文件夹中,应该给文件名加上合适的前缀,确保查出来的顺序跟程序中的编号一致。 # 例如,以往分词和情感分析的结果文件编号有这些: # 0:'词频', 1:'分词效果', 2:'选词矩阵', 3:'选词匹配', 4:'选词结果', 5:'共词矩阵' # 本文为了简化,假定raw文件夹中只有一个要分析的excel文件,编号是0 INDEX_CRAWLER_RESULT_FILE = 0 for item_filename in os.listdir(raw_data_dir): if filename_temp[INDEX_CRAWLER_RESULT_FILE] in item_filename: file_jd_detail_para = item_filename break if file_jd_detail_para: print("采集结果原始excel表:", "data\\raw\\", file_jd_detail_para) else: print("采集结果原始excel表:不存在") 输出结果: 采集结果原始excel表: data\raw\ 京东商品详情_参数采集_1652857131584.xlsx 6. 将数据的行列进行转换 用GooSeeker网络爬虫采集数据的时候,有时候是为了省事,定义一个很通用的采集规则,把网页上的产品参数表(一行一个参数)原样采集下来,不用定义复杂的采集规则,给每个参数命名专门的名字。这就是产生上面采集结果的原因。 显然,针对这样的采集结果,就需要这个notebook做一个变换,把一行一个参数的格式变成一列一个参数,这样转换以后,一行只有一个产品。 6.1. 打开原始采集结果excel数据表 这里的df变量表示打开的excel表格,这是一个DataFrame对象,下面的所有操作都是针对DataFrame对象做的。 df = '' try: df = pd.read_excel(os.path.join(raw_data_dir, file_jd_detail_para)) print("数据表打开成功") except: print("数据表打开错误,请检查数据文件:","data\\raw\\", file_jd_detail_para) 输出结果: 数据表打开成功 6.2. 操作数据表进行数据清洗 【注意】以下演示的所有步骤都需要在上一步“打开原始采集结果excel数据表”成功的条件下才能正常执行。 使用notebook最大一个好处,就是可以来来回回执行多个cell,修改一下再执行,如果不小心,会在后面的cell做了一些设置,却在前面的cell使用了,如果当时是在反复执行,就不会觉得有问题,但是哪一天从头初始执行,就会遇到错误。所以,哪些放在前面执行,要心里注意一下。 6.3. 清洗完成后保存的excel表 file_jd_detail_para_output = 'output_' + file_jd_detail_para 6.4. 初始化清洗结果dataframe 下面的语句其实是产生了一个新的dataframe,是一个空的,只有两个字段,就像新创建一张表一样,将用来存储清洗后的结果数据。 很多Pandas的dataframe函数执行结果是生成一个新的dataframe,即便是在老的dataframe上做表格计算,往往也是新生成一个dataframe。这有一个很大的好处,对比sql,常常一拍脑袋“大件事了,数据更新错了!”,此时作为普通用户就很难回退回去,因为在交互式界面上输入sql语句,每句一个事务,即时提交了。 但是,dataframe大部分情况下在执行了一个函数以后会生成一个新的dataframe,这就避免了很多像上面那样的拍脑袋。这叫immutable的模式。但是Pandas允许一些就地更改,这跟Spark dataframe不一样,那是严格immutable。 df_output = pd.DataFrame(columns=['_fullpath','商品名称']) df_output 输出结果: _fullpath 商品名称 6.5. 显示采集结果表的表头和第5条记录 df.head(5) 6.6. 读取采集结果表的每条记录,清洗进最终的集成表 上一个excel执行完成以后,你会发现数据有个很大问题:同一个产品的不同参数分别放在一行中。 下面的代码就是进行行列转换: 1. 首先_fullpath表示产品网址,作为唯一性关键词,如果结果表还没有这个产品,就插入一行新数据 2. 然后把每个参数值作为一列放在产品行中 for idx, row in df.iterrows(): # 从源数据表读出来需要的字段 # 读源数据表的时候,采用了序号方式:idx v_fullpath = df.iloc[idx]['_fullpath'] v_item_name = df.iloc[idx]['商品名称'] v_para_name = df.iloc[idx]['参数名'] v_para_value = df.iloc[idx]['参数值'] # 如果作为唯一性关键字的_fullpath字段还没有这一行数据,那么先插入这行数据 if len(df_output.loc[df_output['_fullpath'] == v_fullpath]) == 0: # 每次append,生成了一个新的dataframe,用原来的df_output继续保存新的dataframe df_output = df_output.append({'_fullpath': v_fullpath, '商品名称': v_item_name}, ignore_index = True) #下面这个操作没有生成新的dataframe,而是增加了表的列,用于存某个参数值,并填上了参数值 df_output.loc[df_output['_fullpath'] == v_fullpath, v_para_name] = v_para_value 6.7. 显示最终结果表的前5行 df_output.head(5) 6.7. 把最终结果表保存到data/processed目录下 df_output.to_excel(os.path.join(processed_data_dir, file_jd_detail_para_output), sheet_name='sheet1') 7. 下载notebook 下载本Jupyter Notebook文件请进入:用python将京东商品参数数据表做行列转换 |