Pandas学习
pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使Python成为强大而高效的数据分析环境的重要因素之一。(来自百度百科)
这是参考了知乎上这篇文章的教程做的一个笔记https://www.zhihu.com/question/56310477/answer/873227129?utm_source=wechat_session
第一步当时是import pandas as pd
1. 创建、读取和存储
1.1 创建
创建函数包括两个部分,一部分是一个字典,表示各个数据项;另一个是相应的索引
df1 = pd.DataFrame({'工资':[5000, 7000, 9000, 8500],
'绩效分':[60, 84, 98, 91],
'备注':['不及格', '良好', '最佳', '优秀']}
, index = ['老王', '小刘', '小赵', '老龚'])
df1
创建后的效果:
1.2 读取
这个就没什么好说的,直接看下面函数就行
df = pd.read_csv('csv文件路径', engine = 'python')
# 读取csv文件,engine是指定分析引擎,用python就对了~
df = pd.read_excel('xls文件路径', sheet_name = '表单名称')
# 读取xls文件,sheet_name用于指定表单(不指定默认读取第一个表单)
1.3 存储数据
没啥好说的,直接保存就完事了
df.to_csv('csv文件路径')
df.to_excel('xls文件路径')
2. 数据查看
2.1 查看数据前(后) i 行
有时数据量非常大,查看所有数据没有多大意义,所以只需查看一部分数据了解概括
df.head() # 默认查看数据前五行,当时也可指定行数df.head(i)
df.tail() # 默认查看数据后五行,当时也可指定行数df.tail(i)
查看效果:
2.2 查看数据信息(行数、缺失值等)
将数据加载好了后可以使用info
函数查看数据信息
df.info()
输出结果:
2.3 统计信息
可以对数据中的数值型数据进行统计
df.describe()
输出样例:
3. 数据列的操作
3.1 增加数据列
和python的字典类似,代码如下
df['新增的列'] = range(0, len(df))
df.head()
输出结果:
3.2 删除列
使用drop
函数
df.drop('新增的列', axis = 1, inplace = True) # 删除数据,axis=1表示对列进行操作, inplace表示在源数据上进行修改
df.head()
3.3 选中列
同时选中多个列
df2[['列名1', '列名2', '列名3']]
举个栗子:
4. 数据类型
4.1 字符串
值得注意的是,保存的数据中除了数值型数据,其他类型数据都是object,所以对数据的字符串进行处理需要先调用str
,其余操作与python完全相同
举个栗子:
df2['来源明细'] = df2['来源明细'].str.replace('-','')
输出结果:
4.2 数值型
这个其实没啥好讲的,可以直接对数据进行操作,不过值得注意的是,可以使用其广播特性,可以看下面这个栗子:
df['访客数']+1000 # 广播机制,为这一列都加上1000
4.3 时间类型
时间类型里面学问比较多,这里简要学习一下
首先添加时间:
data = []
for i in range(len(df2)):
data.append('2020-7-'+str(i+1))
df2['日期'] = data
df2['日期'].head() # 默认添加是字符串类型的
输出效果:
可以看到默认添加的时间是字符串类型的,但是可以将字符串类型的转化为时间类型(当然需要满足xxxx-xx-xx
或xxxx/xx/xx
等格式)
df2['日期'] = pd.to_datetime(df2['日期'])
df2['日期'].head()
输出效果:
当我们将数据转化为时间类型时,就行进行许多人性化的操作,比如减法(求距离某一天有多少天)
5. 灵活的索引
5.1 位置索引
位置索引使用iloc
函数,使用起来比较简单,可以直接看下面代码。
df.iloc[13:18, 0:4] # 第个参数填写选取行,第二个参数填写选取列
选取效果:
5.2 标签索引
和位置索引类似,使用loc
函数,使用方法类似,但是由于使用的不是数字,而是标签,所以填写参数的形式有所不同。
df2.loc[df2['流量来源'].isin(['二级', '三级']), ['流量来源', '来源明细', '访客数', '支付转化率']]
# 注意isin()函数的使用,大家看看都能明白
输出结果(成功筛选出流量来源
为二级
或者三级
的行数,并且只展示 ‘流量来源’, ‘来源明细’, ‘访客数’, ‘支付转化率’ 这几列):
当然可以用其他方式索引行,比如使用条件判断:
df2.loc[df2['访客数']>df2['访客数'].mean(), :]
一个条件判断不够,那你可以试试多个:
df2.loc[(df2['访客数']>df2['访客数'].mean()) & (df2['流量来源'].isin(['二级', '三级'])), :]
6. 数据合并
6.1 纵向合并
将几个数据纵向拼接起来,使用concat
函数(需要总想数据维度完全一致)
df = pd.concat([d1, d2, d3]) # 将数据d1,d2,d3纵向合并
输出结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZWl0C7Sc-1595605777296)(https://s1.ax1x.com/2020/07/24/UvtMSP.png)]
6.2 横向合并
使用merge
函数(但是也可以使用concat
,只需设置一下axis),merge
函数可以允许横向维度不同的情况。
函数原型:
merge(left, right, left_index, left_index, right_index, left_on, right_on, how)
参数说明:
left
:参与合并的左侧DataFrameright
:参与合并的右侧DataFrameleft_index
:bool类型,当为True时将左侧行索引作为连接的键right_index
:bool类型,当为True时将右侧行索引作为连接的键left_on
:左侧DataFrame用于连接键的列right_on
:右侧DataFrame用于连接键的列how
:连接方式,包括’inner’(连接键取交集), ‘outer’(连接键取并集), ‘left’(取左侧连接键), ‘right’(取右侧连接键)。(默认为inner)
栗子1:
# 分别尝试不同的连接方式,并且都是使用索引作为连接键
pd.merge(left=h1, right=h2, left_index=True, right_index=True, how='inner')
pd.merge(left=h1, right=h2, left_index=True, right_index=True, how='left')
pd.merge(left=h1, right=h2, left_index=True, right_index=True, how='right')
pd.merge(left=h1, right=h2, left_index=True, right_index=True, how='outer')
运行后结果:
栗子2
score_combine = pd.merge(left=max_score, right=min_score, left_on='姓名', right_on='姓名', how='inner')
# 将姓名作为连接键将成绩合并一下
合并效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wuw6FvyU-1595605777298)(https://s1.ax1x.com/2020/07/24/UxVLm6.png)]
7. 数据行的操作
7.1 删除空行
使用dropna
可以去除含有缺失值的行
df.dropna() # 删除表中含有缺失值的行
运行结果
删除空行默认是删除含有缺失数据的行,当然也可以指定某列中的含有缺失数据的行。
df.dropna(subset=['客单价']) # 当然也可以指定参数
7.2 行去重
将DataFrame中重复的行去掉
repeat = pd.concat([df, df])
print(len(repeat), len(df))
# 将一个DataFrame重复两遍
unique = repeat.drop_duplicates() # 去重
print(len(unique))
输出结果:
30 15
15
7.3 行排序
使用sort_values
按照指定列进行排序,而且可以同时指定多列(现在第一个指定列的基础上,再进行后续排序)
sort_df = df.sort_values(['流量级别', '支付金额'], ascending=False)
# 先按照流量级别排序,再按照支付金额降序(ascending升序)
输出结果
7.4 行分组
将数据按照某一列的值进行分组,然后再分组的基础上再进行其他操作(比如sum(), max(), min()等等)
df.groupby('流量级别').sum() # 按照流量级别分组后然后对各项数据进行求和,有的变量不是数值型变量无法求和
输出结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vsYGtDZw-1595605777300)(https://s1.ax1x.com/2020/07/24/UxKamn.png)]
当然也可以指定数据项进行统计
df.groupby('流量级别')[['访客数', '支付金额']].sum() # 选择指定的数据项进行统计
输出结果:
可以看到上述栗子分组后都会将分组项默认转化为index
,当然我们可以指定参数,不让其成为index
df.groupby('流量级别', as_index=False)[['访客数', '支付金额']].sum() # 分组后默认转化为索引列,当时可以指定
输出结果
7.5 行打标
往往行就是代表一个样本数据,我们经常就会有这样的需求,需要对样本进行打标,实现这一个打标的过程我们可以使用切分函数cut
。
函数原型:
pd.cut(x, bins, right, labels)
参数说明:
x
:待切分的一维数组bins
:切分方式,① 传入列表,则会按照列表中各个数据所形成的区间进行切分;② 传入数字,则会将数据切分成指定组数。right
:bool类型,True时为左开右闭,否则相反label
:各个区间所对应的标签,也可不指定
我们一个一个逐步深入:
pd.cut(x = df['访客数'], bins=[0, 100, 1000, 10000, 100000], right=True)
# 将数据分组划分到相应的区间,默认为左开右闭(课通过设置right来修改)
进一步的,尝试给各个区间打上标签:
pd.cut(x = df['访客数'], bins=[0, 100, 1000, 10000, 100000],
right=True, labels=['辣鸡', '百级', '千级', '万级']) # 可以为每一个区间打标
输出结果
有了以上这些我们就可以给我们的DataFrame打标了
df['分类达标']=pd.cut(x = df['访客数'], bins=[0, 100, 1000, 10000, 100000],
right=True, labels=['辣鸡', '百级', '千级', '万级']) # 可以为每一个区间打标
df
输出结果:
8. apply函数
数据进行了行分组后就可以使用apply函数对各个组进行处理,可以使用现有的一些函数,如max
,min
等等,也可以自己定义,所以有时候就非常的方便。
使用现有的一些函数:
max_score = score.groupby('姓名')['综合成绩'].apply(max).reset_index()
# 一些常见的函数都可以apply(比如max min len) reset_index用于取消姓名索引
输出结果:
自定义apply函数
def bias(x):
return x.max()-x.min() # 求出最大的分数波动
score_bias = score.groupby('姓名')['综合成绩'].apply(bias).reset_index()
输出结果: