文章目录
- 一、Series的定义和使用
- 二、DataFrame数据结构与行列操作
- 三、DataFrame 描述统计、离散化、排序
- 四、缺失值、重复值、异常值的处理
- 五、聚合、分组与透视表
- 六、向量化字符串操作
- 七、练习
一、Series的定义和使用
- Series 是一个带有名称和索引的一维数组。
- Series 中包含的数据类型可以是整数、浮点、字符串、列表、元组、ndarray等。
pd.Series([‘data=None’, ‘index=None’, ‘dtype=None’, ‘name=None’])
# 导入相关库(一般一起导入两个包)
import numpy as np
import pandas as pd
Series中只能保存一种数据类型,如果不一致会自动转化为一致,与ndarray类似
1.1 Series索引标签的添加
1.1.1 创建Series对象时添加
1.1.2 建立好Series后用一个新的列表赋值到该Series的索引对象index中
1.2 Series的名字
1.2.1 创建Series对象的时候添加
1.2.2 建立好Series后通过改变Series实例属性的方式添加
1.2.3 Series索引名字的添加
1.3 Pandas的Index对象
1.4 Series的索引和切片
1.4.1 数字下标去取
1.4.2 标签名去取
1.5 Series的.get()方法
1.6 Series掩码提取
补充:ufunc可以在在Series对象中使用
二、DataFrame数据结构与行列操作
2.1 DataFrame的创建
2.1.1 通过数组转化
2.1.2 通过字典转化
2.1.3 通过嵌套列表转化
嵌套列表换成ndarray也可以
DataFrame有行标签以及列标签,在设置的时候可以在创建DataFrame的时候赋值给相应的参数,也可以通过对对应的属性进行赋值,从而添加或者修改
2.2 数据提取
2.2.1 根据列标签名提取
2.2.2 df.loc[]
语法 user_info.loc[索引行,索引列 ]
2.2.3 df.iloc[]
2.3 行列增删改
2.3.1 行的增加与修改
2.3.2 列的增加与修改
以下表为例子,在指定位置新增一列指定科目的相加的总分
df.insert
新增一列 理综 位置在生物后面
新增一列 排名, 位置在总分之前,名次从1开始
2.3.3 行列删除
2.3.3.1 df.drop()
df.drop()操作,设置inplace=False并没有删除原表记录,而是返回了一个新的DataFrame对象。
删除 排名
2.3.3.2 df.pop()
df.pop()方法只能删除列。
df.pop()会直接删除原表的列!谨慎操作!
2.4 列顺序的更改
df.pop()+df.insert()
- 将要移动位置的列使用df.pop()删除,并使用变量进行接收
- 使用df.insert()把弹出来的这一列放到原df你想放的位置
- 使用df.insert()插入列,会直接改变原df
2.5 索引和列名的修改
- 修改索引名用需要在df.rename()中设置index参数。
- 修改列名只需要设置参数 columns。
使用df.rename()将整个索引标签替换掉,包括行标签index,列标签columns,只需要建立一个字典:
- 该字典的“键”对应着“旧索引”
- 该字典的“值”对应着“新索引”
df.rename()也可以通过字典映射的方法,修改DataFrame的列表标签:
修改索引df.index
2.6 单列数据类型转换
2.6.1 Series.astype
2.7 表合并方式
2.7.1 pd.concat([表1,表2])
两个表↓
2.7.2 df.append(df)
2.7.3 pd.merge()
有内连接、左连接、右连接操作。和MySQL里面的原理一致
两张表↓
2.7.3.1 内连接
就普通的把俩表都有的数据相匹配查询出来,可以说为普通查询
2.7.3.2 左连接
简单理解为以左表内容为主,进行查询,左表有,右表没有的内容会被以NaN填满
2.7.3.3 右连接
简单理解为以右表内容为主,进行查询,右表有,左表没有的内容会被以NaN填满
2.8 数据保存与读取
2.8.1 保存
数据保存,把在python中操作后的表格存到本地
1、df有被定义
2、df.to_excel() or df.to_csv()
3、可以填写完整的保存路径,或者直接写设置的表的名字
2.8.2 读取
读取:是把本地的文件读到python里
1、确保你写的文件的名字在对应位置的路径可以被找到
2、使用pd.read_excel()或pd.read_csv()
如果数据有索引,但是没有索引名,导入进来后该索引会作为新的一列,导入的时候设置好参数index_col="Unnamed: 0"即可。
如果需要导入的文件不在当前工作路径下,填写完整路径即可
三、DataFrame 描述统计、离散化、排序
3.1 查看基本信息
3.1.1 df.info()
3.1.2 df.head(num)
3.1.3 df.shape
3.1.4 df.T
通过 .T 获取数据的转置
3.1.5 df.values
获取原有数据
3.2 描述与统计
3.2.1 常用描述性统计指标
获取到数据之后,若想要查看下数据的简单统计指标(最大值、最小值、平均值、中位数等)
DataFrame中有两种方法可以实现:
- 方法一:直接通过DataFrame抽取出来的单列series使用series的相应统计方法或函数。
- 方法二:通过使用numpy对应的方法或函数,处理目标也是DataFrame抽出来的series。
DataFrame和Series均支持以下方法:
指标 | 描述 |
---|---|
count() | 计数项 |
mean()、median() | 均值与中位数 |
min()、max() | 最大值与最小值 |
mode() | 众数 |
std()、var() | 标准差与方差 |
prod() | 所有项乘积 |
sum() | 所有项求和 |
统计user_infor中年龄的平均值:
series能用的描述性统计的指标:
3.2.2 例子
3.2.3 df.describe()
直接调用 describe 方法后,会显示出数字类型的列的一些统计指标,如 总数、平均数、标准差、最小值、最大值、25%/50%/75% 分位数。
3.2.4 Series.value_counts()
如果想要统计某个字段不同数值出现的频次,我们可以使用.value_counts()方法
3.3 离散化
3.3.1 pd.cut()
有时候,我们会碰到这样的需求,想要将年龄进行离散化(分箱),直白来说就是将年龄分成几个区间,这里我们想要将年龄分成 3 个区间段。就可以使用 pd.cut 方法来完成,返回的也是Series。
有时候离散化之后,想要给每个区间起个名字,可以在pd.cut()中使用参数 labels 来指定。
3.3.2 pd.qcut()
除了可以使用 cut 进行离散化之外,qcut 也可以实现离散化。cut 是根据每个值的大小来进行离散化的,qcut 是根据每个值出现的次数来进行离散化,也就是基于分位数的离散化功能。
3.4 排序功能
3.4.1 df.sort_index()
sort_index 方法默认是按照索引进行正序排的。
3.4.2 df.sort_values()
按照实际值来排序
3.4.3 Series.nlargest()
一般在排序后,我们可能需要获取最大的n个值或最小值的n个值,我们可以使用 nlargest 和 nsmallest 方法来完成,这比先排序再使用 head(n)方法快得多。
3.5 函数应用及映射方法
3.5.1 Series.map()
将所编写的字典或者函数的规则运用到series里的一个一个元素上
- map 是 Series 中特有的方法,通过它可以对 Series 中的每个元素实现转换。
- 如果我想通过年龄判断用户是否属于中年人(50岁以上为中年),通过 map 可以轻松搞定。
可以使用自定义函数来形成这种映射关系
3.5.2 Series.apply()和df.apply()
apply既可以作用于series,也可以作用于dataframe,以及分组后的对象都可以使用
若是series:是将编写的函数规则运用到series里的一个个元素上面
若是dataframe:作用对象是这个dataframe里面的一行一行或是一列一列的数据,作用对象是series
若是分组后的对象:将所编写的规则运用到分组后的一个一个组
apply 方法既支持 Series,也支持 DataFrame,在对 Series 操作时会作用到每个值上,在对 DataFrame 操作时会作用到所有行或所有列(通过 axis参数控制)。
注意:Series.apply()只能使用自定义函数构建相应的转换规则
对 DataFrame 来说,apply 方法的作用对象是一行或一列数据(一个Series)
- axis为 0 或 ‘index’ :将函数应用于每一列。
- axis为 1 或 ‘columns’ :将函数应用于每一行。
3.5.3 df.applymap()
通过dataframe对象调用,将所编写的规则运用到这个dataframe的每一个元素上
applymap 方法针对于 DataFrame,它作用于 DataFrame 中的每个元素,它对 DataFrame 的效果类似于 apply 对 Series 的效果
还是操作heros那张表
pandas中map()、apply()、applymap()的区别:
- map()方法适用于Series对象,可以通过字典或函数类对象来构建映射关系对Series对象进行转换;
- Series.map() 作用对象是Series里的一个个元素
- apply()方法适用于Series对象、DataFrame对象、Groupby对象,用函数类对象来构建映射关系对Series对象进行转换;
- Series.apply() 作用对象是Series里的一个个元素
- df.apply()处理的是行或列数据(本质上处理的是单个Series),作用对象为一个个Series
- Groupby.apply() 作用对象是依据某个要求分组后,里面的一个个小组
- applymap()方法用来处理DataFrame对象的单个元素值,也是使用函数类对象映射转换;
- df.applymap() 作用对象是df里的一个个元素
补充:若有一张表
orders = pd.read_csv('/data/orders.csv')
orders.head(2)
#显示的最大行数和列数为100,如果超过设置的行和列就显示省略号
pd.set_option('display.max_rows', 100)
pd.set_option('display.max_columns', 100)
提取买家应付货款, 买家应付邮费, 总金额, 买家实际支付金额四列,计算这四列每列的总计和
money_part = orders[['买家应付货款', '买家应付邮费', '总金额', '买家实际支付金额']]
money_part
money_part.apply(np.sum,axis=0)
四、缺失值、重复值、异常值的处理
4.1 缺失值的处理
4.1.1 发现缺失值
注意:NaN为特殊的浮点数
4.1.1.1 df.isnull()
判断是否为空值:dataframe.isnull()或者dataframe.notnull()
4.1.1.2 df.notnull()
和isnull()相反,是查不为空的数据,用法和isnull()一样。这个方法用的不是很多
4.1.2 剔除缺失值df.dropna()
还是这个表
4.1.2.1 参数how
how="all"只有当该列(或行)全都为缺失值时,才会将该列删除
how="any"只有当该列(或行)有一个缺失值,就会将该列删除 默认
4.1.2.2 参数thresh
thresh参数设置的是:你想至少留下多少非缺失值!
如何删除heros_null中缺失值超过45%的字段。
- 非缺失值的数量不能低于55%
- 整个字段元素的个数 (行数)
- 非缺失值的数量不低于 整个字段元素的个数*0.55
4.1.3 填充缺失值
4.1.3.1 固定值填充fillna()
填充均值容易受到异常值的影响,所以可以使用:
- 中位数:Series.median()
- 众数:Series.mode() 但并不是所有数据集都有众数,如[1,2,3,4,5]
4.1.3.2 从前往后填充 method=“ffill”
4.1.3.3 从后往前填充 method=“bfill”
与之相反
4.1.3.4 df.replace()
有的缺失值并非是NaN,所以我们应该用replace()去把这些缺失值替换成NaN,然后再进行相应缺失值的操作
4.2 重复值的处理drop_duplicates()
a.duplicated().sum() #查看重复的数量
pandas 里面 drop_duplicates函数用于删除Series、DataFrame中重复记录,并返回删除重复后的结果。
DataFrame实例调用.drop_duplicates()方法会直接删除所有数值都一模一样的数据,保留一行。
4.2.1 keep
4.2.2 subset
补充:nunique()返回非重复值统计的个数
4.3 异常值的处理(统计学)
检测到了异常值,我们需要对其进行一定的处理。而一般异常值的处理方法可大致分为以下几种:
- 删除含有异常值的记录:直接将含有异常值的记录删除;
- 视为缺失值:将异常值视为缺失值,利用缺失值处理的方法进行处理;
- 平均值修正:可用前后两个观测值的平均值修正该异常值;
- 不处理:如果异常值具有实际价值,直接在具有异常值的数据集上进行数据挖掘;
五、聚合、分组与透视表
import pandas as pd
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
# 解决坐标轴刻度负号乱码
plt.rcParams['axes.unicode_minus'] = False
# 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Simhei']
#plt.rcParams["font.family"] = 'Heiti TC' #mac字体不显示
#全部行都能输出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
常用聚合函数如下
指标 | 描述 |
---|---|
count() | 计数项 |
mean()、median() | 均值与中位数 |
min()、max() | 最大值与最小值 |
std()、var() | 标准差与方差 |
prod() | 所有项乘积 |
sum() | 所有项求和 |
5.1 groupby分组
DataFrame和Series的方法都可以由GroupBy方法调用
操作实现原理如图所示
5.1.1 groupby对象
查看方法:(数据量多就不建议查看了)
groupby对象可以直接按组进行迭代的,每一组都是Series或DataFrame,如果我们将上面的groupby对象转化为list来看:
只看幸存者,按性别分组
5.1.2 依据多个键分组
5.2 多级索引对象
5.2.1 多级索引的Series
上面个例子可以看到,依据多个键进行分组的结果,返回了有两级索引的Series对象。
5.2.1.1 通过Series自带的索引值
5.2.1.2 通过一级索引标签
5.2.1.3 通过二级或以上索引标签
5.2.2 多级索引的DataFrame
索引变成两级,一级是“性别”,第二级是“船舱等级”
提取性别为女的数据
提取船舱等级为3的数据:使用IndexSlice对象(索引切片器)
5.3 索引的重置与设置
- sort_index() 对数字索引进行排序(不会重置,不会改变原来数字索引的大小)
- reset_index() 把标签列转为数据列
- set_index() 指定数据列设置为标签列
5.3.1 .reset_index()方法
把上面的多级索引全部转化为一列列单独的字段,然后用序列数字重新变成新表的索引
在.reset_index()方法中用参数level指定要转化成字段的索引名
drop=True #把原本的索引删掉,重新排列
5.3.2 .set_index()方法
指定数据列为标签列
5.4 索引的.stack()与.unstack()
行索引“性别”,挪到列索引中,用unstack()方法的参数level指定索引“性别”
上表我们就可以直观地看出一等舱中没有男性。
把上面的表“复原”也是使用.stack()方法的level参数指定就行
5.5 分组后累积、过滤、转换、应用
5.5.1 分组后合计aggregate()
也可以简写agg()
若想看不同性别乘客的:船舱等级的众数、年龄的均值。可以使用groupby对象的aggregate()方法,填入带映射关系的字典即可
以性别分组后,另外三个字段的求和以及均值的情况
5.5.2 分组后过滤filter()
titanic中各年龄段的年龄标准差情况如下:
使用filter()方法,将年龄标准差小于2的年龄组删除,只保留标准差大于等于2的年龄组:
def filer_func(x):
return x["年龄"].std()>2 #这里面的x其实是用来传输groupby对象的每一小组
titanic_02=titanic.groupby("年龄段").filter(filer_func)
titanic_02.head()
再看一下各年龄段的年龄标准差,标准差小于2的年龄段数据已经删除:
5.5.3 分组后转换transform()
group对象的transform()方法,在数据转换之后的形状和原来的是一样的,但是并不是单纯地将一列数据转换,
而对是分组之后,不同小组的数据内部按照相同的逻辑和组内指标来转换,常见的例子是实现数据组内标准化:
以年龄分组,对每个人的年龄进行组内标准化(每个人的年龄减去自己年龄组的年龄均值):
def standar(x):
return x-x.mean() #这里面的x其实是用来传输groupby对象的每一小组,x-x.mean()其实用了广播
titanic_03.groupby("年龄段").transform(standar)
5.5.4 分组后应用apply()
若想在分组后对小组使用任意方法,可以使用apply()。
- 输入一个分组数据的DataFrame进行apply(),可以返回一个DataFrame或Series或一个标量。
- group()和apply()的组合操作可以适应apply()返回的结果类型,因此非常灵活。
以“船舱等级”为分组,如果这个船舱等级的男性多,则将该船舱等级改为“男多年龄段”,反之亦然
def more(x):
i=x["性别"].value_counts().index[0] # 这里面的x其实是用来传输groupby对象中的每一小组
return "%s性的多船舱等级"%i
titanic_03.groupby("船舱等级").apply(more)
5.6 透视表
5.6.1 pd.pivot_table()
pd.pivot_table(values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')
- values:要聚合的列,可选
- index:在数据透视表索引上分组的键。
- columns:在数据透视表列上分组的键。
- aggfunc:function,function of list,dict,default numpy.mean
- 如果传递的函数列表,则生成的数据透视表将具有分层列。
- 如果传递了dict,则键是要聚合的列,值是函数或函数列表。
- fill_value:标量,默认无,用于替换缺失值的值。
- margin:boolean,默认为False,添加所有行/列(例如,对于小计/总计)。
- dropna:布尔值,默认为True,不包括条目全部为NaN的列
- margins_name:string,默认为’All’,当边距为真时,将包含总计的行/列的名称。
若想查看泰坦尼克乘客的生存率状况,从性别和船舱等级两个维度观察
默认多维分析的对象是均值
5.6.1.1 参数aggfunc
aggfunc参数指定聚合函数多维分析"幸存否"的不是均值,而是总人数
求幸存者的总人数和平均年龄
5.6.1.2 参数margins
titanic.pivot_table("幸存否",index="性别",columns="船舱等级",aggfunc="sum",margins=True) #为True时会添加行/列的总计
5.6.2 多级透视表
titanic.pivot_table("幸存否",index=["性别","年龄段"],columns="船舱等级")
六、向量化字符串操作
6.1 Pandas字符串操作
#全部行都能输出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
import numpy as np
import pandas as pd
a=pd.Series(["make","join",np.nan,np.nan,"mary"])
a[:2]
a.str[:2] #.str表示操作作用于每个元素上
所有单词的首写字母都转化为大写.str.capitalize()
a.str.capitalize() #首字母变为大写
Series的一些字符串的切片以及合并操作,都可以通过.str的方法来调用。
a=pd.Series(["mike","join","lily","tom","mary"])
a.str[:2]
a.str[2:]
a.str[:2]+a.str[2:]
6.2 Pandas字符串方法列表
- len()
- 字符检索
- find()
- rfind()
- 字符转换
- lower()
- upper():
- title:将每个单词的第一个字符转换为大写和保持小写。
- capitalize():将第一个字符转换为大写字母保持小写。
- swapcase() :将大写转换为小写,小写转换为大写。
- translate()
- 字符类型判断
- islower()
- isupper()
- isnumeric()
- isalnum()
- isdecimal()
- isalpha()
- isdigit()
- isspace()
- istitle()
- 字符调整
- ljust()
- rjust()
- 字符对齐与填充
- startswith()
- endswith()
- center()
- zfill()
- 字符检索
- index()
- rindex()
- find()
- 字符切割
- split()
- rsplit()
- partition()
- rpartition()
- 字符整理
- strip()
- rstrip()
- lstrip()
例如:
a.str.replace("a","A")
a.str.find("o")
demo = pd.Series(["he llo","wor ld","a hh "])
demo.str.split(' ')
demo.str.split(' ').str[0]
6.2.1 字符转化.str.translate
ord()函数主要用来返回对应字符的ascii码,chr()主要用来表示ascii码对应字符的输入时数字,可以用十进制,也可以用十六进制。
6.2.2 字符调整
- .str.ljust()
- .str.rjust()
6.2.3 字符对齐与填充
a.str.startswith("m") #看每个元素是否以m开头
a.str.center(6,"*") #居中对齐,不足部分以*填充
a.str.zfill(6) #默认以0填充
6.2.4 replace()替换
6.2.5 strip()去重无用字符
6.2.6 split()进行分裂
6.2.7 字符检索.str.find()
如果.str.index()方法无法在series中找到包含字符的字符串或者出现缺失值,就会报错
用.str.find()的话,找不到检索字符的话,将会返回-1
七、练习
import numpy as np
import pandas as pd
#全部行都能输出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
1 创建一个dataframe,要求索引是a,b,c,d,列名是one,two,其中one列数据为1,2,3,two列数据为1,2,3,4
2 查看df的索引名和列名
3 给df增加一列,列名为three,列中的值为one列和two列值的乘积
4 分别用两种不同的方法删除df中的two和three列
5 用基于标签的索引和基于位置的索引两种方法提取df1中two这列的数据信息
6 用基于位置和基于标签两种方法从df1中提取b,d行one,three列的信息(提取不连续信息)
7 数据对齐及运算,观察运算结果,体会对齐原理,执行df3+df4的操作
8 查看数据框的形状\索引\列名\详细信息\简单统计描述
9 提取df6中C列数值大于5的所有信息
10 提取df6中A列数值大于5并且B列数字大于6的所有信息
11 利用isin方法提取ids为‘a’或‘b’的信息
data = {
'vals':[1,2,3,4],
'ids':['a','b','f','n'],
'ids2':['a','n','c','n']
}
df7 = pd.DataFrame(data)
df7
df7[df7['ids'].isin(["a","b"])]