shuyi;周三
学习目标:
-
数据预处理——numpy&pandas
- 读入数据
- 过滤重复
- 处理缺失
- 描述分析
- apply
- group by
- 时间序列
- merge
- ...
-
画图——先学会最基本的:
- 散点图
- 条形图
- 直方图
- ...
-
使用数据:
-
火锅数据集作为例子学习
-
把双十一、高考、直播、网剧,四个数据集作为练习题
-
...
-
-
希望:掌握数据描述统计
画图基本——Matplotlib
画布的概念
matplotlib 中的pyplot函数:
- figure(figsize = (长,宽)):创建画布
- add_subplot(行,列,第几个位置):分割画布
- plt.show():画图
- plt.close():关闭画布,jupyter里一定要关闭
预设
- 支持中文
需要设置字体路径 prop = mfm.FontProperties(fname = font_path)
加文字时设置 fontproperties=prop即可
- 画图主题
比如plt.style.use('ggplot') # 指定全局画图主题为ggplot
- 图片显示
在jupyter 里显示图片需要加上:%matplotlib inline
坐标轴、辅助线、标题、图例
具体看狗熊会python画图
[https://mmbiz.qpic.cn/mmbiz_png/1y1ObuUF34zwoIN91WUYmTtxkMRYD6QxZYk8URAW2XRo6WkOdDj6BVLsHDEWB8MFBmAWP3LwlRKVn5gicXdlwkQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1.png]
# 将代码块运行结果全部输出,而不是只输出最后的,适用于全文
#from IPython.core.interactiveshell import InteractiveShell
#InteractiveShell.ast_node_interactivity = "all"
# matplotlib 中的pyplot函数,用于画图
import matplotlib.pyplot as plt # 命名为plt
# 在jupyter 里显示图片
import numpy as np
%matplotlib inline
# font_manager函数,用于指定中文字体样式、大小
import matplotlib.font_manager as mfm
# 设置字体
font_path = r"/Users/mac/Library/Fonts/字体管家方萌简(非商业使用)v1.1.ttf"
prop = mfm.FontProperties(fname = font_path)
# 画图主题
plt.style.use('seaborn-white') # 指定全局画图主题为ggplot
# 画布
fig = plt.figure(figsize=(16,9)) # 创建一张18*6的画布
ax1 = fig.add_subplot(111) # 创建子图
#fig.add_subplot(2,2,1) # 创建2*2=4张图,ax1画在第一张图上
ax1.set_title('你好', fontproperties=prop, fontsize=50) # 图标题
ax1.hlines(y = 0.5, xmin = 0, xmax=1)
plt.show() # 画图
plt.close() # plt.show()结束后仍然保存在内存中, 切记关闭!!!在jupyter理!!!
Text(0.5,1,'你好')
<matplotlib.collections.LineCollection at 0x114802d30>

# 读入数据
import pandas as pd # 导入Pandas模块
merge_data = pd.read_excel("https://github.com/xiangyuchang/xiangyuchang.github.io/blob/master/BearData/merge_shop_coupon_nm.xlsx?raw=true") #读入数据
print('数据的维度是:', merge_data.shape)
merge_data.head() #查看数据的前5行
数据的维度是: (197, 12)
店名 | 关键词 | 城市 | 评分 | 评价数 | 人均 | 地址 | 营业时间 | 菜名 | 商家等级 | 购买人数 | 团购价 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 老北京涮羊肉 | 火锅 | xa | 4.4 | 877 | 45.5 | 西安市雁塔区朱雀大街250号东方大酒店西门斜对面(子午路站下车向北走60米路西) | 11:00-21:00 | 【羊肉】【豆腐】【麻酱】【精品肥牛】【粉丝】【羔羊肉】【牛肚】【油豆皮】【香菇】【豆皮】【土... | 2 | 1692 | 118.5 |
1 | 大龙燚火锅(粉巷店) | 火锅 | xa | 4.6 | 2253 | 100.0 | 西安市碑林区粉巷南院门15A南苑中央广场食尚南苑2F | 周一至周日 10:00-21:00 | 【麻辣排骨】【千层毛肚】【鸳鸯锅】【鸭血】【天味香肠】【薄土豆】【功夫黄瓜】【清汤锅】【印度... | 2 | 19584 | 88.0 |
2 | 鲜上鲜文鱼庄(凤城五路店) | 火锅 | xa | 4.5 | 1398 | 56.0 | 西安市未央区凤城五路地铁D口出人人乐5楼 | 全天 | 【生菜】【鸳鸯锅】【千叶豆腐】【荷包豆腐】【生鱼片】【毛肚】【文鱼】【鱼丸】【撒尿牛丸】【山... | 2 | 11798 | 52.0 |
3 | 蜜悦士鲜牛肉时尚火锅(凯德广场店) | 火锅 | xa | 4.4 | 48 | 63.0 | 西安市雁塔区南二环凯德广场四楼东南角 | 10:00-21:00 | 【吊龙伴】【三花腱】【番茄锅】【招牌牛舌】【油豆皮】【油炸豆腐皮】【菌汤鸳鸯锅】【手工面】【... | 2 | 40 | 59.9 |
4 | 大自在火锅(和平村店) | 火锅 | xa | 4.3 | 214 | 84.0 | 西安市莲湖区三桥和平村十字西南角伯乐城市广场6层 | 暂无时间 | 【蔬菜拼盘】【黄豆芽】【虾饺】【撒尿牛肉丸】【油条】【毛肚】【自在小酥肉】【鸡爪】【自在嫩牛... | 2 | 1282 | 59.5 |
散点图
ax.scatter(x=,y=,color='',marker='')
直方图
ax.hist(x=, bins= ,color = ,cumulative = T/F)
fig = plt.figure(figsize=(16,15))
ax1 = fig.add_subplot(221)
ax1.scatter(y = merge_data['评价数'], x = merge_data['人均'], color='black')
ax1.set_title('人均-评价数 关系图', fontproperties=prop, fontsize=25)
# 基本设置
ax2 = fig.add_subplot(222)
ax2.scatter(y = merge_data['购买人数'], x = merge_data['评分'], color='black')
ax2.set_title('评分-购买人数 关系图', fontproperties=prop, fontsize=25)
ax3 = fig.add_subplot(223)
ax3.scatter(y = merge_data['评价数'], x = merge_data['人均'], color='black')
ax3.set_title('人均-评价数 关系图2', fontproperties=prop, fontsize=25)
ax3.set_ylim((500, 6000))
ax3.set_xlim((20, 60))
ax3.hlines(2000, 20, 60, colors ="r", linestyles="dashed")
ax4 = fig.add_subplot(2,2,4)
ax4.hist(x = merge_data['评分'], color = "grey")
ax4.set_xlabel('评分', fontproperties=prop, fontsize=25)
plt.show()
plt.close()
<matplotlib.collections.PathCollection at 0x115a723c8>
Text(0.5,1,'人均-评价数 关系图')
<matplotlib.collections.PathCollection at 0x115ac2470>
Text(0.5,1,'评分-购买人数 关系图')
<matplotlib.collections.PathCollection at 0x115aef1d0>
Text(0.5,1,'人均-评价数 关系图2')
(500, 6000)
(20, 60)
<matplotlib.collections.LineCollection at 0x115aef6d8>
(array([ 1., 0., 1., 0., 1., 0., 6., 2., 54., 132.]),
array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ]),
<a list of 10 Patch objects>)
Text(0.5,0,'评分')

