简介
Pandas 是 Python 进行数据分析的一个扩展库,是基于 NumPy 的一种工具。
能够快速得从不同格式的文件中加载数据(比如 CSV 、Excel文件等),然后
将其转换为可处理的对象。
Pandas 在 ndarray 的基础上构建出了两种更适用于数据分析的存储结构,分别
是 Series(一维数据结构)和 DataFrame(二维数据结构)。在操作 Series 和
DataFrame 时,基本上可以看成是 NumPy 中的一维和二维数组来操作,数组
的绝大多数操作它们都可以适用。
Pandas Series
Series是一种一维数据结构,每一个元素都带有一个索引,与 NumPy
中的一维数组类似
Series 可以保存任何数据类型,比如整数、字符串、浮点数、Python
对象等,它的索引默认为整数,从 0 开始依次递增。Series 的结构
图,如下所示:
创建:
pd.Series(data=None, index=None, dtype=None, name=None)
- data:array-like, dict, or scalar value
- index:索引必须是不可变数据类型,允许相同。不指定时,默认为从 0 开始依次递增的整数
- dtype:数据类型,如果没有指定,则会自动推断得出
- name:设置 Series 的名称
当传入为字符串或字符时,类型为一个对象
import pandas as pd
import numpy as np
ser = pd.Series("hello") #object
ser1 = pd.Series([1,3,4,5,0]) #int64
ser2 = pd.Series(np.array([1,3,4,5,0])) #int32
'''
0 hello
dtype: object
0 1
1 3
2 4
3 5
4 0
dtype: int64
0 1
1 3
2 4
3 5
4 0
dtype: int32
'''
data = {'args':[1,2,3]}
ser3 = pd.Series(data) #args [1, 2, 3] 键作为索引,值为值
'''
args [1, 2, 3]
dtype: object
'''
ser4 = pd.Series([1,2,3],index=['n1','n2','n3'])
'''
n1 1
n2 2
n3 3
dtype: int64
'''
data = {'args':[1,2,3],'height':54,'weight':79}
ser5 = pd.Series(data,index=['n1','args','height','weight'])
'''
n1 NaN
args [1, 2, 3]
height 54
weight 79
dtype: object
'''
访问
- 位置索引访问:可以通过下标获取值,取值唯一。
- 索引标签访问:也可以通过标签获取值,但取值不唯一,不降维。
- 切片:取值不唯一情况下,通过标签进行切片会报错。标签切片左右都闭区间
修改
- 修改索引:可以通过给 index 属性重新赋值达到修改索引的目的
- 修改数据:可以通过索引和切片的方式修改数据
重索引:
Series.reindex(index=None, fill_value=np.NaN)
- index:要获取数据的索引,传入列表
- fill_value:填充的缺失值(标量),默认为 np.NaN。当找不到标签时使用
- 返回重新索引组成的新的 Series 对象,若有缺失值则会改变数据类型 如float64
- 注意:reindex操作的series对象不能有重复的索引
属性:
- dtype, empty, name, size, values(返回ndarray数组),index(对象)
方法:
Series.head(n=5)
:返回前n行数据Series.tail(n=5)
:返回后n行数据Series.isnull() / Series.notnull()
:判断是不是缺失值,返回各数据上的true false
运算:
Series 保留了 NumPy 中的数组运算,且 Series 进行数组运算的时候,索引与
值之间的映射关系不会发生改变。在进行 Series 和 Series 的运算时,把两个
Series 中索引一样的值进行运算,其他不一样的做并集,对应的值为 NaN
import pandas as pd
ser1 = pd.Series([1,2,3],index=['a','b','c'])
ser2 = pd.Series([4,5,6],index=['b','c','a'])
print(ser1+ser2)
#标签会自动排列,标签相同的相加,不同的变缺失值
'''
a 7
b 6
c 8
dtype: int64
'''
Pandas DataFrame
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html
DataFrame 是一种表格型的二维数据结构,既有行索引(index),又有列索
引(columns),且默认都是从0开始递增的整数。可以把每一列看作是共同用
一个索引的 Series,且不同列的数据类型可以不同。DataFrame 的结构图,如
下所示:
创建
pd.DataFrame(data=None, index=None, columns=None, dtype=None)
- data:array-like, dict, or DataFrame
- index:行索引。不指定时,默认为从 0 开始依次递增的整数
- columns:列索引。不指定时,默认为从 0 开始依次递增的整数
- dtype:数据类型,如果没有指定,则会自动推断得出
import pandas as pd
import numpy as np
df = pd.DataFrame([1,2,3,4])
print(df)
print(df.shape)
'''
0
0 1
1 2
2 3
3 4
(4, 1)
'''
df2 = pd.DataFrame([[1,2],[3,4]])
'''
0 1
0 1 2
1 3 4
(2, 2)
'''
df3 = pd.DataFrame({"name":['a','b','c'],"ages":[11,22,33]})
'''
键作为列标签
name ages
0 a 11
1 b 22
2 c 33
(3, 2)
'''
df3 = pd.DataFrame({"name":['tonny','peter','kitty'],"ages":[11,22,33]},index=['a','b','c'])
'''
name ages
a tonny 11
b peter 22
c kitty 33
'''
#series放列表里是躺平的 放字典里是竖着的
pd.DataFrame({"name":pd.Series(['a','b','c'])})
pd.DataFrame([pd.Series(['a','b','c'])])
df = pd.DataFrame([[1,2,3],[4,5,6]])
'''
name
0 a
1 b
2 c
0 1 2
0 a b c
0 1 2
0 1 2 3
1 4 5 6
'''
df = pd.DataFrame([[1.,2,3],[4,5,6]],index=['a','b'],columns=['col1','col2','col3'])
print(df)
print(df.dtypes)
'''
col1 col2 col3
a 1.0 2 3
b 4.0 5 6
col1 float64
col2 int64
col3 int64
dtype: object
'''
访问
- 索引获取列数据,切片获取行数据
- 如果设置了标签则不能使用下标获取
- DataFrame降维为Series
- loc指定标签获取数据,iloc指定下标获取数据:
- loc允许接两个参数分别是行和列, 且只能接收标签索引
- iloc允许接两个参数分别是行和列, 且只能接收整数索引
d = {'name': ['Tom', 'Bob', 'Linda'], 'age': [17, 18,26], 'height': [172, 176, 188]}
df = pd.DataFrame(data=d, index=['p1', 'p2', 'p3'])
print(df)
# 索引获取列数据
print(df['age'])
print(df[['age', 'name']])
# 切片获取行数据
print(df[0: 1]) # 下标切片左闭右开
print(df['p1': 'p2']) # 标签切片两边都是闭区间
# 组合使用
print(df[['name', 'age']][0: : 2])
print(df[0: : 2][['name', 'age']])
'''
name age height
p1 Tom 17 172
p2 Bob 18 176
p3 Linda 26 188
p1 17
p2 18
p3 26
Name: age, dtype: int64
age name
p1 17 Tom
p2 18 Bob
p3 26 Linda
name age height
p1 Tom 17 172
name age height
p1 Tom 17 172
p2 Bob 18 176
name age
p1 Tom 17
p3 Linda 26
name age
p1 Tom 17
p3 Linda 26
'''
d = {'name': ['Tom', 'Bob', 'Linda'], 'age': [17, 18,26], 'height': [172, 176, 188]}
df = pd.DataFrame(data=d, index=['p1', 'p2', 'p3'])
print(df)
""" loc允许接两个参数分别是行和列, 且只能接收标签索引 """
# 选取行索引为'p1'的数据
print(df.loc['p1'])
# 选取行索引为'p2'且列索引为'age'的数据
print(df.loc['p2', 'age'])
# 选取行索引为'p2'且列索引分别为'age'和'name'的数据
print(df.loc['p2', ['age', 'name']])
# 选取行索引分别为'p3'和'p2'且列索引分别为'age'和'name'的数据
print(df.loc[['p3', 'p2'], ['age', 'name']])
""" iloc允许接两个参数分别是行和列, 且只能接收整数索引 """
# 选取行索引为0的数据
print(df.iloc[0])
# 选取行索引为1且列索引为1的数据
print(df.iloc[1, 1])
# 选取行索引为1且列索引分别为1和0的数据
print(df.iloc[1, [1, 0]])
# 选取行索引分别为2和1且列索引分别为1和0的数据
print(df.iloc[[2, 1], [1, 0]])
print(pd.loc([::2,::2]) #不可1::2
print(pd.iloc([::2,::2])
修改
- 索引:df.index, df.columns
- 数据:对访问的数据重新赋值,即可修改数据;如果访问数据不存在,则会添加数据
import pandas as pd
import numpy as np
d = {'name': ['Tom', 'Bob', 'Linda'], 'age': [17, 18,26], 'height': [172, 176, 188]}
df = pd.DataFrame(data=d, index=['p1', 'p2', 'p3'])
#修改单列
df['col']=[1,2,3]
df.loc[:,'col']=[1,2,3]
#修改多列
df.loc[:,['name', 'age']] = pd.DataFrame({'name':['a','b','c'],'age':[1,2,3]},index = df.index)
df[['name', 'age']] = [['a',12],['b',23],['c',34]]
#修改单行
df[1:2] = ['a',12,12]
#修改多行
df[::2] = [['a',12,12],['b',12,12]]
#新增单列
df['new_key'] = ['c',23,23]
#新增多列
df[['new_key','BMI']] = pd.DataFrame({'new_key':[],'BMI':[]})
重索引
DataFrame.reindex(labels=None, axis=0, index=None, columns=None, fill_value=np.NaN)
- labels:要获取数据的列标签或者行标签,传入列表,与axis对应
- axis:轴的方向,0为行,1为列
- index:要获取数据的行索引,传入列表
- columns:要获取数据的列索引,传入列表
- fill_value:填充的缺失值(标量),默认为 np.NaN
- 返回重新索引组成的新的 DataFrame 对象
d = {'name': ['Tom', 'Bob', 'Linda'], 'age': [17, 18,26], 'height': [172, 176, 188]}
df = pd.DataFrame(data=d, index=['p1', 'p2', 'p3'])
print(df.reindex(index=['p1','p3'],columns=['age','height']))
'''
age height
p1 17 172
p3 26 188
'''
属性:
T,dtypes,index,empty,shape,size,columns,axes,values,
方法:
- head(n=5): 返回前n行数据
- tail(n=5): 返回后n行数据
- isnull() / notnull(): 检测DataFrame中的缺失值
- 多数操作只针对列,可以通过转置来插入行
DataFrame.insert(loc, column, value)
- loc:int,整数列索引,指定插入数据列的位置
- column:新插入的数据列的名字
- value:int, Series, or array-like,插入的数据
DataFrame.pop(item)
1. item:要删除的列标签
2. 删除并返回 item 指定的数据
3. 可以使用 del 直接删除某列 :del df['col']
DataFrame.append(other, ignore_index=False)
1. other:DataFrame or Series/dict-like,要添加的数据
2. ignore_index:如果指定为 True,则索引将变为从0开始递增的整数
3. 返回一个新的 DataFrame,默认0轴拼接pd.concat(objs, axis=0, join='outer', ignore_index=False)
1. objs:Series 或 DataFrame对象的序列或映射
2. axis:要拼接的轴
3. join:外连接(‘outer’)保留两个表中的所有信息,有缺失值;内连接(‘inner’)只保留共有信息
4. ignore_index:如果指定为 True,则索引将变为从0开始递增的整数,重新设置索引标签,默认使用原标签
5. 返回一个新的 DataFrame
import pandas as pd
import numpy as np
d = np.arange(9).reshape(3,3)
df1 = pd.DataFrame(data=d,columns=['a','b','c'],index=['n1','n2','n3'])
d = np.arange(16).reshape(4,4)
df2 = pd.DataFrame(data=d,columns=['a','b','c','f'],index=['n1','n2','n3','n4'])
print(pd.concat([df1,df2],join='inner',ignore_index=True))
print(pd.concat([df1,df2],join='outer',axis=1,ignore_index=True))
'''
a b c
0 0 1 2
1 3 4 5
2 6 7 8
3 0 1 2
4 4 5 6
5 8 9 10
6 12 13 14
0 1 2 3 4 5 6
n1 0.0 1.0 2.0 0 1 2 3
n2 3.0 4.0 5.0 4 5 6 7
n3 6.0 7.0 8.0 8 9 10 11
n4 NaN NaN NaN 12 13 14 15
'''
pd.merge(left, right, how='inner', on=None)
1. left:左侧 DataFrame 对象
2. right:右侧 DataFrame 对象
3. how:要执行的合并类型。- 'inner’为内连接,取左右两个 DataFrame的键的交集进行合并,键值需要完全一致,然后左边的行+右边的行;
- 'left’为左连接,以左侧 DataFrame 的键为基准进行合并,如果左侧 DataFrame 中的键在右侧不存在,则用缺失值NaN 填充;
- 'right’为右连接,以右侧 DataFrame 的键为基准进行合并,如果右侧 DataFrame 中的键在左侧不存在,则用缺失值NaN 填充;
- 'outer’为外连接,取左右两个 DataFrame 的键的并集进行合并
4. on:指定用于连接的键(即列标签的名字),该键必须同时存在于左右两个 DataFrame 中,如果没有指定,那么将会以两个 DataFrame 的列名交集做为连接键
d1 = {'name': ['Tom', 'Bob', 'Jack'], 'age': [18, 17,19], 'weight': [65, 66, 67]}
df1 = pd.DataFrame(data=d1)
d2 = {'name': ['Tom', 'Tony'], 'height': [168, 187],'weight': [65, 68]}
df2 = pd.DataFrame(data=d2)
print(df1)
print(df2)
print(pd.merge(df1, df2, how='inner'))
print(pd.merge(df1, df2, how='left', on='name'))
print(pd.merge(df1, df2, how='right', on='name'))
print(pd.merge(df1, df2, how='outer', on='name'))
'''
name age weight
0 Tom 18 65
1 Bob 17 66
2 Jack 19 67
name height weight
0 Tom 168 65
1 Tony 187 68
name age weight height
0 Tom 18 65 168
name age weight_x height weight_y
0 Tom 18 65 168.0 65.0
1 Bob 17 66 NaN NaN
2 Jack 19 67 NaN NaN
name age weight_x height weight_y
0 Tom 18.0 65.0 168 65
1 Tony NaN NaN 187 68
name age weight_x height weight_y
0 Tom 18.0 65.0 168.0 65.0
1 Bob 17.0 66.0 NaN NaN
2 Jack 19.0 67.0 NaN NaN
3 Tony NaN NaN 187.0 68.0
'''
DataFrame.drop(labels=None, axis=0, index=None, columns=None,inplace=False)
1. labels:要删除的列标签或者行标签,如果要删除多个,传入列表,与axis对应
2. axis:轴的方向,0为行,1为列
3. index:要删除的行索引,如果要删除多个,传入列表
4. columns:要删除的列索引,如果要删除多个,传入列表
5. inplace:inplace=True时,对原数据操作 原地操作,返回NoneDataFrame.dropna(axis=0, how='any', thresh=None, subset=None,inplace=False)
1. 删除缺失值所在的行或列
2. axis:0表示删除包含缺失值的行,1表示删除包含缺失值的列
3. how:- ‘any’ 表示如果存在任何缺失值,则删除该行或列;
- ‘all’ 表示如果所有值都是缺失值,则删除该行或列
4. thresh:只保留至少n个非NaN值的行或列,n由该参数指定
5. subset:定义要根据哪些列(行)中的缺失值来删除行(列),和axis成行列对应关系,传入列表
6. inplace:如果为 True 表示对原数据操作,返回 None
DataFrame.fillna(value=None, method=None, axis=None, inplace=False,limit=None)
1. value:需要填充的数据,可以是数值,可以是字典,字典时按键对应标签填充,键不存在则无效果不填充,字典只能填充列按0轴填
2. method:填充方式。‘pad’/‘ffill’ 表示用前一个非缺失值去填充该缺失值;‘backfill’/‘bfill’ 表示用后一个非缺失值填充该缺失值,前一个后一个根据axis指定的填充方向
3. axis:指定填充方向,0表示行方向,1表示列方向,默认行方向
4. inplace:如果为 True 表示对原数据操作,返回 None
5. limit:限制填充个数DataFrame.info(verbose=None, show_counts=None)
1. verbose:是否打印完整的摘要,为None时表示打印完整摘要,为False则打印简短摘要
2. show_counts:是否显示Non-Null Count,为None时表示显示,为False则不显示
3. 打印 DataFrame 的简明摘要DataFrame.describe(percentiles=None, include=None, exclude=None)
1. percentiles:默认值为 [.25, .5, .75],它返回第 25、第 50 和第 75 个百分位数
2. include:包含在结果中的数据类型;- 默认None表示结果将包括所有数字列;
- 'all’表示包括所有列;
- 'number’表示包括所有数字列;
- 'object’表示包括所有字符列,与数字列统计信息不同
3. exclude:不包含在结果中的数据类型;默认None表示结果不会排除任何列;'number'表示不包括所有数字列;'object'表示不包括所有字符列
4. 返回描述性统计,默认统计数字列,比如均值,字符出现频次
- 描述:
1. DataFrame.count(axis=0) 返回指定轴的非空值的数
2. DataFrame.max(axis=0) 返回指定轴的最大值
3. DataFrame.min(axis=0) 返回指定轴的最小值
4. DataFrame.mean(axis=0) 返回指定轴的平均值
5. DataFrame.var(axis=0) 返回指定轴的方差
6. DataFrame.std(axis=0) 返回指定轴的标准差 DataFrame.sample(n=None, frac=None, replace=False, random_state=None,axis=None)
1. 随机采样
2. n:默认为1,表示要采样的行数,不能和 frac 参数一起使用
3. frac:表示要采用的比例,不能和 n 参数一起使用
4. replace:表示是否有放回采样,不放回则表示不重复采样
5. random_state:随机数种子
6. axis:表示采样的方向,默认为0,行采样从指定的轴返回随机样本DataFrame.drop_duplicates(subset=None, keep='first', inplace=False)
1. 返回去重(删除重复行)之后的 DataFrame
2. subset:表示要进行去重的列名,默认为 None,表示所有列。指定根据哪几列判断。
3. keep:保留哪些副本。'first’表示只保留第一次出现的重复项,删除其余重复项;'last '表示只保留最后一次出现的重复项;False 则表示删除所有重复项
4. inplace:False 表示删除重复项后返回一个副本;Ture 表示直接在原数据上删除重复项
5.DataFrame.sort_values(by, axis=0, ascending=True, inplace=False,na_position='last')
1. by可以是列表,有多个时,先按第一个排序,然后有重复项再将重复项按第二个排序
2. ascending可以是列表,与by对应
3. na_position 缺失值位置DataFrame.apply(func, axis=0)
1. 根据func对DataFrame的各项操作DataFrame.groupby(by=None, axis=0, as_index=True, sort=True,dropna=True)
1. 返回一个包含分组信息的 DataFrameGroupBy 对象,可根据 组号和内容 迭代 DataFrameGroupBy降维为SeriesGroupBy。相当于筛选
2. by:指定根据哪个或者哪些标签分组
3. axis:沿着分组的轴,0表示行,1表示列
4. as_index:对于聚合操作的输出结果,默认将分组列的值作为索引,如果将 as_index 设置为 False,可以重置索引(0, 1, 2…)
5. sort:结果按分组标签的值升序排列,设置为False则不排序
6. dropna:默认为 True 时,分组标签那列的 NaN 在分组结果中不保留,设置为 False,可以保留 NaN 分组
7. GroupBy对象DataFrameGroupBy
的属性:groups,get_group(label),agg(函数或函数名) 聚合操作 针对各个组进行分类汇总操作SeriesGroupBy
的属性:transform(函数或函数名),transform转换方法对各组分别操作后,得到的结果是同一组内的样本共有的,再按照原索引的顺序返回结果
Pandas文件读写
CSV文件读写
pd.read_csv(filename,sep=',',...)
:- 返回 DataFrame
- header 参数,默认自行推断, 会把第一行数据作为列索引or列标签(表头),也可以指定列索引
- names 参数可以指定列索引, 如果指定names, 则header推断为None
- nrows 参数用来读取指定行数的数据 ,header先推断再读取header后的行
- skiprows 参数用来指定需要跳过的行 (先跳过, header再推断),可为索引列表,表示跳过对应的索引行
- usecols 参数用来读取指定列的数据:这里读取第1列和第3列
- chunksize参数指定时, read_csv会返回TextFileReader对象,TextFileReader对象是个迭代器, 可以按照chunksize迭代。在大数据中使用,分批读取
df.to_csv(filename,...)
:- 把 DataFrame 写入 csc 文件
- sep 参数默认为逗号, 所以文件中分隔符为逗号
- index 参数默认为True, 所以行索引也被写入了文件
- header 参数默认为True, 所以列索引也被写入了文件
EXCEL文件读写
df.to_excel(filename,...)
: 优点快速,但是对文件从头覆盖写,不适合写多个工作表,可以通过写到 ExcelWriter 的实例对象解决。pd.Excelwriter(filename)
:适合写多个工作表
# 把DataFrame写入excel文件
writer = pd.ExcelWriter('./test11.xlsx')
# 写入工作表1
df.to_excel(writer, sheet_name='工作表1', index=False)
# 写入工作表2
df.iloc[:, :2].to_excel(writer, sheet_name='工作表2',index=False)
writer.close()
# with语句更优雅
with pd.ExcelWriter('./test11.xlsx') as writer:
df.to_excel(writer, sheet_name='工作表1', index=False)
df.iloc[:, :2].to_excel(writer, sheet_name='工作表2',index=False)
pd.read_excel(filename,...)
:- 使用names参数时注意 header 默认为0
- sheet_name 参数可以为索引也可以是标签