Python数据分析极简入门_Pandas
Pandas基础知识
前言
参与CDA_Python数据分析极简入门,记录学习进度,便于复习
一、Pandas简介
什么是Pandas
- Pandas是一个开源的Python库,主要用于数据分析、数据处理、数据可视化。
- Pandas作为Python数据分析的核心包,提供了大量的数据分析函数,包括数据处理、数据抽取、数据集成、数据计算等基本的数据分析手段。
- Pandas的名称来自于面板数据
(panel data)
和python数据分析(data analysis)
的简称。
为什么学Pandas
-
比SQL语句还要简洁,查询数据事半功倍!简单
-
基于Numpy数值计算,数据处理高效运算!高效
-
支持数值、文本和可视化,快速灵活完成数据需求!强大
如果用一个字来说明,那就是 快
怎么学Pandas
-
第一步,必须了解Pandas的数据结构。在之前的系列文章里面说过,学习语言学习的三板斧,数据结构,流程控制,自定义函数。这里pandas虽然只是一个库,但同样有其数据结构。
- pandas 简介
- pandas 数据类型
- Series
- DataFrame
- pandas 数据查看
-
第二步,必须学会用Pandas做数据处理。这是你做数据分析的基本功,里面包含如下内容
- pandas 条件查询
- pandas 数据计算
- pandas 合并连接
- pandas 分组聚合
- pandas 数据重塑
-
第三步,掌握一些Pandas高阶与展示技巧。这是你分析或展示的必备技能
- pandas 文本数据
- pandas 时间数据
- pandas 窗囗数据
- pandas 数据读写
- pandas 表格样式
- pandas 数据可视化
二、Pandas数据类型
Pandas 有两种自己独有的基本数据结构。需要注意的是,它固然有着两种数据结构,因为它依然是 Pvthon 的一个库,所以 Python 中有的数据类型在这里依然适用。我们分别看一下这两种数据结构:
Series
Series:一维数组。该结构能够放置各种数据类型,比如字符、整数、浮点数等
我们先引入pandas包,这里有一个约定成俗的写法import pandas as pd
将pandas引入,并命其别名为pd接着将列表[2,3,5,7,11]放到pd.Series()里面
import pandas as pd
s= pd.series([2,3,5,7,11],name ='A')
s
#结果
0 2
1 3
2 5
3 7
4 11
Name: A, dtype:int64
Time- Series:以时间为索引的Series 同样的,将列 [‘2024-01-01 08:08:80’,‘2024-01-81 03:88:08’,‘2824-01-81 86:88:08’]放到pd.Datetimelndex()
里面
dts1 = pd.DatetimeIndex(['2024-01-01 00:80:00','2024-01-01 03:00:80','2024-01-01 06:00:00'])
dts1
#结果
DatetimeIndex(['2024-01-01 00:80:00','2024-01-01 03:00:80','2024-01-01 06:00:00'],dtype="datetime64[ns]',freg=None)
还有另外一种写法pd.date_range
可以按一定的频率生成时间序列
dts2 = pd.date_range(start='2024-01-01',periods=6, freq='3H')
dts2
#结果
DatetimeIndex(['2024-01-01 00:00:00','2024-01-01 03:00:00',
'2024-01-01 06:00:00','2024-01-01 09:00:00',
'2024-01-01 12:00:00','2024-01-01 15:00:00'],
dtype='datetime64[ns]', freg='3H')
dts3 = pd.date_range('2024-01-01',periods=6,freq='d')
dts3
#结果
DatetimeIndex(['2024-01-01','2024-01-02','2024-01-03','2024-01-04','2024-01-05','2024-01-06'],
dtype='datetime64[ns]',freg='D')
DataFrame
DataFrame:二维的表格型数据结构,可以理解为Series的容器,通俗地说,就是可以把Series放到DataFrame里面
它是一种二维表格型数据的结构,既有行索引,也有列索引。行索引是 index,列索引是 columns
。类似于初中数学里,在二维平面里用坐标轴来定位平面中的点。
注意,DataFrame又是Pandas的核心
!接下来的内容基本上以DataFrame为主先来看
看如何创建DataFrame,上面说过Series也好,DataFrame也罢,本质上都是容器,就是里面可以放东西的东西。
从字典创建DataFrame
相当于给里面放dict:先创建一个字典d,再把 d放进了 DataFrame
里命名为 df
d = {'A':[1,2,3],
'B':[4,5,6],
'C':[7,8,9]}
df = pd.DataFrame(data = d)
df
从列表创建DataFrame
先创建了一个列表 d,再把 d放进了DataFrame
里命名为 df
d=[[4,7,10],[5,8,11],[6,9,12]]
df1 = pd.DataFrame(
data = d,
index=['a','b','c'],
columns=['A','B','C'])
df1
从数组创建DataFrame
数组(array)对你来说可能是一个新概念,在Python里面,创建数组需要引入一个类似于Pandas的库,叫做Numpy。与前面引入Pandas类似,我们用import numpy as np
来引入numpy,命其别名为np.
同样的,先创建一个数组d,再把d放进了 DataFrame
里命名为 df
import numpy as np
d = np.array([[1,2,3],[4,5,6],[7,8,9]])
df2 = pd.DataFrame(
data =d,
index=['a','b','c'],
columns=「'A','B','C'])
df2
三、Pandas数据查看
这里我们创建一个 DataFrame
命名为 df
import numpy as np
import pandas as pd
d= np.array([[81,28,24,25,96],
[8,35,56,98,39],
[13,39,55,36,3],
[70,54,69,48,12],
[63,80,97,25,70]])
df = pd.DataFrame(
data = d,
columns=list('abcde'))
df
随机选取
查看前n行
df.head(3)
查看后n行
df.tail(2)
查看随机N行
df.sample(2)
如何査看一个DataFrame里的数据,包括用[]、i1oc、iat 等方法
按列选取
第一种,直接在[ ]
里面写上要筛选的列名
df['a']
第二种,在.iloc[ ]
里的,前面写上要筛选的行索引,在,
后面写上要筛选的列索引,.iloc[行索引, 列索引]
。其中:
代表所有,0:3
代表从索引0到2
df.iloc[0:3,0]
第三种,直接.
后面写上列名
df.a
选择多列
第一种,直接在[ ]
里面写上要筛选的列名组成的列表['a','c',d']
df[['a','c','d']]
第二种,在.iloc[]
里面行索引位置写:
选取所有行,列索引位置写上要筛选的列索引组成的列表[0,2,3]
df.iloc[:,[0,2,3]]
第三种,在.loc[]
里面的行索引位置写来选取所有行,在列索引位置写上:
要筛选的列索引组成的列表['a','c','d']
df.loc[:,['a','c','d']]
按行选取
第一种:直接选取第一行
df[0:1]
第二种:用 .loc[]
选取第一行
df.loc[0:0]
第三种:用.iloc[]
选取任意多行
df.iloc[[1,3],]
第四种:用`.iloc[]选择连续多行
df.iloc[[1:3],]
指定行列
第一种:指定行列值 iat
, at
# 根据行列索引
df.iat[2,2]
# 根据行列名称
df.at[2,'a']
第二种:指定行列区域 .iloc[]
df.iloc[[2,3],[1,4]]
四、Pandas条件查询
如何用条件表达式筛选数据:
import pandas as pd
np.array([[81,28,24,25,96],
[8,35,56,98,39],
[13,39,55,36,3],
[70,54,69,48,12],
[63,80,97,25,70]])
df = pd.DataFrame(
data =d,
columns=list('abcde"))
df
单一条件
df[df['a']>60]
单一条件&多列
df.loc[(df['a']>60),['a','b','d']]
多条件
df[(df['a']>60)&(df['b']>60)]
多条件 筛选行&指定列筛选列
df.loc[(df['a']>60)&(df['b']>60),['a','b','d']]
五、Pandas数学计算
聚合计算
聚合计算是指对数据进行汇总和统计的操作。常用的聚合计算方法包括计算均值、求和、最大值、最小值、计数等。
#平均值
df['a'].mean()
#求和
df['a'].sum()
#最大值
df['a'].max()
#最小值
df['a'].min()
#计数
df['a'].count()
#中位数
df['a'].median()
#方差
df['a'].var()
#偏度
df['a'].skew()
#峰度
df['a'].kurt()
#累计求和
df['a'].cumsum()
#累计求积
df['a'].cumprod()
# 差分
df['a'].diff()
# 平均绝对偏差
df['a'].mad()
按行、列聚合计算
#按列求和汇总到最后一行
df.sum(axis=0)
#按行求和汇总到最后一列
df.sum(axis=1)
df.describe()# 描述性统计
agg函数
对整个DataFrame批量使用多个聚合函数
df.agg(['sum','mean','max','min','median'])
对DataFramed的某些列应用不同的聚合函数
df.agg({'a':['max','min'],'b':['sum','mean'],'c':['median']})
apply、applymap、map函数
applymap函数在新版已经弃用,该部分可忽略
在Python中如果想要对数据使用函数,可以借助apply(),applymap(),map()
对数据进行转换,括号里面可以是直接函数式,或者自定义函数(def)
或者匿名函数(lambda)
当我们要对数据框(DataFrame)的数据进行按行或按列操作时用apply()
df.apply(lambda x :x.max()-x.min(),axis=1)
#axis=1,表示按行对数据进行操作
#从下面的结果可以看出,我们使用了apply函数之后,系统自动按行找最大值和最小值计算,每一行输出一个值
df.apply(lambda x:x.max()-x.min(),axis=0)
#默认参数axis=0,表示按列对数据进行操作
#从下面的结果可以看出,我们使用了apply函数之后,系统自动按列找最大值和最小值计算,每一列输出一个值
当我们要对数据框(DataFrame)的每一个数据进行操作时用applymap()
,返回结果是DataFrame格式
df.applymap(lambda x:1 if x>60 else 0)
#从结果可以看出,我们使用了applymap函数之后,
#系统自动对每一个数据进行判断,判断之后输出结果
当我们要对Series的每一个数据进行操作时用map()
df['a'].map(lambda x:1 if x>60 else 0)
apply()
函数可以在DataFrame或Series上应用自定义函数,可以在行或列上进行操作。applymap()
函数只适用于DataFrame,可以在每个元素上应用自定义函数。map()
函数只适用于Series,用于将每个元素映射到另一个值。
以上是数学运算部分,包括聚合计算、批量应用聚合函数,以及对Series和DataFrame进行批量映射
六、Pandas合并连接
在pandas中,有多种方法可以合并和拼接数据。常见的方法包括append()、concat()、merge()
。
append追加
append()
函数用于将一个DataFrame或Series对象追加到另一个DataFrame中。
import pandas as pd
#定义df1
df1 = pd.DataFrame({'A': ['a', 'b'],
'B':[1,2]})
df1
#定义df2
df2 = pd.DataFrame({'A':['b','c','d'],
'B':[2,3,4]})
df2
#按'A','B'索引追加
df1.append(df2,ignore index=True)
concat合并
concat()
函数用于沿指定轴将多个对象(比如Series、DataFrame)堆叠在一起可以沿行或列方向进行拼接。
上下堆叠(拼接)
df1 = pd.DataFrame({'A':['a','b'],
'B':[1,2]})
df2 = pd.DataFrame({'A':['b','c','d']
'B':[2,3,4]})
df1
df2
pd.concat([df1,df2],axis =0) # 上下堆叠(拼接)
左右堆叠(拼接)
df1 = pd.DataFrame({'A':['a','b']})
df2 = pd.DataFrame({'B':[1,2],
'c':[2,4]})
df1
df2
pd.concat([df1,df2],axis =1)#左右堆叠(拼接)
merge连接
merge()
函数用于根据一个或多个键将两个DataFrame的行连接起来。类似于SQL中的JOIN操作。
pd.merge 类似inner 和 outer
链接
df1 = pd.DataFrame({'A':['a','b','c'],
'B':[1,2,3]})
df2 = pd.DataFrame({'A':['b','c','d'],
'B':[2,3,4]})
df1
df2
pd.merge(df1,df2,how = 'inner')
pd.merge(df1,df2,how = 'outer')
pd.merge 类似left 和 right
链接
df1 = pd.DataFrame({ 'A':['a','b','c'],
'B':[1,2,3]})
df2 = pd.DataFrame({'A':['b','c','d'],
'C':[2,3,4]})
pd.merge(df1,df2,how ='left',on ="A")#左连接
pd.merge(df1,df2,how='right',on ="A")#右连接
pd.merge(df1,df2,how='inner',on ="A")# 内连接
pd.merge(df1,df2,how='outer',on ="A")#外连接
#返回在df1中列'A'的值在df2中也存在的行
df1[df1['A'].isin(df2['A'])]
#返回在df1中列'A'的值在df2中不存在的行
df1[~df1['A'].isin(df2['A'])]
七、Pandas分组聚合
分组聚合(group by)顾名思义就是分2步
- 先分组:根据某列数据的值进行分组。用
groupby()
对某列进行分组 - 后聚合:将结果应用聚合函数进行计算。在
agg()
函数里应用聚合函数计算结果,如sum()、mean()、count()、max()、min()
等,用于对每个分组进行聚合计算。
import pandas as pd
import numpy as np
import random
df = pd.DataFrame({'A':'a','b','a','b','a','b'],
'B':['L','L','M','N','M','M'],
'C':[107,177,139,3,52,38],
'D':[22,59,38,50,60,82]})
df
单列分组
- 对单列分组后应用聚合函数sum
df.groupby('A').sum()
- 对单列分组后应用单个指定的聚合函数
df.groupby('A').agg({'C': 'min'}).rename(columns={'C': 'c_min'})
- 对单列分组后应用多个指定的聚合函数
df.groupby(['A']).agg({'C':'max','D':'min'}).rename(columns={'C':'C_max','D':'D_min'})
两列分组
- 对多列分组后应用
sum
聚合函数:
df.groupby(['A','B']).sum()
- 对两列进行
group
后,都应用max
聚合函数
df.groupby(['A','B']).agg({'C':'max'}).rename(columns={'C':'C_max'})
- 对两列进行分组 group 后,分别应用 max、min 聚合函数
df.groupby(['A','B']).agg({'C':'max','D':'min'}).rename(columns={'C':'C_max','D':'D_min'})
自定义聚合函数
df = pd.DataFrame({'A':'a','b','a','b','a','b'],
'B':['L','L','M','N','M','M'],
'C':[107,177,139,3,52,38],
'D':[22,59,38,50,60,82]})
df
#使用自定义的聚合函数计算每个分组的最大值和最小值
def custom_agg(x):
return x.max()- x.min()
result = df[['B','C']].groupby('B').agg({'C':custom_agg})
result
开窗函数
开窗函数(类似于SQL里面的 over partition by)
使用transform函数计算每个分组的均值
#使用transform函数计算每个分组的均值
df['B_C_std'] = df[['B','C']].groupby('B')['C'].transform('mean')
df
group_concat功能
分组聚合拼接字符串 pandas实现类似 group_concat 功能
假设有这样一个数据:
df = pd.DataFram({
'姓名':['张三','张三','张三','李四','李四','李四','李四'],
'科目':['语文','数学','英语','语文','数学','英语']
})
df
按名称分组,把每个人的科目拼接到一个字符串:
#对整个group对象中的所有列应用join连接元素
#(df.astype(str).groupby('姓名').agg(lambda x:",".join(x)))[['科目']]
(df.astype(str)#先将数据全转为字符
.groupby('姓名')#分组
.agg(lambda x:",".join(x)))[['科目']]#join连接元素
八、Pandas数据重塑
[数据变形、数据堆叠、数据交叉表]
数据重塑(Reshaping)
数据重塑,顾名思义就是给数据做各种变形,主要有以下几种,
- df.pivot 数据变形。
- df.pivot table 数据透视表
- df.stack/unstack数据堆叠
- df.melt 数据融合
- df.cross 数据交叉表
数据变形 df.pivot
根据索引(index)、列(column)(values)值),对原有DataFrame(数据框)进行变形重塑,俗称长表转宽表
importpandas as pd
import numpy as np
#定义成绩
df = pd.DataFrame(
{'姓名':['张三','张三','张三','李四','李四','李四'],
'科目':['语文','数学','英语','语文','数学','英语'],
'成绩':[91,80,100,80,100,96]})
df
#长转宽:使用 df.pivot以姓名为index,以各科目为columns,来统计各科成绩:
df.pivot(index='姓名',columns='科目',values='成绩')
数据融合pd.melt
df1 = pd.pivot(df,index='姓名',columns='科目',values='成绩').reset_index()
#宽表变长表:使用 pd.melt 以 姓名为标识变量的列 id_vars ,以各 科目为value_vars来统计各科成绩:
df1.melt(id_vars=['姓名'],value_vars=['数学','英语','语文'])
数据透视pd.pivot_table
random.seed(1024)
df = pd.DataFrame(
{'专业': np.repeat(['数学与应用数学’,'计算机’,'统计学”,4),
'班级':['1班','1班','2班','2班']*3,
'科目':['高数','线代’]*6,
平均分':[random.randint(60,100)for i in range(12)],
及格人数':[random.randint(30,50)for i in range(12)]})
df
各个专业对应科目的及格人数和平均分
pd.pivot_table(df, index=['专业','科目'],
values=['及格人数','平均分'],
aggfunc={'及格人数':np.sum,'平均分':np.mean})
补充说明
df.pivot_table()
和 df.pivot()
都是Pandas中用于将长表转换为宽表的方法但它们在使用方式和功能上有一些区别。
- 使用方式:
df.pivot()
方法接受三个参数:index、columns和values
分别指定新表的索引、列和值。df.pivot_table()
方法接受多个参数,其中最重要的是index、columns和 values
用于指定新表的索引、列和值。此外,还可以使用aggfunc
参数指定对重复值进行聚合操作的函数,默认为均值。
- 处理重复值:
df.pivot()
方法在长表中存在重复值时会引发错误。因此,如果长表中存在重复值,就需要先进行去重操作,或者使用其他方法来处理重复值。df.pivot_table()
方法可以在长表中存在重复值的情况下进行透视操作并可以使用aggfunc
参数指定对重复值进行聚合操作的函数,默认为均值。
- 聚合操作
df.pivot()
方法不支持对重复值进行聚合操作,它只是简单地将长表中的数据转换为宽表。df.pivot_table()
方法支持对重复值进行聚合操作。可以使用aggfunc
参数来指定聚合函数,例如求均值、求和、计数等。
总的来说,df.pivot()
方法适用于长表中不存在重复值的情况,而df.pivot_table()
方法适用于长表中存在重复值的情况,并且可以对重复值进行聚合操作。根据具体的数据结构和分析需求,选择合适的方法来进行转换操作。
数据堆叠Stack/Unstack
交叉表显示了每个变量的不同类别组合中观察到的频率或计数。通俗地说,就是根据不同列的数据统计了频数
df = pd.DataFrame(
{'专业': np.repeat(['数学与应用数学','计算机','统计学','物理学'],6),
'班级':['1班','2班','3班']*8,
'科目':['高数','线代']* 12
'平均分':[random.randint(60,100)for i in range(24)],
'及格人数':[random.randint(30,50)for i in range(24)]})
df2 = pd.pivot_table(df,index=['专业','科目'], values=['及格人数','平均分'],aggfunc={'及格人数':np.sum,"平均分":np.mean})
df2
#“压缩”后的DataFrame或Series(具有Multilndex作为索引),stack()的逆操作是unstack(),默认情况下取消最后压缩的那个级别:
#堆叠 stack(),顾名思义就是把透视结果堆到一起。接下来我们把透视后堆叠的数据一步步展开 unstack():
stacked =df2.stack()
stacked.unstack()
数据交叉表(pd.crosstab)
交叉表
df = pd.DataFrame({'High':["高","高","高","中","中","低","低","低","高","低"],
'weight':["重","轻","中","中","轻","重","重","中","重","轻"})
df
pd.crosstab(df['High'], df['weight'])
双层交叉表
df = pd.DataFrame(
{'High': ["高","高","高","中","中","中","低","低","低","高","低"],
'Weight':["重","轻","中","中","轻","重","重","轻","中","重","轻"],
'Size': ["大","中","小","中","中","大","中","小","小","大","小"]})
df
pd.crosstab(df['Hight'],[df['Weight'],df['Size']],rowname=['High'],colnames=['Weight','Size'])
宽表转长表 pd.wide_to_long()
np.random.seed(123)
df = pd.DataFrame({"A1970":{0 :"a",1 :"b",2 :"c"},
"A1980":{0 :"d",1 :"e",2 :"f"},
"B1970":{0 :2.5,1:1.2,2 :.7},
"B1980":{0:3.2,1:1.3,2 :.1},
"x":dict(zip(range(3),np.random.randn(3)))
})
df["id"]= df.index
df
把id 列用作标识列
pd.wide_to_long(df,["A","B"],i = "id",j="year")
df = pd.DataFrame({
'famid':[1,1,1,2,2,2,3,3,3],
'birth':[1,2,3,1,2,3,1,2,3],
'ht1':[2.8,2.9,2.2,2,1.8,1.9,2.2,2.3,2.1],
'ht2':[3.4,3.8,2.9,3.2,2.8,2.4,3.3,3.4,2.9]
})
df
把famid , birth 两列用作标识列
l = pd.wide_to_long(df,stubnames = 'ht',i =['famid','birth'],j='age')
l
总结
待补充
https://pandas.pydata.org/pandas-docs/stable/index.html