箱线图
ax1.boxplot
fig = plt.figure(figsize=(12,8))
ax1 = fig.add_subplot(111)
d1 = merge_data['评价数'][merge_data['购买人数'] < 500]
d2 = merge_data['评价数'][merge_data['购买人数'] >= 500][merge_data['购买人数'] < 1500]
d3 = merge_data['评价数'][merge_data['购买人数'] >= 1500][merge_data['购买人数'] < 2000]
d = [d1, d2, d3]
ax1.boxplot(d)
#ax1.set_title('购买人数评价数关系图', fontproperties=prop, fontsize=20)
ax1.set_xlabel('购买人数', fontproperties=prop, fontsize=20)
ax1.set_ylabel('评价数', fontproperties=prop, fontsize=20)
ax1.set_xticklabels(['<500', '[500, 1500)', '[1500, 2000)'], fontproperties=prop, fontsize=20)
ax1.set_ylim((0, 1600)) # 去掉异常值
plt.show()
plt.close()
# 由于d只是为画图而产生的属于中间变量,之后不会再使用到
# 用完就删除,防止内存过大
del d
{'whiskers': [<matplotlib.lines.Line2D at 0x115bd26a0>,
<matplotlib.lines.Line2D at 0x115bd2b00>,
<matplotlib.lines.Line2D at 0x116bf7550>,
<matplotlib.lines.Line2D at 0x116bf79b0>,
<matplotlib.lines.Line2D at 0x116c05470>,
<matplotlib.lines.Line2D at 0x116c058d0>],
'caps': [<matplotlib.lines.Line2D at 0x115bd2f60>,
<matplotlib.lines.Line2D at 0x116bef400>,
<matplotlib.lines.Line2D at 0x116bf7e10>,
<matplotlib.lines.Line2D at 0x116bf7f28>,
<matplotlib.lines.Line2D at 0x116c05d30>,
<matplotlib.lines.Line2D at 0x116c05e48>],
'boxes': [<matplotlib.lines.Line2D at 0x115bd20f0>,
<matplotlib.lines.Line2D at 0x116befd30>,
<matplotlib.lines.Line2D at 0x116bfefd0>],
'medians': [<matplotlib.lines.Line2D at 0x116bef7f0>,
<matplotlib.lines.Line2D at 0x116bfe710>,
<matplotlib.lines.Line2D at 0x116c0d630>],
'fliers': [<matplotlib.lines.Line2D at 0x116befc50>,
<matplotlib.lines.Line2D at 0x116bfeb70>,
<matplotlib.lines.Line2D at 0x116c0da90>],
'means': []}
Text(0.5,0,'购买人数')
Text(0,0.5,'评价数')
[Text(0,0,'<500'), Text(0,0,'[500, 1500)'), Text(0,0,'[1500, 2000)')]
(0, 1600)

