爱数课实验 | 某图书网站数据清洗_数据

爱数课:idatacourse.cn


领域:其他




简介:本次案例是从当当网图书网站爬取下来的关于机器学习的数据,在本次案例中我们进行数据的处理,如增加、删除和修改等操作,已满足我们所需要的信息。




数据:

./dataset/data.csv

./dataset/星级.jpg

目录

爱数课实验 | 某图书网站数据清洗_字符串_02

1. 数据集介绍

本案例的数据集来自某图书网站爬取的机器学习相关的图书信息,数据集链接:http://idatascience.cn/dataset-detail?table_id=2
数据集中共有600条数据,5个字段,其中各个字段的含义如下:

字段

含义

书名

书的名称和相关简介

出版信息

书的作者、出版日期和出版社

当前价格

爬取时书的价格

星级

书的评价等级

评论数

购买该书的用户评论数量

2. 数据读取

2.1 读取数据

数据集保存在csv文件中,使用Pandas中的​​read_csv()​​函数读取csv文件,结果会保存为一个DataFrame或Series对象,使用DataFrame或Series对象的​​head()​​方法可以查看前行数据,默认为5。

# 导入相关的库
import pandas as pd
import numpy as np
# 读取数据
data = pd.read_csv("./dataset/data.csv",encoding='utf-8',sep='\t')
# 查看数据
data['星级'].value_counts()

爱数课实验 | 某图书网站数据清洗_正则表达式_03

2.2 查看数据集基本信息

调用DataFrame对象的​​info()​​方法,获取数据集的列名,非空值个数,列数据类型,内存占用等信息。

data._____

爱数课实验 | 某图书网站数据清洗_字符串_04

可以看出数据集索引为0到599,共600条数据。各个字段均没有空值,不需要进行缺失值处理。各个字段的数据类型均为字符型。

3. 数据清洗

3.1 提取价格数值

由于​​当前价格​​​这一列中包含'¥' 符号,如果我们想对图书价格进行统计以及可视化分析,则需要从​​当前价格​​​中提取出价格的数值。我们可以使用正则表达式的方法完成上述操作。正则表达式(Regular Expression)使用单个字符串来描述和匹配一系列符合某个句法规则的字符串,常见的正则表达式如下所示。re库是Python中正则表达式的支持库。使用re中的​​findall()​​​函数将​​当前价格​​​中的数值提取出来,保存为新的一列​​当前价格_match​​​。​​findall()​​函数返回字符串中所有与正则表达式匹配的全部字符串,返回形式为数组。

  • ​+​​将前面的模式匹配一次或者多次
  • ​?​​该符号匹配前一个字符零次或一次
  • ​*​​将前面的模式匹配0次或多次
  • ​.​​匹配除换行符以外的任意字符
  • ​\​​转译字符
  • ​\d​​ 匹配数字0-9
  • ​\d{n}​​ 匹配正好为n位数的数字
  • ​\d{n,}​​匹配至少为n位数的数字
  • ​\d{m,n}​​匹配m-n位数的数字
  • ​[A-Za-z]+​​匹配英文字母组成的字符串
  • ​[A-Za-z0-9]+​​匹配由数字和英文字母组成的字符串

DataFrame对象中的​​apply​​​方法可以将某个函数应用到由列或行形成的Series对象上。首先定义一个函数​​num_func​​​,用于提取价格数值,然后使用​​apply​​​方法将​​num_func​​​应用于​​当前价格​​这一列上。

data['当前价格']

爱数课实验 | 某图书网站数据清洗_数据_05

import re
# 利用正则表达式,将当前价格一列只读取数字部分并创建新的一列
def func(data):
result = __________
return float(result[0])

data['当前价格_match'] = data['当前价格'].apply(func)
data.head(3)

爱数课实验 | 某图书网站数据清洗_字符串_06

3.2 提取评论数值

由于​​评论数​​​这一列中不仅包含评论数值,还包括一些文字,如果我们想对评论的数量进行统计以及可视化分析,则需要从​​评论数​​​这一列当中提取出评论的数值。利用正则表达式将评论数中的数值提取出来,保存为新的一列​​评论数_match​​。

data['评论数']

爱数课实验 | 某图书网站数据清洗_数据_07

import re
# 定义读取评论数的函数
def func_1(data):
result = __________
return int(result[0])

# 利用apply方法,将每一条数据进行处理
data['评论数_match'] = data['评论数'].apply(func_1)
# 查看是否处理成功
data.head(3)

爱数课实验 | 某图书网站数据清洗_正则表达式_08

3.3 转换图书星级数值

爱数课实验 | 某图书网站数据清洗_字符串_09

同样​​星级​​​这一列中不仅包含数值,还包括一些其他的字符,如果我们想对图书的星级进行统计以及可视化分析,则需要从​​星级​​​这一列当中提取出星级的数值。利用正则表达式将星级中的数值提取出来。原网站中,利用星级对图书进行评价,图书星级最高用五颗星来进行表示,且可用半颗星进行表示。我们将星级的数值转换到​​[0,5]​​​的区间内,保存为新的一列​​星级_match​​,方便我们后续对数据集进行可视化等操作。

