目录
一、Pandas概括
1.什么是pandas
2.Pandas的安装
3.pandas的使用
4.小结
二、Pandas数据结构与数据类型
1.概念
2.series对象
2.1 创建Series对象
2.2 Series对象属性
3.DataFrame
3.1 创建DataFrame对象
3.2 DataFrame对象属性
3.3 DataFrame对象方法
3.4 DatatFrame索引的设置
4、Pandas的数据类型
小结
三、Pandas的基本操作
1.数据集准备
2、索引操作
2.1 直接使用行列索引(先列后行)
2.2 结合loc或者iloc使用索引
3、赋值操作
4、排序操作
4.1 DataFrame排序
4.2 Series排序
小结
四、DataFrame运算
1、算法运算
2、逻辑运算符
2.1 逻辑运算符号
2.2 逻辑运算函数
3、统计运算
3.1 describe
3.2 统计函数
3.3 累计统计函数
3.4 apply自定义运算⭐
小结
五、文件的读取与存储
1、CSV
1.1 read_csv
1.2 to_csv
2、MySQL
3、JSON
3.1 read_json
3.2 read_json案例
3.3 to_json
3.4 案例
4 小结
六、DataFrame数据的增删改查操作
1、增加列
2、删除与去重
3、修改DataFrame中的数据
4、查询dataFrame中的数据
七、高级处理-确实值处理
1、如何处理NAN
2、电影数据的缺失值处理
3、判断缺失值是否存在
4、存在缺失值nan,并且是np.nan
5、不是缺失值nan,有默认标记的
小结
八、高级处理-数据合并
1、pd.concat实现数据合并
2、pd.merge
小结
九、高级处理-数据分组
1、数据准备
2、groupby分组聚合
3、分组过滤操作
3、透视表
4、案例分析
4.1 数据准备
4.2 查看效果
4.3 使用pivot_table(透视表)实现
小结
一、Pandas概括
1.什么是pandas
Python在数据处理上独步天下:代码灵活、开发快速;尤其是Python的Pandas包,无论是在数据分析领域、还是大数据开发场景中都具有显著的优势:
-
Pandas是Python的一个第三方包,也是商业和工程领域最流行的结构化数据工具集,用于数据清洗、处理以及分析
-
Pandas在数据处理上具有独特的优势:
-
底层是基于Numpy构建的,所以运行速度特别的快
-
有专门的处理缺失数据的API
-
强大而灵活的分组、聚合、转换功能
-
适用场景:
-
数据量大到Excel严重卡顿,且又都是单机数据的时候,我们使用Pandas
-
Pandas用于处理单机数据(小数据集(相对于大数据来说))
-
-
在大数据ETL数据仓库中,对数据进行清洗及处理的环节使用Pandas
2.Pandas的安装
打开cmd窗口,输入命令
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pandas
3.pandas的使用
1.准备一个数据表
2.创建一个jupyter 文件
3.导入pandas库
import pandas as pd
4.基于pandas加载数据
df = pd.read_csv('./1960-2019全球GDP数据.csv', encoding='gbk')
5.基于pandas完成相关查询
# 查询中国的GDP
china_gdp = df[df.country=='中国'] # df.country 选中名为country的列
china_gdp.head(10) # 显示前10条数据
4.小结
Python Pandas的作用:(清洗、处理、分析数据)
Pandas环境搭建:
-
安装Anaconda,默认自带Python以及其他相关三方包
-
使用默认的base虚拟环境启动
JupyterNotebook
二、Pandas数据结构与数据类型
1.概念
上图为上一节中读取并展示出来的数据,以此为例我们来讲解Pandas的核心概念,以及这些概念的层级关系:
-
DataFrame
-
Series
-
索引列
-
索引名、索引值
-
索引下标、行号
-
-
数据列
-
列名
-
列值,具体的数据
-
-
-
其中最核心的就是Pandas中的两个数据结构:DataFrame和Series
2.series对象
Series也是Pandas中的最基本的数据结构对象,下文中简称s对象;是DataFrame的列对象,series本身也具有索引。
Series是一种类似于一维数组的对象,由下面两个部分组成:
-
values:一组数据(numpy.ndarray类型)
-
index:相关的数据索引标签;如果没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引。
2.1 创建Series对象
-
1- 导入pandas
import pandas as pd
-
2- 通过list列表来创建
# 使用默认自增索引 s2 = pd.Series([1, 2, 3]) print(s2) # 自定义索引 s3 = pd.Series([1, 2, 3], index=['A', 'B', 'C']) s3 结果为: 0 1 1 2 2 3 dtype: int64 A 1 B 2 C 3 dtype: int64
-
3- 使用字典或元组创建series对象
#使用元组 tst = (1,2,3,4,5,6) pd.Series(tst) #使用字典: dst = {'A':1,'B':2,'C':3,'D':4,'E':5,'F':6} pd.Series(dst)
-
4- 使用numpy创建series对象
pd.Series(np.arange(10)) # 运行结果 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 dtype: int64
2.2 Series对象属性
构造一个series对象
s4 = pd.Series([i for i in range(6)], index=[i for i in 'ABCDEF']) s4 # 返回结果如下 A 0 B 1 C 2 D 3 E 4 F 5 dtype: int64
-
1- series对象常用属性
s4.index
-
2- values
s4.values
-
3- 也可以通过索引来获取数据
s4['A']
3.DataFrame
3.1 创建DataFrame对象
DataFrame是一个类似于二维数组或表格(如excel)的对象,既有行索引,又有列索引
-
行索引,表明不同行,横向索引,叫index,0轴,axis=0
-
列索引,表名不同列,纵向索引,叫columns,1轴,axis=1
DataFrame的创建有很多种方式
读取文件数据返回df:在之前我们使用了pd.read_csv('csv格式数据文件路径')
的方式获取了df对象
使用字典、列表、元组创建df:接下来就展示如何使用字典、列表+元组、numpy创建df对象
-
1- 使用字典加列表创建df,使默认自增索引
df1_data = {'日期': ['2021-08-21', '2021-08-22', '2021-08-23'],'温度': [25, 26, 50],'湿度': [81, 50, 56] } df1 = pd.DataFrame(data=df1_data) df1 # 返回结果如下日期 温度 湿度 0 2021-08-21 25 81 1 2021-08-22 26 50 2 2021-08-23 50 56
-
2- 使用列表加元组创建df,并自定义索引
df2_data = [('2021-08-21', 25, 81),('2021-08-22', 26, 50),('2021-08-23', 27, 56) ] df2 = pd.DataFrame(data=df2_data, columns=['日期', '温度', '湿度'],index = ['row_1','row_2','row_3'] # 手动指定索引 ) df2 # 返回结果如下日期 温度 湿度 row_1 2021-08-21 25 81 row_2 2021-08-22 26 50 row_3 2021-08-23 27 56
-
3- 使用numpy创建df
通过已有数据创建
pd.DataFrame(np.random.randn(2,3)) # 2行3列
创建学生成绩表
# 生成10名同学,5门功课的数据 score = np.random.randint(40, 100, (10, 5)) # 结果 array([[92, 55, 78, 50, 50],[71, 76, 50, 48, 96],[45, 84, 78, 51, 68],[81, 91, 56, 54, 76],[86, 66, 77, 67, 95],[46, 86, 56, 61, 99],[46, 95, 44, 46, 56],[80, 50, 45, 65, 57],[41, 93, 90, 41, 97],[65, 83, 57, 57, 40]])
但是这样的数据形式很难看到存储的是什么的样的数据,可读性比较差!
问题:如何让数据更有意义的显示?
# 使用Pandas中的数据结构 score_df = pd.DataFrame(score)
给分数数据增加行列索引,显示效果更佳
增加行、列索引
# 构造行索引序列 subjects = ["语文", "数学", "英语", "政治", "体育"] # 构造列索引序列 stu = ['同学' + str(i) for i in range(score_df.shape[0])] # 添加行索引 data = pd.DataFrame(score, columns=subjects, index=stu)
3.2 DataFrame对象属性
属性
-
1- shape属性
data.shape # 结果 (10, 5)
-
2- index属性
DataFrame的行索引列表
data.index # 结果 Index(['同学0', '同学1', '同学2', '同学3', '同学4', '同学5', '同学6', '同学7', '同学8', '同学9'], dtype='object')
-
3- columns
data.columns # 结果 Index(['语文', '数学', '英语', '政治', '体育'], dtype='object')
-
4- values
直接获取其中array的值
data.values array([[92, 55, 78, 50, 50],[71, 76, 50, 48, 96],[45, 84, 78, 51, 68],[81, 91, 56, 54, 76],[86, 66, 77, 67, 95],[46, 86, 56, 61, 99],[46, 95, 44, 46, 56],[80, 50, 45, 65, 57],[41, 93, 90, 41, 97],[65, 83, 57, 57, 40]])
-
5- T
转置
data.T
结果
3.3 DataFrame对象方法
1- head(n)
显示前n行内容
data.head(5)
2- tail(n)
显示后n行内容
如果不补充参数,默认5行。填入参数n则显示后n行
data.tail(5)
....其他的方法自己测试...
3.4 DatatFrame索引的设置
需求:
-
1- 修改行列索引值
stu = ["学生_" + str(i) for i in range(score_df.shape[0])] # 必须整体全部修改 data.index = stu
注意:以下修改方式是错误的
# 错误修改方式 data.index[3] = '学生_3'
-
2- 重设索引
-
reset_index(drop=False)
-
设置新的下标索引
-
drop:默认为False,不删除原来索引,如果为True,删除原来的索引值
-
-
# 重置索引,drop=False data.reset_index()
# 重置索引,drop=True data.reset_index(drop=True)
-
3- 以某列值设置为新的索引
-
set_index(keys, drop=True)
-
keys : 列索引名成或者列索引名称的列表
-
drop : boolean, default True.当做新的索引,删除原来的列
-
-
设置新索引案例
第一步:创建
df = pd.DataFrame({'month': [1, 4, 7, 10],'year': [2012, 2014, 2013, 2014],'sale':[55, 40, 84, 31]}) month sale year 0 1 55 2012 1 4 40 2014 2 7 84 2013 3 10 31 2014
第二步:以月份设置新的索引
df.set_index('month')sale year month 1 55 2012 4 40 2014 7 84 2013 10 31 2014
第三步:设置多个索引,以年和月份
df = df.set_index(['year', 'month']) dfsale year month 2012 1 55 2014 4 40 2013 7 84 2014 10 31
4、Pandas的数据类型
df或s对象中具体每一个值的数据类型有很多,如下表所示
Pandas数据类型 | 说明 | 对应的Python类型 |
---|---|---|
Object | 字符串类型 | string |
int | 整数类型 | int |
float | 浮点数类型 | float |
datetime | 日期时间类型 | datetime包中的datetime类型 |
timedelta | 时间差类型 | datetime包中的timedelta类型 |
category | 分类类型 | 无原生类型,可以自定义 |
bool | 布尔类型 | bool(True,False) |
nan | 空值类型 | None |
-
可以通过下列API查看s对象或df对象中数据的类型
s1.dtypes df1.dtypes df1.info()
-
几个特殊类型演示
-
datetime类型
import pandas as pd # 创建一个datetime类型的Series dates = pd.to_datetime(['2024-09-01', '2024-09-02', '2024-09-03']) print(dates)
-
timedelta类型
import pandas as pd # 计算两个日期之间的差值 start_date = pd.to_datetime('2024-09-01') end_date = pd.to_datetime('2024-09-05') delta = end_date - start_date print(delta)
-
category类型
类型用于表示分类数据,通常用于有限集合中的数据类型,例如性别、颜色、产品类型等。这种类型的优点在于占用更少的内存,并且对分类数据的操作更快。
import pandas as pd # 创建一个category类型的Series categories = pd.Series(['apple', 'banana', 'apple', 'orange'], dtype='category') print(categories)
-
小结
-
series
-
创建
-
pd.Series([], index=[])
-
pd.Series({})
-
-
属性
-
对象.index
-
对象.values
-
-
-
DataFrame
-
创建
-
pd.DataFrame(data=None, index=None, columns=None)
-
-
属性
-
shape -- 形状
-
index -- 行索引
-
columns -- 列索引
-
values -- 查看值
-
T -- 转置
-
head() -- 查看头部内容
-
tail() -- 查看尾部内容
-
-
DataFrame索引
-
修改的时候,需要进行全局修改
-
对象.reset_index()
-
对象.set_index(keys)
-
-
三、Pandas的基本操作
1.数据集准备
准备文件,作为数据来源,最好先以.csv为结尾的表格,举例如下:
# 读取文件
data = pd.read_csv("./data/stock_day.csv")
# 删除一些列,让数据更简单些,再去做后面的操作
data = data.drop(["ma5","ma10","ma20","v_ma5","v_ma10","v_ma20"], axis=1)
2、索引操作
2.1 直接使用行列索引(先列后行)
获取'2018-02-27'这天的'open'的结果
# 直接使用行列索引名字的方式(先列后行) data['open']['2018-02-27'] 23.53 # 不支持的操作 # 错误 data['2018-02-27']['open'] # 错误 data[:1, :2]
2.2 结合loc或者iloc使用索引
获取从'2018-02-27':'2018-02-22','open'的结果
# 使用loc:只能指定行列索引的名字 data.loc['2018-02-27':'2018-02-22', 'open'] 2018-02-27 23.53 2018-02-26 22.80 2018-02-23 22.88 Name: open, dtype: float64 # 使用iloc可以通过索引的下标去获取 # 获取前3天数据,前5列的结果 data.iloc[:3, :5] open high close low 2018-02-27 23.53 25.88 24.16 23.53 2018-02-26 22.80 23.78 23.53 22.80 2018-02-23 22.88 23.37 22.82 22.71
3、赋值操作
对DataFrame当中的close列进行重新赋值为1
# 直接修改原来的值 data['close'] = 1 # 或者 data.close = 1
4、排序操作
排序有两种形式,一种对于索引进行排序,一种对于内容进行排序
4.1 DataFrame排序
-
使用df.sort_values(by=, ascending=)
-
单个键或者多个键进行排序,
-
参数:
-
by:指定排序参考的键
-
ascending:默认升序
-
ascending=False:降序
-
ascending=True:升序
-
-
-
# 按照开盘价大小进行排序 , 使用ascending指定按照大小排序
data.sort_values(by="open", ascending=True).head()
# 按照多个键进行排序
data.sort_values(by=['open', 'high'])
-
使用df.sort_index给索引进行排序
这个股票的日期索引原来是从大到小,现在重新排序,从小到大
# 对索引进行排序 data.sort_index()
4.2 Series排序
-
使用series.sort_values(ascending=True)进行排序
series排序时,只有一列,不需要参数
data['p_change'].sort_values(ascending=True).head() 2015-09-01 -10.03 2015-09-14 -10.02 2016-01-11 -10.02 2015-07-15 -10.02 2015-08-26 -10.01 Name: p_change, dtype: float64
-
使用series.sort_index()进行排序
与df一致
# 对索引进行排序 data['p_change'].sort_index().head() 2015-03-02 2.62 2015-03-03 1.44 2015-03-04 1.57 2015-03-05 2.02 2015-03-06 8.51 Name: p_change, dtype: float64
小结
-
1.索引
-
直接索引 -- 先列后行,是需要通过索引的字符串进行获取
-
loc -- 先行后列,是需要通过索引的字符串进行获取
-
iloc -- 先行后列,是通过下标进行索引
-
-
2.赋值
-
data[""] = **
-
data. =
-
-
3.排序
-
dataframe
-
对象.sort_values()
-
对象.sort_index()
-
-
series
-
对象.sort_values()
-
对象.sort_index()
-
-
四、DataFrame运算
-
应用add等实现数据间的加、减法运算
-
应用逻辑运算符号实现数据的逻辑筛选
-
应用isin, query实现数据的筛选
-
使用describe完成综合统计
-
使用max, min, mean, std完成统计计算
-
使用idxmin、idxmax完成最大值最小值的索引
-
使用cumsum等实现累计分析
-
应用apply函数实现数据的自定义处理
1、算法运算
-
add(other)
比如进行数学运算加上具体的一个数字
data['open'].add(1)
data,time open
2018-02-27 24.53 (执行后open列数值+1)
2018-02-26 23.80
2018-02-23 23.88
2018-02-22 23.25
2018-02-14 22.49
-
sub(other)
比如进行数学运算减去具体的一个数字
data['open'].sub(1)
2、逻辑运算符
2.1 逻辑运算符号
-
例如筛选data["open"] > 23的日期数据
-
data["open"] > 23返回逻辑结果
-
data["open"] > 23 2018-02-27 True 2018-02-26 False 2018-02-23 False 2018-02-22 False 2018-02-14 False # 逻辑判断的结果可以作为筛选的依据 data[data["open"] > 23].head()
-
完成多个逻辑判断,
data[(data["open"] > 23) & (data["open"] < 24)].head()
2.2 逻辑运算函数
-
query(expr)
-
expr:查询字符串
-
通过query使得刚才的过程更加方便简单
data.query("open<24 & open>23").head()
-
isin(values)
例如判断'open'是否为23.53和23.85
# 可以指定值进行一个判断,从而进行筛选操作 data[data["open"].isin([23.53, 23.85])]
3、统计运算
3.1 describe
综合分析: 能够直接得出很多统计结果,count
, mean
, std
, min
, max
等
# 计算平均值、标准差、最大值、最小值 data.describe()
3.2 统计函数
在这里演示min(最小值), max(最大值), mean(平均值), median(中位数), var(方差), std(标准差),mode(众数)结果:
count | Number of non-NA observations |
---|---|
sum | Sum of values |
mean | Mean of values |
median | Arithmetic median of values |
min | Minimum |
max | Maximum |
mode | Mode(众数) |
abs | Absolute Value |
prod | Product of values(乘积) |
std | Bessel-corrected sample standard deviation |
var | Unbiased variance |
idxmax | compute the index labels with the maximum |
idxmin | compute the index labels with the minimum |
对于单个函数去进行统计的时候,坐标轴还是按照默认列“columns” (axis=0, default),如果要对行“index” 需要指定(axis=1)
-
max()、min()
# 使用统计函数:0 代表列求结果, 1 代表行求统计结果 data.max(0) open 34.99 high 36.35 close 35.21 low 34.01 volume 501915.41 price_change 3.03 p_change 10.03 turnover 12.56 my_price_change 3.41 dtype: float64
-
std()、var()
# 方差 data.var(0) open 1.545255e+01 high 1.662665e+01 close 1.554572e+01 low 1.437902e+01 volume 5.458124e+09 price_change 8.072595e-01 p_change 1.664394e+01 turnover 4.323800e+00 my_price_change 6.409037e-01 dtype: float64 # 标准差 data.std(0) open 3.930973 high 4.077578 close 3.942806 low 3.791968 volume 73879.119354 price_change 0.898476 p_change 4.079698 turnover 2.079375 my_price_change 0.800565 dtype: float64
-
median():中位数
中位数为将数据从小到大排列,在最中间的那个数为中位数。如果没有中间数,取中间两个数的平均值。
df = pd.DataFrame({'COL1' : [2,3,4,5,4,2], 'COL2' : [0,1,2,3,4,2]}) df.median() COL1 3.5 COL2 2.0 dtype: float64
-
idxmax()、idxmin()
# 求出最大值的位置 data.idxmax(axis=0) open 2015-06-15 high 2015-06-10 close 2015-06-12 low 2015-06-12 volume 2017-10-26 price_change 2015-06-09 p_change 2015-08-28 turnover 2017-10-26 my_price_change 2015-07-10 dtype: object # 求出最小值的位置 data.idxmin(axis=0) open 2015-03-02 high 2015-03-02 close 2015-09-02 low 2015-03-02 volume 2016-07-06 price_change 2015-06-15 p_change 2015-09-01 turnover 2016-07-06 my_price_change 2015-06-15 dtype: object
3.3 累计统计函数
函数 | 作用 |
---|---|
cumsum | 计算前1/2/3/…/n个数的和 |
cummax | 计算前1/2/3/…/n个数的最大值 |
cummin | 计算前1/2/3/…/n个数的最小值 |
cumprod | 计算前1/2/3/…/n个数的积 |
那么这些累计统计函数怎么用?
以上这些函数可以对series和dataframe操作
这里我们按照时间的从前往后来进行累计
-
排序
# 排序之后,进行累计求和 data = data.sort_index()
-
对p_change进行求和
stock_rise = data['p_change'] # plot方法集成了前面直方图、条形图、饼图、折线图 stock_rise.cumsum() 2015-03-02 2.62 2015-03-03 4.06 2015-03-04 5.63 2015-03-05 7.65 2015-03-06 16.16 2015-03-09 16.37 2015-03-10 18.75 2015-03-11 16.36 2015-03-12 15.03 2015-03-13 17.58 2015-03-16 20.34 2015-03-17 22.42 2015-03-18 23.28 2015-03-19 23.74 2015-03-20 23.48 2015-03-23 23.74
那么如何让这个连续求和的结果更好的显示呢?
使用plot函数,需要导入matplotlib.
import matplotlib.pyplot as plt # plot显示图形 stock_rise.cumsum().plot() # 需要调用show,才能显示出结果 plt.show()
3.4 apply自定义运算⭐
-
apply(func, axis=0)
-
func:自定义函数
-
axis=0:默认是列,axis=1为行进行运算
-
-
定义一个对列,最大值-最小值的函数
data[['open', 'close']].apply(lambda x: x.max() - x.min(), axis=0) open 22.74 close 22.85 dtype: float64
小结
-
算术运算
-
逻辑运算
-
1.逻辑运算符号
-
2.逻辑运算函数
-
对象.query()
-
对象.isin()
-
-
-
统计运算
-
1.对象.describe()
-
2.统计函数
-
3.累积统计函数
-
-
自定义运算
-
apply(func, axis=0)
-
五、文件的读取与存储
我们的数据大部分存在于文件当中,所以pandas会支持复杂的IO操作,pandas的API支持众多的文件格式,如CSV、SQL、XLS、JSON、HDF5。
1、CSV
1.1 read_csv
-
pandas.read_csv(filepath_or_buffer, sep =',', usecols )
-
filepath_or_buffer:文件路径
-
sep :分隔符,默认用","隔开
-
usecols:指定读取的列名,列表形式
-
-
举例:读取之前的股票的数据
# 读取文件,并且指定只获取'open', 'close'指标 data = pd.read_csv("./data/stock_day.csv", usecols=['open', 'close']) open close 2018-02-27 23.53 24.16 2018-02-26 22.80 23.53 2018-02-23 22.88 22.82 2018-02-22 22.25 22.28 2018-02-14 21.49 21.92
1.2 to_csv
-
DataFrame.to_csv(path_or_buf=None, sep=', ’, columns=None, header=True, index=True, mode='w', encoding=None)
-
path_or_buf :文件路径
-
sep :分隔符,默认用","隔开
-
columns :选择需要的列索引
-
header :boolean or list of string, default True
-
index:是否写进行索引,是否写进列索引值
-
mode:'w':重写, 'a' 追加
-
-
举例:保存读取出来的股票数据
-
保存'open'列的数据,然后读取查看结果
-
# 选取10行数据保存,便于观察数据 data[:10].to_csv("./data/test.csv", columns=['open']) # 读取,查看结果 pd.read_csv("./data/test.csv") Unnamed: 0 open 0 2018-02-27 23.53 1 2018-02-26 22.80 2 2018-02-23 22.88 3 2018-02-22 22.25 4 2018-02-14 21.49 5 2018-02-13 21.40 6 2018-02-12 20.70 7 2018-02-09 21.20 8 2018-02-08 21.79 9 2018-02-07 22.69
会发现将索引存入到文件当中,变成单独的一列数据。如果需要删除,可以指定index参数,删除原来的文件,重新保存一次。
# index:存储不会讲索引值变成一列数据 data[:10].to_csv("./data/test.csv", columns=['open'], index=False)
2、MySQL
以MySQL数据库为例,此时默认你已经在本地安装好了MySQL数据库。如果想利用pandas和MySQL数据库进行交互,需要先安装与数据库交互所需要的python包
pip install pymysql==1.0.2 -i https://pypi.tuna.tsinghua.edu.cn/simple/ # 如果后边的代码运行提示找不到sqlalchemy的包,和pymysql一样进行安装即可 pip install sqlalchemy==2.0.0 -i https://pypi.tuna.tsinghua.edu.cn/simple/
-
准备要写入数据库的数据
import pandas as pd df = pd.read_csv('./csv示例文件.csv', sep=',', index_col=[0]) df
-
创建数据库操作引擎对象并指定数据库
# 需要安装pymysql,部分版本需要额外安装sqlalchemy # 导入sqlalchemy的数据库引擎 from sqlalchemy import create_engine # 创建数据库引擎,传入uri规则的字符串 engine = create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/test,charset=utf8') # mysql+pymysql://root:123456@127.0.0.1:3306/test?charset=utf8 # mysql 表示数据库类型 # pymysql 表示python操作数据库的包 # root:123456 表示数据库的账号和密码,用冒号连接 # 127.0.0.1:3306/test 表示数据库的ip和端口,以及名叫test的数据库 # charset=utf8 规定编码格式
-
将数据写入MySQL数据库
# df.to_sql()方法将df数据快速写入数据库
df.to_sql('test_pdtosql', engine, index=False, if_exists='append')
# 第一个参数为数据表的名称
# 第二个参数engine为数据库交互引擎
# index=False 表示不添加自增主键
# if_exists='append' 表示如果表存在就添加,表不存在就创建表并写入
-
此时我们就可以在本地test库的test_pdtosql表中看到写入的数据
-
从数据库中加载数据:
-
读取整张表, 返回dataFrame
from sqlalchemy import create_engine engine = create_engine('mysql+pymysql://root:root@127.0.0.1:3306/test?charset=utf8') # 指定表名,传入数据库连接引擎对象 pd.read_sql('test_pdtosql', engine)
-
使用SQL语句获取数据,返回dataframe
# 传入sql语句,传入数据库连接引擎对象 pd.read_sql('select name,AKA from test_pdtosql', engine)
-
可能出现的问题:
说明: sqlalche 库版本过低导致的 解决方案:先删除原有版本: pip uninstall sqlalchemy重新安装:pip install sqlalchemy==1.4.31
3、JSON
JSON是我们常用的一种数据交换格式,前面在前后端的交互经常用到,也会在存储的时候选择这种格式。所以我们需要知道Pandas如何进行读取和存储JSON格式。
3.1 read_json
-
pandas.read_json(path_or_buf=None, orient=None, typ='frame', lines=False)
-
将JSON格式准换成默认的Pandas DataFrame格式
-
orient : string,Indication of expected JSON string format.
-
'split' : dict like {index -> [index], columns -> [columns], data -> [values]}
-
split 将索引总结到索引,列名到列名,数据到数据。将三部分都分开了
-
-
'records' : list like [{column -> value}, ... , {column -> value}]
-
records 以
columns:values
的形式输出
-
-
'index' : dict like {index -> {column -> value}}
-
index 以
index:{columns:values}...
的形式输出
-
-
'columns' : dict like {column -> {index -> value}}
,默认该格式
-
colums 以
columns:{index:values}
的形式输出
-
-
'values' : just the values array
-
values 直接输出值
-
-
-
lines : boolean, default False
-
按照每行读取json对象
-
-
typ : default ‘frame’, 指定转换成的对象类型series或者dataframe
-
3.2 read_json案例
-
数据介绍
这里使用一个新闻标题讽刺数据集,格式为json。is_sarcastic
:1讽刺的,否则为0;headline
:新闻报道的标题;article_link
:链接到原始新闻文章。存储格式为:
{"article_link": "https://www.huffingtonpost.com/entry/versace-black-code_us_5861fbefe4b0de3a08f600d5", "headline": "former versace store clerk sues over secret 'black code' for minority shoppers", "is_sarcastic": 0} {"article_link": "https://www.huffingtonpost.com/entry/roseanne-revival-review_us_5ab3a497e4b054d118e04365", "headline": "the 'roseanne' revival catches up to our thorny political mood, for better and worse", "is_sarcastic": 0}
-
读取
orient指定存储的json格式,lines指定按照行去变成一个样本
json_read = pd.read_json("./data/Sarcasm_Headlines_Dataset.json", orient="records", lines=True)
结果:
3.3 to_json
-
DataFrame.to_json(path_or_buf=None,orient=None,lines=False)
-
将Pandas 对象存储为json格式
-
path_or_buf=None:文件地址
-
orient:存储的json形式,{‘split’,’records’,’index’,’columns’(默认),’values’}
-
lines:一个对象存储为一行
-
3.4 案例
-
存储文件
json_read.to_json("./data/test.json", orient='records')
结果
[{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/versace-black-code_us_5861fbefe4b0de3a08f600d5","headline":"former versace store clerk sues over secret 'black code' for minority shoppers","is_sarcastic":0},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/roseanne-revival-review_us_5ab3a497e4b054d118e04365","headline":"the 'roseanne' revival catches up to our thorny political mood, for better and worse","is_sarcastic":0},{"article_link":"https:\/\/local.theonion.com\/mom-starting-to-fear-son-s-web-series-closest-thing-she-1819576697","headline":"mom starting to fear son's web series closest thing she will have to grandchild","is_sarcastic":1},{"article_link":"https:\/\/politics.theonion.com\/boehner-just-wants-wife-to-listen-not-come-up-with-alt-1819574302","headline":"boehner just wants wife to listen, not come up with alternative debt-reduction ideas","is_sarcastic":1},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/jk-rowling-wishes-snape-happy-birthday_us_569117c4e4b0cad15e64fdcb","headline":"j.k. rowling wishes snape happy birthday in the most magical way","is_sarcastic":0},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/advancing-the-worlds-women_b_6810038.html","headline":"advancing the world's women","is_sarcastic":0},....]
-
修改lines参数为True
json_read.to_json("./data/test.json", orient='records', lines=True)
结果
{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/versace-black-code_us_5861fbefe4b0de3a08f600d5","headline":"former versace store clerk sues over secret 'black code' for minority shoppers","is_sarcastic":0} {"article_link":"https:\/\/www.huffingtonpost.com\/entry\/roseanne-revival-review_us_5ab3a497e4b054d118e04365","headline":"the 'roseanne' revival catches up to our thorny political mood, for better and worse","is_sarcastic":0} {"article_link":"https:\/\/local.theonion.com\/mom-starting-to-fear-son-s-web-series-closest-thing-she-1819576697","headline":"mom starting to fear son's web series closest thing she will have to grandchild","is_sarcastic":1} {"article_link":"https:\/\/politics.theonion.com\/boehner-just-wants-wife-to-listen-not-come-up-with-alt-1819574302","headline":"boehner just wants wife to listen, not come up with alternative debt-reduction ideas","is_sarcastic":1} {"article_link":"https:\/\/www.huffingtonpost.com\/entry\/jk-rowling-wishes-snape-happy-birthday_us_569117c4e4b0cad15e64fdcb","headline":"j.k. rowling wishes snape happy birthday in the most magical way","is_sarcastic":0}...
4 小结
-
pandas的CSV、MySQL、JSON文件的读取
-
对象.read_()
-
对象.to_()
-
六、DataFrame数据的增删改查操作
1、增加列
-
方式一: 通过直接赋值的方式添加新列
# 拷贝一份df df3 = df2.copy() # 一列数据都是固定值 df3['new col 1'] = 33 # 新增列数据数量必须和行数相等 df3['new col 2'] = [1, 2, 3, 4, 5] df3['new col 3'] = df3.year * 2 # 分别查看增加数据列之后的df和原df df3 df2
-
方式二: df.assign函数添加列
# 1. 新列名=单个数据或一组数据,一组数据的数量必须和df的行数相同 df2.assign(new0=66) # df2.assign(new1=[1, 2, 3, 4]) # 报错 df2.assign(new1=[1, 2, 3, 4, 5]) # 2.1 新列名=Series对象,该s对象的索引和df索引一致 s = pd.Series([1, 2, 3, 4, 5]) df2.assign(new2=s) # 2.2 新列名=Series对象 df2.assign(new3=df2.year+df2.GDP) # 3. 新列名=自定义函数名 # 该自定义函数必须接收df作为参数 # 该自定义函数可以返回: # 3.1.单个数据 # 3.2.一组数量和df的行数相同的数据 # 3.3.和df索引相同的Series对象 def foo(df):# 函数必须接收一个参数,该参数就是被传入的df对象print('='*10)print(df)print('='*5 + '上面输出的是传入的df')ret = df.index.values# 可以返回一个变量# return 'hahah'# 也可以返回一组变量return ret df2.assign(new4=foo) 解析:当我们使用函数的方式向df对象添加新列时,foo函数要求必须有一个参数,这个参数来自于调用assign的df对象,如上图所示 当我们给foo(df)定义一个df参数时,当assign方法开始执行,则系统会自动将df2对象作为参数传递给foo函数中的df参数
-
df.assign函数可以同时添加多列
df2 def foo(df):return 22 def bar(df):return df.year + 1 df2.assign(new0='hahaha',new1=[1, 2, 3, 4, 5],new2=pd.Series([1, 2, 3, 4, 5]),new3=df.year*2,new4=foo,new5=bar )
2、删除与去重
-
1- df.drop删除行数据
df3.drop([0]) # 默认删除行 df3.drop([0, 2, 4]) # 可以删除多行 df3.GDP.drop([0, 2]) # 对series对象按索引删除
-
2- df.drop删除列数据
-
df.drop默认删除指定索引值的行;如果添加参数
axis=1
,则删除指定列名的列
-
df3.drop(['new col 3'], axis=1)
-
3- 使用del删除指定的列
-
注意区别:
-
del是直接永久删除原df中的列【慎重使用】
-
drop是返回删除后的df或seires,原df或seires没有被修改
-
-
del df3['new col 3'] df3 # 重复运行本段代码将会报错,因为df3中的指定列在第一次运行时就被删除了
-
4- Dataframe数据去重
# 添加一部分重复的数据 df4 = df2.append(df2).reset_index(drop=True) # 实施去重操作 df4.drop_duplicates()
-
5- series去重
方式一: df4.country.drop_duplicates() # 返回结果如下 0 美国 1 英国 2 法国 3 中国 4 日本 Name: country, dtype: object 方式二: df4.country.unique() # 返回结果如下 array(['美国', '英国', '法国', '中国', '日本'], dtype=object)
3、修改DataFrame中的数据
-
1- df.assign替换列
df = pd.read_csv('../数据集/1960-2019全球GDP数据.csv', encoding='gbk', ) df5 = df.head() df5 df5.assign(GDP=66) # 可以接收单变量或列表、数组 df5 # 此时原始的df5不会发生改变
-
2- 直接对原始的DF进行赋值修改处理
-
一般不建议直接修改操作
-
df = pd.read_csv('../数据集/1960-2019全球GDP数据.csv', encoding='gbk', ) df5 = df.head() df5 df5['GDP'] = [5, 4, 3, 2, 1] df5 # 此时原始的df5会发生改变
-
3- replace函数替换数据
# 读取数据选取前5行作为一个新的df df = pd.read_csv('../数据集/1960-2019全球GDP数据.csv', encoding='gbk', ) df6 = df.head() df6 # series对象替换数据,返回的还是series对象,不会对原来的df造成修改 df6.year.replace(1960, 19600) df6 # 如果加上inplace=True参数,则会修改原始df df6.country.replace('日本', '扶桑', inplace=True) df6 # df也可以直接调用replace函数,用法和s.replace用法一致,只是返回的是df对象 df6.replace(1960, 19600) df6 备注:replace()是按照单元格元素值进行完全匹配
4、查询dataFrame中的数据
-
1- 从前从后取多行数据
-
head()
# 导包 import pandas as pd # 加载csv数据,指定gbk编码格式来读取文件,返回df df = pd.read_csv('../数据集/1960-2019全球GDP数据.csv', encoding='gbk') # 默认取前5行数据 df.head() df.head(10) # 取前10行
-
tail()
# 默认取后5行数据 df.tail() df2 = df.tail(15) # 倒数15行 df2
-
-
2- 获取一列或多列数据
-
获取一列数据
df[col_name]
等同于df.col_name
df2['country'] df2.country # 注意!如果列名字符串中间有空格的,只能使用df['country']这种形式
-
获取多列数据
df[[col_name1,col_name2,...]]
df2[['country', 'GDP']] # 返回新的df
-
-
3- 索引下标切片取行
-
df[start:stop:step]
:
df[start:stop:step]
==df[起始行下标:结束行下标:步长]
,遵循
顾头不顾尾
原则(包含起始行,不包含结束行),步长
默认为1df4 = df.head(10) # 取原df前10行数据作为df4,默认自增索引由0到9 df4[0:3] # 取前3行 df4[:5:2] # 取前5行,步长为2 df4[1::3] # 取第2行到最后所有行,步长为3
-
-
4- 查询函数获取子集: df.query()
-
df.query(判断表达式)
可以依据判断表达式返回的符合条件的df子集 -
与
df[布尔值向量]
效果相同 -
特别注意
df.query()
中传入的字符串格式
-
示例:
df3.query('country=="帕劳"') df3[df3['country']=='帕劳']
-
查询中国, 美国 日本 三国 2015年至2019年的数据
df.query('country=="中国" or country=="日本" or country=="美国"').query('year in ["2015", "2016", "2017", "2018", "2019"]') df.query('(country=="中国" or country=="日本" or country=="美国") and year in ["2015", "2016", "2017", "2018", "2019"]')
-
-
5- 排序函数
-
sort_values函数: 按照指定的一列或多列的值进行排序
# 按GDP列的数值由小到大进行排序 df2.sort_values(['GDP']) # 按GDP列的数值由大到小进行排序 df2.sort_values(['GDP'], ascending=False) # 倒序, ascending默认为True # 先对year年份进行由小到大排序,再对GDP由小到大排序 df2.sort_values(['year', 'GDP'])
-
rank函数:
-
rank函数用法:
DataFrame.rank()
或Series.rank()
-
rank函数返回值:以Series或者DataFrame的类型返回数据的排名(哪个类型调用返回哪个类型)
-
==rank函数包含有如下6个参数:==
-
axis:设置沿着哪个轴计算排名(0或者1),默认为0按纵轴计算排名
-
numeric_only:是否仅仅计算数字型的columns,默认为False
-
na_option :NaN值是否参与排序及如何排序,固定参数:keep top bottom
-
keep: NaN值保留原有位置
-
top: NaN值全部放在前边
-
bottom: NaN值全部放在最后
-
-
ascending:设定升序排还是降序排,默认True升序
-
pct:是否以排名的百分比显示排名(所有排名与最大排名的百分比),默认False
-
method:排名评分的计算方式,固定值参数,常用固定值如下:
-
average : 默认值,排名评分不连续;数值相同的评分一致,都为平均值
-
min : 排名评分不连续;数值相同的评分一致,都为最小值
-
max : 排名评分不连续;数值相同的评分一致,都为最大值
-
dense : 排名评分是连续的;数值相同的评分一致
-
df2 df2.rank() df2.rank(axis=0) df2.rank(numeric_only=True) # 只对数值类型的列进行统计 df2.rank(ascending=False) # 降序 df2.rank(pct=True) # 以最高分作为1,放回百分数形式的评分,pct参数默认为False
df2.rank(method='average')#(2 3.5 3.5 5) df2.rank(method='min')#(2 3 3 5) df2.rank(method='max')#(2 4 4 5) df2.rank(method='dense')#(2 3 3 4)
rank使用详解
df7 = pd.DataFrame({'姓名':['小明', '小美', '小强', '小兰'],'成绩':[100, 90, 90, 80] }) df7.rank() # 等价于df7.rank(method='average', ascending=True) df7['成绩排名'] = df7.成绩.rank(method='min', ascending=False) df7 df7['成绩排名'] = df7.成绩.rank(method='max', ascending=False) df7 df7['成绩排名'] = df7.成绩.rank(method='dense', ascending=False) df7 最后一种希望大家重点掌握,其他几种搞清楚原理即可。
-
-
6- 聚合函数:
常用聚合函数有:
-
min 最小值
-
max 最大值
-
mean 平均值
-
sum 求和
-
count 求个数
-
min函数
df2.min() df2['year'].min()
-
max函数
df2.max() df2['year'].max()
-
mean 平均值
df2.mean() df2['year'].mean() df2['GDP'].mean()
-
七、高级处理-确实值处理
-
应用isnull判断是否有缺失数据NaN
-
应用fillna实现缺失值的填充
-
应用dropna实现缺失值的删除
-
应用replace实现数据的替换
对于数据
1、如何处理NAN
-
获取缺失值的标记方式(NaN或者其他标记方式)
-
如果缺失值的标记方式是NaN
-
判断数据中是否包含NaN:
-
pd.isnull(df),
-
pd.notnull(df)
-
-
存在缺失值nan:
-
1、删除存在缺失值的:dropna(axis='rows')
-
注:不会修改原数据,需要接受返回值
-
-
2、替换缺失值:fillna(value, inplace=True)
-
value:替换成的值
-
inplace:True:会修改原数据,False:不替换修改原数据,生成新的对象
-
-
-
-
如果缺失值没有使用NaN标记,比如使用"?"
-
先替换‘?’为np.nan,然后继续处理
-
2、电影数据的缺失值处理
-
电影数据文件获取
# 读取电影数据 movie = pd.read_csv("./dataset/movie.csv")
3、判断缺失值是否存在
-
pd.notnull()
pd.notnull(movie) Rank Title Genre Description Director Actors Year Runtime (Minutes) Rating Votes Revenue (Millions) Metascore 0 True True True True True True True True True True 1 True True True True True True True True True True 2 True True True True True True True True True True 3 True True True True True True True True True True 4 True True True True True True True True True True 5 True True True True True True True True True True 6 True True True True True True True True True True 7 True True True True True True True True True True
-
np.all(pd.notnull(movie))
-
pd.isnull()
4、存在缺失值nan,并且是np.nan
-
1- 删除
pandas删除缺失值,使用dropna的前提是,缺失值的类型必须是np.nan
# 不修改原数据 movie.dropna() # 可以定义新的变量接受或者用原来的变量名 data = movie.dropna()
获取空值行 => ① row_with_null = movie.isnull().any(axis=1)
② moive[row_with_null]
-
2- 替换缺失值
# 替换存在缺失值的样本的两列 # 替换填充平均值,中位数movie['Revenue (Millions)'].fillna(movie['Revenue (Millions)'].mean(), inplace=True)
替换所有缺失值:
for i in movie.columns:if np.all(pd.notnull(movie[i])) == False:print(i)movie[i].fillna(movie[i].mean(), inplace=True)
5、不是缺失值nan,有默认标记的
数据是这样的:
wis = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data")
以上数据在读取时,可能会报如下错误:
URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:833)>
解决办法:
# 全局取消证书验证 import ssl ssl._create_default_https_context = ssl._create_unverified_context
处理思路分析:
-
1、先替换‘?’为np.nan
-
df.replace(to_replace=, value=)
-
to_replace:替换前的值
-
value:替换后的值
-
-
# 把一些其它值标记的缺失值,替换成np.nan wis = wis.replace(to_replace='?', value=np.nan)
-
2、在进行缺失值的处理
# 删除 wis = wis.dropna()
小结
-
isnull、notnull判断是否存在缺失值
-
np.any(pd.isnull(movie)) # 里面如果有一个缺失值,就返回True
-
np.all(pd.notnull(movie)) # 里面如果有一个缺失值,就返回False
-
-
dropna删除np.nan标记的缺失值
-
movie.dropna()
-
-
fillna填充缺失值
-
movie[i].fillna(value=movie[i].mean(), inplace=True)
-
-
replace替换具体某些值
-
wis.replace(to_replace="?", value=np.NaN)
-
八、高级处理-数据合并
-
应用pd.concat实现数据的合并 => union
-
应用pd.merge实现数据的合并 => join
1、pd.concat实现数据合并
-
pd.concat([data1, data2], axis=1)
-
按照行或列进行合并,axis=0为列索引,axis=1为行索引
-
比如我们将刚才处理好的one-hot编码与原数据合并
# 按照行索引进行 pd.concat([data, dummies], axis=1)
2、pd.merge
-
pd.merge(left, right, how='inner', on=None)
-
可以指定按照两组数据的共同键值对合并或者左右各自
-
left
: DataFrame -
right
: 另一个DataFrame -
on
: 指定的共同键 -
how:按照什么方式连接
-
Merge method | SQL Join Name | Description |
---|---|---|
left | LEFT OUTER JOIN | Use keys from left frame only |
right | RIGHT OUTER JOIN | Use keys from right frame only |
outer | FULL OUTER JOIN | Use union of keys from both frames |
inner | INNER JOIN | Use intersection of keys from both frames |
内连接:
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],'key2': ['K0', 'K1', 'K0', 'K1'],'A': ['A0', 'A1', 'A2', 'A3'],'B': ['B0', 'B1', 'B2', 'B3']}) right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],'key2': ['K0', 'K0', 'K0', 'K0'],'C': ['C0', 'C1', 'C2', 'C3'],'D': ['D0', 'D1', 'D2', 'D3']}) # 默认内连接 result = pd.merge(left, right, on=['key1', 'key2'])
左连接
result = pd.merge(left, right, how='left', on=['key1', 'key2'])
右连接
result = pd.merge(left, right, how='right', on=['key1', 'key2'])
外连接
result = pd.merge(left, right, how='outer', on=['key1', 'key2'])
小结
-
pd.concat([数据1, 数据2], axis=**)
-
pd.merge(left, right, how=, on=)
-
how -- 以何种方式连接
-
on -- 连接的键的依据是哪几个
-
九、高级处理-数据分组
1、数据准备
-
加载优衣库的销售数据集,包含了不同城市优衣库门店的所有产品类别的销售记录,数据字段说明如下
-
store_id 门店随机id
-
city 城市
-
channel 销售渠道 网购自提 门店购买
-
gender_group 客户性别 男女
-
age_group 客户年龄段
-
wkd_ind 购买发生的时间(周末,周间)
-
product 产品类别
-
customer 客户数量
-
revenue 销售金额
-
order 订单数量
-
quant 购买产品的数量
-
unit_cost 成本(制作+运营)
-
# 导包 加载数据集 import pandas as pd df = pd.read_csv('../数据集/uniqlo.csv')
2、groupby分组聚合
-
1- df.groupby分组函数返回分组对象
【基于一列进行分组】
# 基于顾客性别分组 gs = df.groupby(['gender_group']) gs gs['city'] # 返回结果如下 <pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001B1DA988B80> <pandas.core.groupby.generic.SeriesGroupBy object at 0x000001B1DB2B4FA0>
【基于多列进行分组】
# 基于顾客性别、不同城市分组 gs2 = df.groupby(['gender_group', 'city']) gs2 # 返回结果如下 <pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001B1DB24F1F0>
-
2- 分组后获取各个组内的数据
-
2.1 取出每组第一条或最后一条数据
gs2 = df.groupby(['gender_group', 'channel']) gs2.first() # 取出每组第一条数据 gs2.last() # 取出每组最后一条数据
-
2.2 - 按分组依据获取其中一组
gs2.get_group(('Female', '线上'))
-
-
3- 分组聚合
-
格式:分组后对多列分别使用不同的聚合函数
df.groupby(['列名1', '列名2']).agg({'指定列1':'聚合函数名', '指定列2':'聚合函数名', '指定列3':'聚合函数名' })
-
按城市和线上线下划分,分别计算销售金额的平均值、成本的总和
df.groupby(['city', 'channel']).agg({'revenue':'mean', 'unit_cost':'sum' })
3、分组过滤操作
-
格式:
df.groupby(['列名1',...]).filter(lambda x: dosomething returun True or False )
案例: 按城市分组,查询每组销售金额平均值大于200的全部数据
df.groupby(['city']).filter(lambda s: s['revenue'].mean() > 200) df.groupby(['city'])['revenue'].filter(lambda s: s.mean() > 200)
-
3、透视表
import pandas as pd data = {'性别': ['男', '女', '男', '女', '男', '女'],'购买': ['是', '否', '是', '是', '否', '否'],'金额': [100, 150, 200, 130, 160, 120] } df = pd.DataFrame(data) # 创建透视表 pivot_table = pd.pivot_table(df, values='金额', index='性别', columns='购买', aggfunc='mean') print(pivot_table) 购买 否 是 性别 女 135.0 130.0 男 180.0 150.0
4、案例分析
4.1 数据准备
-
准备两列数据,星期数据以及涨跌幅是好是坏数据
-
进行交叉表计算
# 寻找星期几跟股票张得的关系 # 1、先把对应的日期找到星期几 date = pd.to_datetime(data.index).weekday data['week'] = date # 2、假如把p_change按照大小去分个类0为界限 data['posi_neg'] = np.where(data['p_change'] > 0, 1, 0) # 通过交叉表找寻两列数据的关系 count = pd.crosstab(data['week'], data['posi_neg'])
但是我们看到count只是每个星期日子的好坏天数,并没有得到比例,该怎么去做?
-
对于每个星期一等的总天数求和,运用除法运算求出比例
# 算数运算,先求和 sum = count.sum(axis=1).astype(np.float32) # 进行相除操作,得出比例 pro = count.div(sum, axis=0)
4.2 查看效果
使用plot画出这个比例,使用stacked的柱状图
pro.plot(kind='bar', stacked=True) plt.show()
4.3 使用pivot_table(透视表)实现
使用透视表,刚才的过程更加简单
# 通过透视表,将整个过程变成更简单一些 data.pivot_table(['posi_neg'], index='week')
小结
-
交叉表与透视表的作用【知道】
-
交叉表:计算一列数据对于另外一列数据的分组个数
-
透视表:指定某一列对另一列的关系
-