numpy
- ndarray:数组,存储单一数据类型 ~
有点类似matrix,只能放数值,但是 T/F 浮点 int都行
- ufunc:对数组做处理
需要了解:
- 创建数组 numpy.array
- 数据类型的定义dtype和转化float int bool
- 统计分析 sum mean std var min max sort
创建一个matrix
- np.array~~ 利用列表构建一个数组
- np.arange(start, stop, step, dtype) ~~~ seq
import numpy as np
# 用列表构建二维数组
# 可以理解为matrix
# 要求长度一致
np.array([[1,2,3,3,4,2],['a','a','b','a','a','b']])
# 用arange创建一个数组~~ 非常类似seq
np.arange(0,10,2)
np.arange(0,1,0.2)
array([['1', '2', '3', '3', '4', '2'],
['a', 'a', 'b', 'a', 'a', 'b']], dtype='<U21')
array([0, 2, 4, 6, 8])
array([0. , 0.2, 0.4, 0.6, 0.8])
读入数据
首先尝试用昨天学的pandas read函数读入:
## 将代码块运行结果全部输出,而不是只输出最后的,适用于全文
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
# 设置路径
import os ## 加载标准库
os.chdir('/Users/mac/Desktop/快乐研一/python/py0915') # 相当于setwd()
os.getcwd() # 确认位置
# 读入多元作业1-1的csv
import pandas as pd #导入Pandas模块
duoyuan1 = pd.read_csv("肺活量与其他指标的数据.csv") # 读入当前目录下的某个excel
duoyuan1.head() # 查看前五行
duoyuan1.dtypes
序号 int64
age int64
weight float64
time float64
spulse int64
rpulse int64
mpulse int64
OXY float64
dtype: object
接着试试numpy创建数据或者读入数据:要求每一列都是一种类型
步骤如下:
- 加载numpy
- loadtxt 来读入
- 定义字段类型 dtype
# 1.加载numpy
# import numpy as np # 上面加载过了
# 2.读入数据,按定义好的字段类型匹配
# 读入csv文件分隔符delimiter=,
#duoyuan2 = np.loadtxt('肺活量与其他指标的数据.csv', delimiter = ",", dtype = str)
#duoyuan2[3:7]
定义字段类型
np.dtype([(字段1', 类型1), (字段2', 类型2)...(字段k', 类型k)])
# 定义字段类型
student = np.dtype([('name',np.str_,10), ('age', np.int64), ('marks', np.float64),('isgirl',np.bool_)])
stu_data = np.array([('abc', 21, 50, True),('xyz', 18, 75,True),('asd', 22, 90, False),('abc', 21, 50,True),('wsd', 20, 76,False)], dtype = student)
# 查看某个字段用括号
stu_data['isgirl']
# 冒号分隔切片参数 start:stop:step 来进行切片操作
stu_data[:4:2]
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-12-fc745cc02e4e> in <module>()
1 # 定义字段类型
----> 2 student = np.dtype([('name',np.str_,10), ('age', np.int64), ('marks', np.float64),('isgirl',np.bool_)])
3 stu_data = np.array([('abc', 21, 50, True),('xyz', 18, 75,True),('asd', 22, 90, False),('abc', 21, 50,True),('wsd', 20, 76,False)], dtype = student)
4
5 # 查看某个字段用括号
NameError: name 'np' is not defined
计算统计量
- data.sort
- sum/mean/var/max/min
marks = stu_data['marks']
marks.astype(int)
marks.sort()
marks
[np.sum(marks),np.mean(marks),int(np.var(marks)),np.max(marks)]
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-13-79ab63fcf526> in <module>()
----> 1 marks = stu_data['marks']
2 marks.astype(int)
3 marks.sort()
4 marks
5 [np.sum(marks),np.mean(marks),int(np.var(marks)),np.max(marks)]
NameError: name 'stu_data' is not defined
pandas
需要掌握:
基本:
- 读入数据
- 处理重复和异常值
- 切片索引筛选
- 统计量
进阶:
- 类似apply
- 类似group.by
拓展:
- 时间序列
- 结合sql——类似reshape
读入数据
read_csv or read_excel
出现乱码时可以设置encoding = 'utf8'或者'gbk'
# 加载pandas
import pandas as pd
# 读取狗熊会火锅数据
raw_data = pd.read_excel('https://github.com/xiangyuchang/xiangyuchang.github.io/blob/master/BearData/shops_nm.xlsx?raw=true')
# 查看数据维度
raw_data.shape
(699, 9)
切片索引
# 查看读入结果(注意 head也是针对pd读入,前一节numpy读入head报错了)
# 查看某列某行:
raw_data.iloc[1,0] # 第2行第1列
#raw_data.iloc[0,:] # 某一行
#raw_data['店名'] # 某一列
#raw_data.iloc[:,3] # 某一列
# 输出前五行
raw_data.head()
'鲜上鲜文鱼庄(望庭国际店)'
店名 | 关键词 | 城市 | 评分 | 评价数 | 人均 | 地址 | 营业时间 | 菜名 | |
---|---|---|---|---|---|---|---|---|---|
0 | 老北京涮羊肉 | 火锅 | xa | 4.4 | 877.0 | 45.5 | 西安市雁塔区朱雀大街250号东方大酒店西门斜对面(子午路站下车向北走60米路西) | 11:00-21:00 | 【羊肉】【豆腐】【麻酱】【精品肥牛】【粉丝】【羔羊肉】【牛肚】【油豆皮】【香菇】【豆皮】【土... |
1 | 鲜上鲜文鱼庄(望庭国际店) | 火锅 | xa | 4.6 | 535.0 | 56 | 西安市高新区高新路80号望庭国际一栋楼10106室 | 11:00-23:00 | 【菌菇大拼】【麻酱】【菠萝飞饼】【鸳鸯锅】【酸菜鸳鸯锅】【青菜】【毛肚】【文鱼】【菌汤】【鱼... |
2 | 大龙燚火锅(李家村店) | 火锅 | xa | 4.6 | 29.0 | 大概92左右 | 西安市碑林区雁塔北路时亿广场南座2楼李家村华润万家外 | 10:00-22:00 | 【手撕竹笋】【麻辣排骨】【砣砣牛肉】【菠萝飞饼】【鸭血】【四川金针菇】【麻辣牛肉】【贡菜】【... |
3 | 鲜上鲜文鱼庄(阳阳国际店) | 火锅 | xa | 4.6 | 906.0 | 56 | 西安市雁塔区朱雀大街132号阳阳国际广场C座2楼 | 11:00-22:00 | 【海带】【鸳鸯锅】【冻豆腐】【荷包豆腐】【生鱼片】【毛肚】【文鱼】【清汤锅】【山珍菌汤锅】【... |
4 | 大龙燚火锅(粉巷店) | 火锅 | xa | 4.6 | 2253.0 | 人均:100 | 西安市碑林区粉巷南院门15A南苑中央广场食尚南苑2F | 周一至周日 10:00-21:00 | 【麻辣排骨】【千层毛肚】【鸳鸯锅】【鸭血】【天味香肠】【薄土豆】【功夫黄瓜】【清汤锅】【印度... |
理解DataFrame
- 非常非常类似R里的数据框
- 每一列的数据类型要相同,但是不同列可以不同
- 基于这个理念,可以通过构建字典或数组的方式生成DataFrame
重复值处理
重复:
step1 .duplicated() 判断各行是否存在重复值
data['列名'].duplicated() / data.duplicated()
step2 .删除重复值
删除方法1:.drop_duplicates(列名,丢弃方法)
- first 只留第一个
- last 只留最后一个
- false 全部删除
删除方法2:.duplicated() + 判断表达式
raw_data[raw_data.duplicated()] # 结果表明,各行都不重复
# 注意!即使后面有和它重复的,第一次出现时仍然记作T
len(raw_data[raw_data.duplicated()] ) # 看重复的行数
# 写一个小判断,可以编成函数使用
if len(raw_data[raw_data.duplicated()])==0: # 看是否有重复
print('没有任何重复')
else:
print(raw_data[raw_data.duplicated()]) # 输出重复行
# 加入人为构造一个重复: 把第一行数据赋给第二行
raw_data.iloc[1, : ] = raw_data.iloc[0, :]
# 写一个小判断,可以编成函数使用
if len(raw_data[raw_data.duplicated()])==0: # 看是否有重复
print('没有任何重复')
else:
print(raw_data[raw_data.duplicated()]) # 输出重复行
店名 | 关键词 | 城市 | 评分 | 评价数 | 人均 | 地址 | 营业时间 | 菜名 |
---|
0
没有任何重复
店名 关键词 城市 评分 评价数 人均 地址 \
1 老北京涮羊肉 火锅 xa 4.4 877.0 45.5 西安市雁塔区朱雀大街250号东方大酒店西门斜对面(子午路站下车向北走60米路西)
营业时间 菜名
1 11:00-21:00 【羊肉】【豆腐】【麻酱】【精品肥牛】【粉丝】【羔羊肉】【牛肚】【油豆皮】【香菇】【豆皮】【土...
# 处理重复值,把店名当做唯一性的id
raw_data = raw_data.drop_duplicates(subset = ['店名']) # 含义:删除店名重复的数据,只保留第一条
# 或者用if duplicates 然后subset一下,与上面等价
raw_data = raw_data[raw_data['店名'].duplicated()==False]
# 当店名不是唯一id,只想删除完全重复两行,方法2更好
# 当希望通过几列共同判断时,maybe只有方法1可行
raw_data.shape
(698, 9)
缺失处理
isnull()作用于某一列或某几列——判断是否为缺失值
-
data.isnull().sum(axis = 0) 看各变量缺失总数
-
data['列名'].isnull() 某个变量具体缺失情况
-
data.dropna(axis=0, how='any', thresh = None, subset = None, inplace=True) 等价于na.omit
-
data[data['列名'].isnull() == False] 根据某个变量删除缺失
raw_data1 = pd.read_excel('https://github.com/xiangyuchang/xiangyuchang.github.io/blob/master/BearData/shops_nm.xlsx?raw=true')
### 导出缺失数据
raw_data1[raw_data1['评价数'].isnull()==True]
# subset保留无缺失的
raw_data2 = raw_data1[raw_data1['评价数'].isnull()==False]
raw_data2.shape
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-1-f7326fdcb62d> in <module>()
----> 1 raw_data1 = pd.read_excel('https://github.com/xiangyuchang/xiangyuchang.github.io/blob/master/BearData/shops_nm.xlsx?raw=true')
2
3 ### 导出缺失数据
4 raw_data1[raw_data1['评价数'].isnull()==True]
5
NameError: name 'pd' is not defined
0918 pandas继续
实例exercise
#### 读入
os.chdir("/Users/mac/Desktop/快乐研一/python/data")
import pandas as pd
gaokao = pd.read_csv("高考_numpy专用.csv")
gaokao.head()
gaokao.shape
gaokao.iloc[0,:]
大学名称 | 类型 | 重点学科 | 博士点 | 分数线 | |
---|---|---|---|---|---|
0 | 北京大学 | 综合 | 81.0 | 201.0 | 694.0 |
1 | 北京大学 | 综合 | 81.0 | 201.0 | 694.0 |
2 | 北京大学 | 综合 | 81.0 | 201.0 | 694.0 |
3 | 复旦大学 | 综合 | 30.0 | 178.0 | 687.0 |
4 | 清华大学 | 综合 | 37.0 | 253.0 | 686.0 |
(98, 5)
大学名称 北京大学
类型 综合
重点学科 81
博士点 201
分数线 694
Name: 0, dtype: object
#### 缺失值检查
# 看各变量中缺失值的数量
gaokao.isnull().sum(axis = 0) # 每一列缺失几项
gaokao.isnull().sum(axis = 0)/gaokao.shape[0] # 每个变量的缺失比例
#gaokao.isnull().sum(axis = 1) # 每一行缺失几项
#### 删除缺失
## 第一种:na.omit 对于包含任意缺失的行直接删除
gaokao.dropna(axis=0, how='any', thresh = None, subset = None, inplace=True)
gaokao.isnull().sum(axis = 0)
# axis 指 轴,0是行,1是列,
# how 是删除条件:any 任意一个为na则删除整行/列,all 整行/列为na才删除
# inplace 是否在原DataFrame 上进行删除,false为否
##第二种:subset,对某个变量缺失的列进行删除
gaokao1 = gaokao[gaokao['大学名称'].isnull() == False]
#gaokao.drop(labels = gaokao.index[data3['age'].isnull()], axis = 0) #这个和前一行效果一样
大学名称 2
类型 2
重点学科 4
博士点 4
分数线 4
dtype: int64
大学名称 0.020408
类型 0.020408
重点学科 0.040816
博士点 0.040816
分数线 0.040816
dtype: float64
大学名称 0
类型 0
重点学科 0
博士点 0
分数线 0
dtype: int64
#### 删除大学名称重复的行
gaokao2 = gaokao1[gaokao1['大学名称'].duplicated()==False]
gaokao1.shape[0]-gaokao2.shape[0]
3
各种切片操作
- data.iloc[n, m]
- data.loc[n,'列名']
“字符串+数字” 如何清洗变量
- 整理多余的字符为filter_words
- 判断是否包含这些filter_words
- replace(x, "") 删除字符串,只保留数字
raw_data1 = pd.read_excel('https://github.com/xiangyuchang/xiangyuchang.github.io/blob/master/BearData/shops_nm.xlsx?raw=true')
raw_data1.shape
(699, 9)
raw_data2 = raw_data1[raw_data1['评价数'].isnull()==False]
# 查看人均这一列前几行
renjun1 = raw_data2.loc[1,'人均']; [renjun1, type(renjun1)]
renjun2 = raw_data2.loc[2,'人均']; [renjun2, type(renjun2)]
# 整理出多余的字符
filter_words = ['大概','左右','人均','人均:','差不多',':']
# “大概92左右”——> 92
for wordi in filter_words:
if wordi in renjun2:
renjun2 = renjun2.replace(wordi,"")
int(renjun2)
# 再套一个对所有样本的循环,需要先判断是否为int
for i in raw_data2.index:
renjun = raw_data2.loc[i,'人均']
if type(renjun) is int or type(renjun) is float:
continue # 插入一个判断,如果不含字符跳过下面直接到赋值
for wordi in filter_words:
if wordi in renjun:
raw_data2.at[i,'人均'] = raw_data2.loc[i,'人均'].replace(wordi,"")
raw_data2['人均'] = raw_data2['人均'].astype(float) # 转换为float类型方便计算统计量
## 不显示warnings
import warnings
warnings.filterwarnings("ignore")
[56, int]
['大概92左右', str]
92
/Users/mac/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:25: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
描述统计量
raw_data2.describe()
评分 | 评价数 | 人均 | |
---|---|---|---|
count | 695.000000 | 695.000000 | 695.000000 |
mean | 4.025036 | 373.473381 | 53.533669 |
std | 1.449120 | 930.327264 | 47.406067 |
min | 0.000000 | 0.000000 | 5.000000 |
25% | 4.300000 | 5.000000 | 32.000000 |
50% | 4.500000 | 69.000000 | 43.000000 |
75% | 4.700000 | 301.500000 | 63.000000 |
max | 5.000000 | 9417.000000 | 548.000000 |
apply 加速循环
等价于for循环+if条件判断
# 定义function:
def clean_price(x):
filter_words = ['人均:', '人均', '大概', '左右', '差不多']
if type(x) is int or type(x) is float:
return x
for word in filter_words:
if word in x:
x = x.replace(word, '')
return x
raw_data2 = raw_data1[raw_data1['评价数'].isnull()==False]
# apply代替循环——应用该function
raw_data2['人均'] = raw_data2['人均'].apply(clean_price)
# 转化为float
raw_data2['人均'] = raw_data2['人均'].astype(float)
# 描述统计
raw_data2.describe()
评分 | 评价数 | 人均 | |
---|---|---|---|
count | 695.000000 | 695.000000 | 695.000000 |
mean | 4.025036 | 373.473381 | 53.533669 |
std | 1.449120 | 930.327264 | 47.406067 |
min | 0.000000 | 0.000000 | 5.000000 |
25% | 4.300000 | 5.000000 | 32.000000 |
50% | 4.500000 | 69.000000 | 43.000000 |
75% | 4.700000 | 301.500000 | 63.000000 |
max | 5.000000 | 9417.000000 | 548.000000 |
groupby & agg
key + data——字典分组非常快
data.groupby(by = 按某列分组).agg({"列名":"函数"})
def cate_shops(x):
if x>4.5:
return "高分"
if x>3 and x<=4.5:
return "中等"
if x<=3:
return "低分"
# 用apply完成对商家评分的分级
raw_data2['商家等级'] = raw_data2['评分'].apply(cate_shops) # 新建变量商家评价分级
raw_data2['商家等级'].value_counts() # 统计各类数量
# groupby+agg分组计算,等价于aggregate
# 看不同评分等级商家的平均人均
raw_data2.groupby(by = '商家等级').agg({'人均': "mean"})
高分 321
中等 290
低分 84
Name: 商家等级, dtype: int64
人均 | |
---|---|
商家等级 | |
中等 | 54.052414 |
低分 | 63.550000 |
高分 | 50.443925 |
merge
多表合并:暂时不学,用到再研究
- data.merge:两个表按照字段合并
- data.concat:连接 rbind & cbind(靠axis=0/1来控制)
输出excel
data.to_excel