文章目录
1 Pandas介绍
1.1 为什么会有Pandas?
Pandas支持大部分Numpy语言风格,尤其是数组函数与广播机制的各种数据处理。但是Numpy更适合处理同质型的数据。而Pandas的设计就是用来处理表格型或异质型数据的,高效的清洗、处理数据。
1.2 Pandas是什么
Pandas是基于Numpy的一种工具,提供了高性能矩阵的运算,该工具是为了解决数据分析任务而创建的。也是贯穿整个Python数据分析非常核心的工具。
1.3 Pandas涉及的内容
- Pandas基础
- 数据清洗与准备
- 数据聚合与分组
- 时间序列
1.4 常用的数据读取
- pandas.read_csv():打开csv文件。
- pandas.read_excel(): 打开excel文件。pandas打开.xlsx文件报错xlrd.biffh.XLRDError: Excel xlsx file; not supported 的原因是xlrd更新到了版本,只支持.xls文件。解决方法一:安装旧版xlrd在cmd 中运行
pip uninstall xlrd
后再运行pip install xlrd == 1.2.0
。解决方法二:也可以用openpyxl代替xlrd打开.xlsx文件,例如:df = pandas.read_excel('data.xlsx',engine='openpyxl')
- pandas.read_json():打开json文件。
- pandas.read_sql():打开sql数据库文件。
1.5 常用的数据存储
- df.to_csv():存储到csv文件
- df.to_excel():存储到excel表格
- df.to_json():存储到json文件
- df.to_sql():存储到数据库
2 Pandas数据结构介绍
2.1 Series
2.1.1 Series介绍
Series是一种一维的数组型对象,它包含了一个值序列(values),并且包含了数据标签,称为索引(index)。
2.1.2 Series创建
pandas.Series(data=None,index=None,dtype=None,name=None,copy=False)
参数说明:
- data:创建数组的数据,可为array-like,Iterable,dict,or scalar value
- index:指定索引,必须为集合,行索引可重复,另外索引列长度必须与值列长度一致
- dtype:数组数据类型
- name:数组名称
- copy:是否拷贝
data可为iterable,dict,or scalar value
import pandas as pd
pd.Series([1,2,3,4,5,6]) # data为iterable
# data为dict
dic = {
'name':'hao','age':18,'gender':'male'}
ser = pd.Series(dic)
print(ser)
'''
name hao
age 18
gender male
dtype: object
'''
# 构建索引列表
index_data = ['class','name','age']
ser1 = pd.Series(data=dic,index=index_data) # 以index指定的为主,对应值通过字典的键进行映射,无映射关系则为NaN
print(ser1)
'''
class NaN
name hao
age 18
dtype: object
'''
索引默认为range(0,n),可以通过index指定索引,也可以指定索引的名称
import pandas as pd
s = pd.Series([1,2,3,4,5],index=list('abcde'))
# 指定索引的名称
s.index.name = 'index_name'
数据类型根据data自动调整,但是也可以通过dtype指定,也可以用series.astype(dtype)
进行修改
import pandas as pd
s1 = pd.Series(np.random.randint(1,10,size=5),dtype='float')
s1 = s1.astype(dtype='int64')
除此之外,Pandas可以使用Numpy的数组函数:
series.dtype
—> 查看数据类型series.astype()
—> 修改数据类型series.head(n)
—> 预览数据前5条,n默认为5series.tail(n)
—> 预览数据后5条,n默认为5
如果需要显示所有数据,则需以下代码,但不建议使用
import pandas as pd
pd.set_option('display.max_columns',None) # 显示所有列
pd.set_option('display.max_columns',None) # 显示所有行
pd.set_option('max_colwidth',100) # 设置value的显示长度为100,默认为50
2.1.3 Series的索引与值
series.index
—> 查看索引series.values
—> 查看值序列,返回ndarray对象,说明pandas数据类型的最底层是Numpy的数据类型series.reset_index(drop=False)
—> 重置索引,drop默认为False,表示是否删除原索引
注意:索引对象是不可变的,所以不能单个修改索引。
2.1.4 Series索引与切片
- 通过标签 —> series[‘标签’]
- 通过索引 —> series[‘索引’]
- 通过标签 —> series.loc(标签)
- 通过索引 —> series.iloc(索引)
import pandas as pd
s = pd.Series(range(1,6),index=list('abcde'))
# 查看数据
print(s['b']) # 行标签
print(s[1]) # 通过索引下标获取
print(s.loc['b']) # 通过标签
print(s.iloc[1]) # 索引下标
# 将4改为10,5改为11
s['d'] = 10
s[4] = 11
# 使用神奇索引查看1和3
print(s[['a','c']])
print(s[[0,2]])
# 切片,查看1~3
print(s[:3])
print(s.iloc[:3])
print(s['a':'c']) # 切片可以使用行标签,但区间为双闭合区间
# 布尔索引
s[s>3]
2.1.5 Series运算
series与series的运算:
- 共同索引对应位置进行运算,其他填充为nan
- 没有共同索引时,则全部为nan
import pandas as pd
s1 = pd.Series(range(10,20),index=range(10))
s2 = pd.Series(range(20,25),index=range(5))
s3 = pd.Series(rang(1,4),index=list('abc'))
# 与标量运算
s1 * 3
# in判断
print('a' in s3) # 结果为True。注意:in判断的是标签,不能判断value值
# series与series的运算
print(s1+s2)
'''
0 30.0
1 32.0
2 34.0
3 36.0
4 38.0
5 NaN
6 NaN
7 NaN
8 NaN
9 NaN
dtype: float64
'''
注意:pandas会根据数据类型自动处理缺失数据
import pandas as pd
pd.Series(['a','b',None]) # object
pd.Series([1,2,3,None]) # float
2.2 DataFrame
2.2.1 DataFrame介绍
DataFrame表示的是矩阵的数据表,它包含已排序的列集合,每一列可以是不同的值类型(数值、字符串、布尔值)。在DataFrame中,数据被存储为一个二维块(包含行索引、列索引、值)。
2.2.2 DataFrame创建
pandas.DataFrame(data=None,index=None,columns=None,dtype=None,copy=False)
- data:创建数组的数据,可为ndarray,dict
- index:指定行索引,序列对象
- columns:指定列索引,序列对象
- dtype:数组数据类型
- copy:是否拷贝
import pandas as pd
import numpy as np
# data为ndarray数组
d1 = pd.DataFrame(np.random.randint(1,100,size=(3,3)))
print(d1)
'''
0 1 2
0 65 27 82
1 91 22 19
2 59 20 31
'''
# 打印值
print(d1.values) #
'''
[[65 27 82]
[91 22 19]
[59 20 31]]
'''
# 打印行索引
print(d1.index) # RangeIndex(start=0, stop=3, step=1)
# 打印列索引
print(d1.columns) # RangeIndex(start=0, stop=3, step=1)
# 创建的时候,可以指定index和columns来设置行索引和列索引
d2 = pd.DataFrame(np.random.randint(60,100,size=(3,3)),index=['mm','xd','sm'],columns=['java','python','go'])
print(d2)
'''
java python go
mm 95 96 99
xd 64 60 69
sm 97 67 60
'''
2.2.3 重置索引
除了创建时可以指定,我们创建后还可以通过df.reindex()
进行重置索引。
df.reindex(index=None,columns=None,axis=None,fill_value=nan)
import pandas as np
import numpy as np
df=pd.DataFrame(np.arange(9).reshape(3,3),index=list('abc'),columns=list('ABC'))
# 注意:如果不指定索引,默认为行索引
print(reindex([1,2,3])) # 如果重置的索引与df中指定的index没有关系,则全部填充为nan,而nan可以通过fill_value参数变为其他值
print(df.reindex(['b','c','a']) # 如果重置的索引与df中指定的索引完全一致,但是顺序不一致,则根据重置索引调整对应行的数据
print(df.reindex(['b','c','a','d'])) # 如果重置索引比df指定的索引多,则多出的部分填充为nan,而nan可以通过fill_value参数变为其他值
2.2.4 DataFrame基础操作
df.shape
—> 查看数组形状,返回值为元组df.dtypes
—> 查看列数据类型,注意后面的s不要忘了df.ndim
—> 查看数据维度,返回为整数df.index
—> 行索引df.columns
—> 列索引df.values
—> 值df.head(n)
—> 显示头部几行,默认n=5df.tail(n)
—> 显示末尾几行,默认n=5df.info()
—> 相关信息概述:1、数组类型;2、行索引类型,以及行数;3、列数;4、每列的数据类型;5、数据是否完整,也就是non-null的个数。
import pandas as pd
# data为dict时,key对应列索引、index不指定则为默认的、values为对应的值
data = [
{
"name":"amy","age":18,"tel":10086},
{
"name":"bob","age":18},
{
"name":"james","tel":10086},
{
"name":"zs","tel":10086},
{
"name":"james","tel":10086},
{
"name":"ls","tel":10086},
]
d2 = pd.DataFrame(data)
print(d2.head())
print(d2.tail())
print(d2.info())
2.2.5 DataFrame查数据(索引与切片)
直接使用索引与标签:
类型 | 描述 |
---|---|
df[:索引] | 表示对行操作 |
df[‘列标签’]或df[[‘列标签’,‘列标签’]] | 表示对列进行操作 |
import pandas as pd
import numpy as np
data = [
{
"name":"amy","age":18,"tel":10086},
{
"name":"bob","age":18},
{
"name":"james","tel":10086},
{
"name":"zs","tel":10086},
{
"name":"james","tel":10086},
{
"name":"ls","tel":10086},
]
df = pd.DataFrame(data,index=list('abcdefg'))
'''行索引'''
# 取前两列
print(df[:2]) # 索引取行
print(df[:'b']) # 标签取行(注意:标签索引是双闭合区间)
'''列索引,列一定要用标签索引取值'''
# 取name这一列。注意:DataFrame取到的每一列都是一个Series,所以包含行索引部分
print(df['name']) # 方式一
print(df.name) # 方式二
# 取name,age这两列
print(df[['name','age']])
# 取前两行的name值,用递归的方式
print(df[:2]['name']) # 方式一
print(df.name[:2]) # 方式二
# 布尔索引取出name不为bob的值
print(df[df.name != 'bob'])
# 如果DataFrame数据全为数值
df2 = pd.DataFrame(np.arange(16).reshape(4,4),columns=list('ABCD'))
# 取出大于5的数据,小于5的会填充为NaN
print(df2[df2>5])
'''
A B C D
0 NaN NaN NaN NaN
1 NaN NaN 6.0 7.0
2 8.0 9.0 10.0 11.0
3 12.0 13.0 14.0 15.0
'''
使用loc及iloc查询数据:
- df.loc[行,列] —> 通过轴标签选择数据
- df.iloc[行,列] —> 通过整数索引选择数据
具体使用如下:
类型 | 描述 |
---|---|
df.loc[val] | 根据标签索引选择DataFrame的单行或多行 |
df.loc[:,val] | 根据标签索引选择DataFrame的单列或多列 |
df.loc[val1,val2] | 同时选择行和列中的一部分 |
df.iloc[where] | 根据位置索引选择DataFrame的单行或多行 |
df.iloc[:,where] | 根据位置索引选择DataFrame的单列或多列 |
df.iloc[where_i,where_j] | 根据位置索引选择行和列 |
import pandas as pd
df3 = pd.DataFrame(np.arange(16).reshape(4,4),index=['php','java','python','go'],columns=['one','two','three','four'])
# df.loc[]是以标签来取值 [行,列]
print(df3.loc['python',:]) # 取Python这一行
print(df3.loc['python']) # 只能取单行
print(df3.loc[:,'three']) # 取three这一列
print(df3.loc[['php','go'],:]) # 取php和go这两行
print(df3.loc[:,['one','four']]) # 取one和four这两列
print(df3.loc['java':'pyton',:]) # 取连续行java python
print(df3.loc[:,'one':'two']) # 取连续列one two
# df.iloc[行,列] ---> 下标索引
print(df3.iloc[2]) # 取Python这一行
print(df3.iloc[:,2]) # 取three这一列
print(df3.iloc[[0,3],:]) # 取php和go这两行
print(df3.iloc[:,[0,3]]) # 取one和four这两列
print(df3.iloc[1:3]) # 取连续行java python,注意是左闭右开的
print(df3.iloc[:,0:2]) # 取连续列one two
# 取出one two three数据,并且筛选two列大于3的数据
print(df3.loc[df['two']>0,['one','two','three']]) # 方式一
print(df3.iloc[:,:3][df3.two>3]) # 方式二
2.2.6 DataFrame修改数据
修改数据主要遵循以下两点:
- 查询数据
- 再赋值
注意:Pandas中可以直接赋值np.nan,且赋值当前列数据会自动转为浮点类型,而不是整个数组都转,这主要是因为Pandas数据可以是异质性。
import pandas as pd
df3 = pd.DataFrame(np.arange(16).reshape(4,4),index=['php','java','python','go'],columns=['one','two','three','four'])
# 修改php整行数据为8
df3.loc['php'] = 8
# 修改two整列数据为10
df3.loc[:,'two'] = 10
# 修改python行three列的数据为80
df3.loc['python','three'] = 80
2.2.7 DataFrame新增数据
新增列:df[‘新的列标签’] = 值
注意:添加列,则新添加的值的长度必须与其他列的长度保持一致,否则会报错。
插入列:如果需要在数据中插入列,则使用df.insert(loc,column,value)
参数说明:
- loc —> 为插入列的位置,int,值范围必须在0<=loc<=len(columns)
- column —> 为插入列的标签
- value —> 为插入列的值,可以为int,Series,array-like
- allow_duplicates —> 布尔值,默认为False,表示不允许存在重复列索引
添加行:df.loc[‘新的行标签’,:] = 值
我们也可以通过df.append(df2)**
方法添加行,但类似于数组与数组的堆叠拼接,但要求df2的列索引必须同df一致。
2.2.8 DataFrame删除数据
- 方法一:del df[‘列标签’] 只能删除列
- 方法二:df.drop(axis=0,index=None,columns=None,inplace=False):默认删除行,可以用axis指定轴来控制删除方向。
2.2.9 DataFrame算术
实际上,通过+ - * / // **
等符号可以直接对DataFrame与DataFrame之间或者DataFrame以及Series之间进行运算,秉承的原则是对应索引运算,存在索引不同时,返回结果为索引对的并集。但是实际操作会发现,当存在索引不同时,返回的值自动填充NaN。
2.2.10 使用填充值的算术方法
方法 | 描述 |
---|---|
add | 加法(+) |
sub | 减法(-) |
div | 除法(/) |
floordiv | 整除(//) |
mul | 乘法(*) |
pow | 幂次方(**) |
注意:Series使用算术方法,不支持指定填充值
import pandas as pd
import numpy as np
df1 = pd.DataFrame(np.ones((2,2),columns=list('ab')))
df2 = pd.DataFrame(np.ones((3,3),columns=list('abc')))
# DataFrame与Series运算
print(df1+df2) # 形状完全不一致,并不报错,而是索引相同部分进行运算,缺失部分填充nan
# DataFrame与Series运算
s = df2.iloc[0] # 取第一行
print(df2+s) # 进行0轴广播
'''
使用方法进行计算
'''
print(df1