Pandas模块学习与使用
Pandas是一个开源的,BSD许可的库,为Python (opens new window)编程语言提供高性能,易于使用的数据结构和数据分析工具。
1.Pandas概述
Pandas 是Python的核心数据分析支持库,提供了快速、灵活、明确的数据结构,旨在简单、直观地处理关系型、标记型数据。Pandas 的目标是成为 Python 数据分析实践与实战的必备高级工具,其长远目标是成为最强大、最灵活、可以支持任何语言的开源数据分析工具。经过多年不懈的努力,Pandas 离这个目标已经越来越近了。
Pandas 适用于处理以下类型的数据:
与 SQL 或 Excel 表类似的,含异构列的表格数据;
有序和无序(非固定频率)的时间序列数据;
带行列标签的矩阵数据,包括同构或异构型数据;
任意其它形式的观测、统计数据集, 数据转入 Pandas 数据结构时不必事先标记。
#Pandas 的主要数据结构是 Series(一维数据)与 DataFrame (二维数据),这两种数据结构足以处理金融、统计、社会科学、工程等领域里的大多数典型用例。对于 R 用户,DataFrame 提供了比 R 语言 data.frame 更丰富的功能。Pandas 基于 NumPy 开发,可以与其它第三方科学计算支持库完美集成。
Pandas 就像一把万能瑞士军刀,下面仅列出了它的部分优势 :
处理浮点与非浮点数据里的缺失数据,表示为 NaN;
大小可变:插入或删除 DataFrame 等多维对象的列;
自动、显式数据对齐:显式地将对象与一组标签对齐,也可以忽略标签,在 Series、DataFrame 计算时自动与数据对齐;
强大、灵活的分组(group by)功能:拆分-应用-组合数据集,聚合、转换数据;
把 Python 和 NumPy 数据结构里不规则、不同索引的数据轻松地转换为 DataFrame 对象;
基于智能标签,对大型数据集进行切片、花式索引、子集分解等操作;
直观地合并(merge)、连接(join)数据集;
灵活地重塑(reshape)、透视(pivot)数据集;
轴支持结构化标签:一个刻度支持多个标签;
成熟的 IO 工具:读取文本文件(CSV 等支持分隔符的文件)、Excel 文件、数据库等来源的数据,利用超快的 HDF5 格式保存 / 加载数据;
时间序列:支持日期范围生成、频率转换、移动窗口统计、移动窗口线性回归、日期位移等时间序列功能。
#这些功能主要是为了解决其它编程语言、科研环境的痛点。处理数据一般分为几个阶段:数据整理与清洗、数据分析与建模、数据可视化与制表,Pandas 是处理数据的理想工具。
其它说明:
Pandas 速度很快。Pandas 的很多底层算法都用 Cython优化过。然而,为了保持通用性,必然要牺牲一些性能,如果专注某一功能,完全可以开发出比 Pandas 更快的专用工具。
Pandas 是 statsmodels的依赖项,因此,Pandas 也是 Python 中统计计算生态系统的重要组成部分。
Pandas 已广泛应用于金融领域。
2.Pandas安装
注意:Python核心团队计划在2020年1月1日停止支持Python 2.7。按照NumPy的计划,2018年12月31日之前的所有Pandas版本都仍支持Python 2(译者注:之后的版本将不再支持)。
2018年12月31日之前的最终版本将是支持Python 2的最后一个版本。已发布的软件包将继续在PyPI和conda上提供。
从 2019年1月1日 开始,所有版本都只支持Python 3。
从PyPI安装
pip install pandas
用于解析HTML的可选依赖项
要使用顶级read_html() (opens new window)函数,需要以下一种库组合:
警告
如果您安装BeautifulSoup4 (opens new window),您必须安装lxml (opens new window)或html5lib (opens new window)或两个都安装。
read_html() (opens new window)不能只安装 BeautifulSoup4 (opens new window)。
我们强烈建议您阅读 HTML表解析之坑 (opens new window)。
它解释了有关上述三个库的安装和使用的问题。
只有 lxml (opens new window),请参阅HTML表解析 (opens new window),以了解为什么您可能不应该采用这种方法
3.数据结构与使用
维数 | 名称 | 描述 |
1 | Series | 带标签的一维同构数组 |
2 | DataFrame | 带标签的,大小可变的,二维异构表格 |
首先,导入 NumPy 和 Pandas:
import numpy as np
import pandas as pd
数据对齐是内在的”,这一原则是根本。除非显式指定,Pandas 不会断开标签和数据之间的连接。
先简单介绍数据结构,然后再分门别类介绍每种功能与方法。
- Series
Series是带标签的一维数组,可存储整数、浮点数、字符串、Python 对象等类型的数据。轴标签统称为索引。调用 pd.Series 函数即可创建 Series
s = pd.Series(data, index=index)
上述代码中,data 支持以下数据类型:
Python 字典
多维数组
标量值(如,5)
index 是轴标签列表。不同数据可分为以下几种情况:
3.1.1多维数组
data 是多维数组时,index 长度必须与 data 长度一致。没有指定 index 参数时,创建数值型索引,即 [0, ..., len(data) - 1]。
import numpy as np
import pandas as pd
p1 = pd.Series(['Lakers', 'Los angeles', 1000000000, 70], index=['球队名称', '地址', '年利润', '历史'])
print(p1)
注意:Pandas 的索引值可以重复。不支持重复索引值的操作会触发异常。其原因主要与性能有关,有很多计算实例,比如 GroupBy 操作就不用索引。
3.1.2字典
Series 可以用字典实例化
将字典的key作为索引,value值作为索引对应的值
p2={'lebron':6,'curry':30,'durant':7}
print(pd.Series(p2,['curry','lebron','durant']))
注意:data 为字典,且未设置 index 参数时,如果 Python 版本 >= 3.6 且 Pandas 版本 >= 0.23,Series 按字典的插入顺序排序索引。
Python < 3.6 或 Pandas < 0.23,且未设置 index 参数时,Series 按字母顺序排序字典的键(key)列表。
上例中,如果 Python < 3.6 或 Pandas < 0.23,Series 按字母排序字典的键。输出结果不是 ['b', 'a', 'c'],而是 ['a', 'b', 'c']。
如果设置了 index 参数,则按索引标签提取 data 里对应的值。
p2={'lebron':6,'curry':30,'durant':7}
print(pd.Series(p2,['curry','lebron','durant','zw']))
#注意:Pandas 用 NaN(Not a Number)表示缺失数据
3.1.3标量值
data 是标量值时,必须提供索引。Series 按索引长度重复该标量值。广播
p3=(5.,['a','b','c','d','e'])
print(pd.Series(5.,index=['a','b','c','d','e']))
3.1.4 Series 类似多维数组
Series 操作与 ndarray 类似,支持大多数 NumPy 函数,还支持索引切片。
p3=pd.Series([1,2,3,4,5],['a','b','c','d','e'])
print(p3[0:3])
print(p3[[2,3,1]])
Series 只是类似于多维数组,提取真正的多维数组,要用 Series.to_numpy()
import numpy as np
import pandas as pd
p1 = pd.Series(['Lakers', 'Los angeles', 1000000000, 70], index=['球队名称', '地址', '年利润', '历史'])
print(p1.to_numpy())
Series 是扩展数组,Series.to_numpy()返回的是 NumPy 多维数组
3.1.5 Series类似字典
Series 类似固定大小的字典,可以用索引标签提取值或设置值,引用 Series 里没有的标签会触发异常:
get 方法可以提取 Series 里没有的标签,返回 None 或指定默认值:
p1 = pd.Series(['Lakers', 'Los angeles', 1000000000, 70], index=['球队名称', '地址', '年利润', '历史'])
print(p1['地址'])
p1.get('你好')
2.DataFrame
DataFrame 是由多种类型的列构成的二维标签数据结构,类似于 Excel 、SQL 表,或 Series 对象构成的字典。DataFrame 是最常用的 Pandas 对象,与 Series 一样,DataFrame 支持多种类型的输入数据:
一维 ndarray、列表、字典、Series 字典
二维 numpy.ndarray
结构多维数组或记录多维数组
Series
DataFrame
除了数据,还可以有选择地传递 index(行标签)和 columns(列标签)参数。传递了索引或列,就可以确保生成的 DataFrame 里包含索引或列。Series 字典加上指定索引时,会丢弃与传递的索引不匹配的所有数据。
没有传递轴标签时,按常规依据输入数据进行构建。
注意:
Python > = 3.6,且 Pandas > = 0.23,数据是字典,且未指定 columns 参数时,DataFrame 的列按字典的插入顺序排序。
Python < 3.6 或 Pandas < 0.23,且未指定 columns 参数时,DataFrame 的列按字典键的字母排序。
3.2.1用 Series 字典或字典生成 DataFrame
import numpy as np
import pandas as pd
p1 = {'one':pd.Series(['Lakers', 'Los angeles', 1000000000, 70], index=['球队名称', '地址', '年利润', '历史']),'two':pd.Series(['warriors','golden state','1000000000',60],index=['球队名称', '地址', '年利润', '历史'])}
p2=pd.DataFrame(p1)
print(p2)
d = {'one': pd.Series([1., 2., 3., 9.], index=['a', 'b', 'c', 'e']),
'two': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
df2 = pd.DataFrame(d)
df3 = pd.DataFrame(d, index=['a', 'c', 'd'], columns=['one', 'two', 'three'])
df1 = pd.DataFrame(d, index=['a', 'b', 'c', 'd', 'e'],
columns=['one', 'three']) # 这样写相当于取了'one'这一列和新建了'第二列'这一列,然后取索引为'a', 'd', 'e'
print(df2)
print(df3)
print(df1)
index 和 columns 属性分别用于访问行、列标签:
print(df3.index)
print(df3.columns)
3.2.2用多维数组字典、列表字典生成 DataFrame
多维数组的长度必须相同。如果传递了索引参数,index 的长度必须与数组一致。如果没有传递索引参数,生成的结果是 range(n),n 为数组长度。
import numpy as np
import pandas as pd
dict1={'one':['a','b','c'],'two':['1','2','3']}
pd1=pd.DataFrame(dict1,index=['1001','1002','1003'],columns=['one','three'])
print(pd1)
3.2.3用列表字典生成 DataFrame
import numpy as np
import pandas as pd
data=[{'one':1,'two':2,'three':3},{'two':2,'three':3}]
pd1=pd.DataFrame(data)
print(pd1)
import numpy as np
import pandas as pd
data=[{'one':1,'two':2,'three':3},{'two':2,'three':3}]
pd1=pd.DataFrame(data,index=['z','w'],columns=['one','three'])
print(pd1)
3.2.4提取、添加、删除列
DataFrame 就像带索引的 Series 字典,提取、设置、删除列的操作与字典类似:
d = {'one': pd.Series([1., 2., 3., 9.], index=['a', 'b', 'c', 'e']),
'two': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
df1 = pd.DataFrame(d)
print(df1)
print('---------------------------')
print(df1['two'])
print('-------------------------------')
df1['three'] = df1['one'] + df1['two']
print(df1)
print("----------------------")
df1['four'] = df1['three'] > 3
print(df1)
删除(del、pop)列的方式也与字典类似:
del df1['four']
print(df1)
df1.pop('three')
print(df1)
标量值以广播的方式填充列:
df1['lebron']='goat'
print(df1)
插入与 DataFrame 索引不同的 Series 时,以 DataFrame 的索引为准
df1['jordan']=df1['lebron'][1:3]
print(df1) #数不足填NaN
可以插入原生多维数组,但长度必须与 DataFrame 索引长度一致。
默认在 DataFrame 尾部插入列。insert 函数可以指定插入列的位置:
df1.insert(2,'curry',df1['jordan'])
print(df1)
3.2.5 索引 / 选择
索引基础用法如下:
操作 | 句法 | 结果 |
选择列 | df[col] | Series |
用标签选择行 | df.loc[label] | Series |
用整数位置选择行 | df.iloc[loc] | Series |
行切片 | df[5:10] | DataFrame |
用布尔向量选择行 | df[bool_vec] | DataFrame |
print(df1.iloc[1])
print(df1[1:3])
3.2.6 合并操作
结合(Concat)
Pandas 提供了多种将 Series、DataFrame 对象组合在一起的功能,用索引与关联代数功能的多种设置逻辑可执行连接(join)与合并(merge)操作。
concat()用于连接 Pandas 对象:
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.randn(10, 4))
print(df)
pieces = [df[:3], df[3:7], df[7:]] #分割成几块
print(pieces)
print(pd.concat(pieces)) #合并分割的块
连接(join)
import numpy as np
import pandas as pd
left = pd.DataFrame({'key': ['lebron', 'curry'], '1va1': [1, 2]})
right = pd.DataFrame({'key': ['lebron', 'durant'], '1va1': [4, 5]})
print(left)
print(right)
print(pd.merge(left,right,on='key'))
追加(Append)
import numpy as np
import pandas as pd
df1 = pd.DataFrame(np.random.randn(8, 4), columns=['a', 'b', 'c', 'c'])
s=df1.iloc[3]
print(df1.append(s, ignore_index=True))
分组(Grouping)
group by” 指的是涵盖下列一项或多项步骤的处理流程:
分割:按条件把数据分割成多组;
应用:为每组单独应用函数;
组合:将处理结果组合成一个数据结构。
import numpy as np
import pandas as pd
df6 = pd.DataFrame({'lebron': ['Cavaliers', 'Heat', 'Cavaliers', 'Lakers', 'Lakers', 'Lakers', 'Lakers', 'Lakers'],
'curry': ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
'durant': np.random.randn(8),
'jordan': np.random.randn(8)})
print(df6)
先分组,再用 sum()函数计算每组的汇总数据:
print(df6.groupby('lebron').sum())
多列分组后,生成多层索引,也可以应用 sum和mean 函数:
print('-----------------------------------------')
print(df6.groupby(['lebron', 'curry']).sum()) #求索引的和
print('-----------------------------------------')
print(df6.groupby(['lebron', 'curry']).mean()) #求索引的平均值
过滤索引查询(filter)
需要注意的是,此方法不会对数据帧的数据内容进行过滤,仅应用于按标签筛选。
其中的参数 items, like, 和 regex parameters 被强制执行为相互排斥,即只能有一个存在。轴默认为使用 [] 索引时使用的信息轴(info axis,按行)。
import numpy as np
import pandas as pd
df = pd.DataFrame(np.array(([1, 2, 3], [4, 5, 6])),
index=['lebron', 'curry'],
columns=['one', 'two', 'three'])
print(df)
# 按名称选择列
print(df.filter(items=['one', 'three']))# items参数表示根据列名过滤
# 按正则表达式选择列
print(df.filter(regex='n$',axis=0))# axis的值是1,正则表达式匹配的是列名,如果是0,匹配的是索引的名
# 选择包含“le”的行
print(df.filter(like='le', axis=0))# like参数表示包含的意思
排序(sort_values)
import numpy as np
import pandas as pd
dic = {'name': ['kiti', 'beta', 'peter', 'tom'],
'age': [20, 18, 35, 21],
'gender': ['f', 'f', 'm', 'm']}
df = pd.DataFrame(dic)
print(df)
print(df.sort_values(by=['age'])) #按照年龄升序排序
print(df.sort_values(by=['age'],ascending=False)) #降序排序
4. Pandas操作CSV类型文件
4.1 read_csv()读文件
xxx.csv 列之间的默认分隔符是英文逗号
xxx.xlsx 记事本打开是看不懂的
4.1 read_csv()读文件
传参路径:
import numpy as np
import pandas as pd
from io import StringIO
# 读取csv表格的文件
df1 = pd.read_csv('demo1.csv',encoding='gbk')#相对路径,gbk编码
df2=pd.read_csv('E:\\Projects\\pythonProject\\bigdata22\\day05\\demo1.csv',encoding='gbk')
print(df1)
print(df2)
data = ('col1,col2,col3\n'
'a,b,1\n'
'a,b,2\n'
'c,d,3')
df2 = pd.read_csv(StringIO(data))
print(df2)
一般情况下,会将读取到的数据返回一个DataFrame,当然按照参数的要求会返回指定的类型
分隔符
# sep参数是字符型的,代表每行数据内容的分隔符号,默认是逗号,另外常见的还有制表符(\t)、空格等,根据数据的实际情况传值。
# 数据分隔符默认是逗号,可以指定为其他符号
pd.read_csv(data, sep='\t') # 制表符分隔tab
pd.read_table(data) # read_table 默认是制表符分隔tab
pd.read_csv(data, sep='|') # 制表符分隔tab
pd.read_csv(data,sep="(?<!a)\|(?!1)", engine='python') # 使用正则表达式
index_col
这个参数是用来决定读进来的数据哪一列做索引的。
这个参数的缺省值是False,就是什么都不做的意思。
咱们来指定第一列看看,第一列在Python里被标做1:(从0开始)
df2=pd.read_csv('E:\\Projects\\pythonProject\\bigdata22\\day05\\demo1.csv',encoding='gbk',sep='|',index_col=1)
print(df2)
usecols
这个参数可以指定你从文件中读取哪几列
data = pd.read_csv("E:\\Projects\\pythonProject\\bigdata22\\day05\\demo1.csv", encoding="gbk", sep='|',usecols=[2,3])
print(data)
nrows
指定读取记录多少行
data = pd.read_csv("E:\\Projects\\pythonProject\\bigdata22\\day05\\demo1.csv", encoding="gbk", sep='|',usecols=[2,3],nrows=10)
print(data)
4.2 to_csv()写文件
将Dataframe保存位一个csv文件
dic = {'name': ['kiti', 'beta', 'peter', 'tom', 'xiaohu', 'jiajia', 'xiaoge'],
'age': [20, 18, 35, 21, 20, 20, 18],
'gender': ['f', 'f', 'm', 'm', 'm', 'f', 'm'],
'score': [100, 65, 34, 78, 92, 105, 89]}
df = pd.DataFrame(dic)
print(df.to_csv('A.csv', sep='\t'))
参数说明
index
缺省index=True,就是上面看到的a到d是索引号。如果你不加这个参数,写文件时会连带索引号一起写入。
dic = {'name': ['kiti', 'beta', 'peter', 'tom', 'xiaohu', 'jiajia', 'xiaoge'],
'age': [20, 18, 35, 21, 20, 20, 18],
'gender': ['f', 'f', 'm', 'm', 'm', 'f', 'm'],
'score': [100, 65, 34, 78, 92, 105, 89]}
df = pd.DataFrame(dic)
print(df.to_csv('A.csv', sep='\t',index=True))
columns
按指定的列写入文件,我在下面只写入文件1列,有意去掉了读操作
df.to_csv("a.csv", index=False,columns=['two'])
encoding
encoding主要是为了兼容Python2的一些中文操作。
大家知道由于计算机的发展历史,中文以及中文语系(包括日文、韩文等)并没有西方字母排列的那么规范。导致我们在不同的系统环境、不同的编程语言下都有可能会生成编码不一样的中文文件来。
这样的文件打印出来没差别,但作为电子文件保留下来,若干年后的人在打开时,会由于不知道中文用的是哪套编码而出现乱码。乱码不仅仅是简体和繁体中文的问题。
建议在写文件时最好加入encoding参数,并制定编码为“utf-8”,这也是目前全球应用最广泛的编码规则。
sep
这是分隔符参数,缺省列与列之间用逗号分隔。不过有很多单位由于历史数据采用的分隔符多种多样,为了适应这种情况,你可以用这个参数指定分隔符。
df.to_csv("a.csv", sep='\t')