#提取星级数
data['星级_match'] = data['星级'].apply(func_1)
data.head(3)

爱数课实验 | 某图书网站数据清洗_字符串_10

#将星级除以20,取值范围转换到[0,5]的区间内
data['星级_match_cal'] = data['星级_match'].apply(______)
data.head(3)

爱数课实验 | 某图书网站数据清洗_字符串_11

3.4 提取作者、出版时间和出版社

接下来我们处理​​出版信息​​​这一列,从原始数据中可以看到,这一列主要包含三个信息,分别是作者、出版日期、出版社。我们将​​出版信息​​​按照​​/​​​分割成三部分,分三列单独存放,列名分别为作者、出版日期和出版社。字符串对象的​​split​​方法通过指定分隔符对字符串进行切片。

data['出版信息'][:5]

爱数课实验 | 某图书网站数据清洗_字符串_12

# 将出版信息分割成三列,分别提取出作者、出版日期和出版社
# 提取出作者
data['作者'] = data['出版信息'].apply(__________)
data.head(3)

爱数课实验 | 某图书网站数据清洗_正则表达式_13

提取出的出版时间为字符串对象,我们可以通过datetime库中datetime模块的strptime函数将字符串转换为datetime时间类型对象。

# 用正则表达式提取日期,并将日期字符串转换成日期格式
from datetime import datetime

def func_2(data):
result = re.findall(__________)
if len(result)<1:
return None
else:
return datetime.strptime(_____,_____) #返回日期类型

# 提取日期,并添加为新的一列
data['出版日期'] = data['出版信息'].apply(func_2)
data.head(3)

爱数课实验 | 某图书网站数据清洗_数据_14

# 提取出版社一列,并添加为新的一列
data['出版社'] = data['出版信息'].apply(_____________)

# 查看结果
data.head(3)

爱数课实验 | 某图书网站数据清洗_正则表达式_15

爱数课实验 | 某图书网站数据清洗_正则表达式_16

爱数课实验 | 某图书网站数据清洗_字符串_17

3.5 提取书名和简介

书名字段包含书名和书籍的相关介绍。​​【】​​​和​​[]​​之间的内容一般是图书的标注信息,我们可以用空格将其进行替换。剩余的内容中书名和其他内容基本是由空格隔开的,所以我们以空格为分隔符,对字段进行分割,提取图书的书名和简介部分。

data['书名'][:5]

爱数课实验 | 某图书网站数据清洗_字符串_18

#将'【】'和'[]'以及之间的内容,用空格来代替
def func_3(data):
data = data.strip()#先去除头和尾的空格
data = re.sub("【.*?】"," ",data)
data = re.sub("\[.*?\]"," ",data)
return data.split(" ")
data['书名_split'] = data['书名'].apply(func_3)
data['书名_split'][:5]

爱数课实验 | 某图书网站数据清洗_字符串_19

# 提取书名
data['书名_split_1'] = data['书名_split'].apply(lambda x:x[0])
data['书名_split_1'][:5]

爱数课实验 | 某图书网站数据清洗_字符串_20

#因为分割后的字段长度不唯一,所以从第三个开始我们要先判定每个字段分割后的长度,之后再进行提取
# 提取简介1
data['书名_split_2'] = data['书名_split'].apply(lambda x: None if len(x)<=1 else x[1])
data['书名_split_2'][:5]

爱数课实验 | 某图书网站数据清洗_数据_21

# 提取简介2
data['书名_split_3'] = data['书名_split'].apply(lambda x: None if len(x)<=2 else x[2])
data['书名_split_3'][:5]

爱数课实验 | 某图书网站数据清洗_数据_22

data.head(3)

爱数课实验 | 某图书网站数据清洗_数据_23

3.6 删除不需要的列

使用DataFrame对象的​​drop​​方法删除不需要的列。

# 删除不需要的列
data.drop(['书名','出版信息','当前价格','星级','评论数','星级_match','书名_split'],_________)
data.head(3)

爱数课实验 | 某图书网站数据清洗_正则表达式_24

3.7 修改列名

使用DataFrame对象的​​rename​​对列进行重命名。

# 修改列名
data.rename(columns={'当前价格_match':'当前价格','评论数_match':'评论数','星级_match_cal':'星级','书名_split_1':'书名','书名_split_2':'简介1','书名_split_3':'简介2'},___________)
data.head(3)

爱数课实验 | 某图书网站数据清洗_正则表达式_25

4. 保存数据

使用DataFrame对象的​​to_csv​​方法将处理好的数据保存为CSV文件。

data.to_csv('当当网机器学习图书数据(已清洗).csv', sep=',',encoding='utf8',index=False)

通过本案例我们了解了数据读取的方法,了解了一些常用的正则表达式,学习了数据清洗的基本操作,包括用正则表达式的方式匹配相应的字符串,用​​split()​​​方法按照指定字符对字符串进行分割,用​​replace()​​方法进行字符串的替换。将原始数据集经过数据清理,处理成适用于建模、计算和可视化分析的数据。

爱数课(iDataCourse)是一个面向院校的大数据和人工智能课程和资源平台。平台提供权威的课程资源、数据资源、案例实验资源,助力院校大数据和人工智能专业建设,课程建设和师资能力建设。