pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。简单地说,你可以把 Pandas 看作是 Python 版的 Excel。
pandas官网 http://pandas.pydata.org/ 可以供查阅API和更多教程
pandas具有以下数据结构:
Series:一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近。Series如今能保存不同种数据类型,字符串、boolean值、数字等都能保存在Series中。
Time- Series:以时间为索引的Series。
DataFrame:二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。
Panel(最近的版本已经弃用这个数据结构,所以不做介绍) :三维的数组,可以理解为DataFrame的容器。
我们本文就来一起总结学习pandas常用数据结构和操作
Series 是一种一维数组,和 NumPy 里的数组很相似。事实上,Series 基本上就是基于 NumPy 的数组对象来的。和 NumPy 的数组不同,Pandas 的 Series 能存放各种不同类型的对象,Series 能为数据自定义标签,也就是索引(index),然后通过索引来访问数组中的数据。
导入模块:
import numpy as np
import pandas as pd
创建一个 Series 的基本语法如下:
s = pd.Series(data,index)
参数 | 意义 |
---|---|
data | 字典、ndarray或标量值 (标量就是只有大小,没有方向的量) |
index | 对 data 的索引值,类似字典的 key, index 参数是可省略的,你可以选择不输入这个参数。如果不带 index 参数,Pandas 会自动用默认 index 进行索引,比如ndarray数组,索引值是 [0, …, len(data) - 1] |
创建分为以下4种情况:
从python list创建Series
从numpy ndarray创建Series
从python dict创建Series
当data为dict,且没有传递索引时,Series如果使用Python版本>=3.6和Pandas 版本>=0.23,则索引将按dict的插入顺序排序。如下图:
在上图中,如果您的Python版本低于3.6,或者Pandas版本低于0.23,则Series将由词条键的词法顺序(即[‘a’, ‘b’, ‘c’]而不是[‘b’, ‘a’, ‘c’]).
注意:NaN(不是数字)是pandas使用的标准缺失数据标记。
从标量创建Series
如果数据是标量值,则必须提供索引。将重复该值以匹配索引的长度。
从 Series 里获取数据:
访问 Series 里的数据的方式,和 Python 字典基本一样:
对 Series 进行算术运算操作
基于 index 进行的。我们可以用加减乘除(+ - * /)这样的运算符对两个 Series 进行运算,Pandas 将会根据索引 index,对响应的数据进行计算,结果将会以浮点数的形式存储,以避免丢失精度。如果 Pandas 在两个 Series 里找不到相同的 index,对应的位置就返回一个空值 NaN。如下图:
DataFrame:二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。
DataFrame是一个二维标记的数据结构,可以具有不同类型的列。您可以将其视为电子表格或SQL表,或序列对象的dict。它通常是最常用的pandas对象。与系列一样,DataFrame接受多种不同类型的输入:
1、一维ndarray的dict,lists, dicts, or Series
2、二维numpy.ndarray
3、结构化或记录 ndarray
4、A Series
5、Another DataFrame
创建方式:
1、用许多 Series 来构建一个DataFrame:
2、用一个字典来创建 DataFrame:
获取,设置和删除列的工作方式与类似的dict操作相同:
只获取一列,所以返回的就是一个 Series,包括index。可以用 type() 函数确认返回值的类型:
如果获取多个列,那返回的就是一个 DataFrame 类型:
向 DataFrame 里增加数据列——创建一个列的时候,你需要先定义好这个列的数据和索引。
比如下图这个 DataFrame:
增加数据列有以下两种办法:
——可以从头开始定义一个 pd.Series,再把它放到表中:
——也可以利用现有的列来产生需要的新列。
从 DataFrame 里删除行/列:
想要删除某一行或一列,可以用 drop() 函数。在使用这个函数的时候,你需要先指定具体的删除方向,axis=0 对应的是行 row,而 axis=1 对应的是列 column 。
删除 ‘Birth_year’ 列/“d”行:
注意,除非用户明确指定,为了防止用户误操作丢失数据,在调用 drop() 的时候,Pandas 并不会真的永久性地删除这行/列。可以通过调用 df 来确认数据的完整性(df就可以显示未永久删除的)。如果你确定要永久性删除某一行/列,你需要加上 inplace=True 参数,比如:
获取 DataFrame 中的一行或多行数据:
要获取某一行,loc[] 来按索引(或标签名)引用,或者用iloc[],按这行在表中的位置(行数(以0开始))来引用。如下:
一行:
多行:
同时你可以用 loc[] 来指定具体的行列范围,并生成一个子数据表。比如,提取 ‘b’ 行中 'Name’ 列的内容(提取“b”,“c”行中的name,Year列的内容),可以如下操作:
条件筛选
用中括号 [] 的方式,除了直接指定选中某些列外,还能接收一个条件语句,然后筛选出符合条件的行/列。
randn(d1,d2,…,dn)函数是生成正态分布的随机数,n是维数,下图即二维,5行4列
创建DataFrame(data,index,属性)
上图的结果即下图的前两个表达式
也可以使用逻辑运算符 &(与)和 |(或)来链接多个条件语句,以便一次应用多个筛选条件到当前的 DataFrame 上。比如,我们可以用下面的方法筛选出同时满足 ‘W’>0 和’X’>1 的行,结果如下图:
重置并设置DataFrame 的索引
——若你觉得当前 DataFrame 的索引有问题,可以先用 .reset_index() 简单地把整个表的索引都重置掉。
这个方法将把目标 DataFrame 的索引保存在一个叫 index 的列中,而把表格的索引变成默认的从零开始的数字,也就是 [0, …, len(data) - 1] 。比如下面这样:
和删除操作差不多,.reset_index() 并不会永久改变你表格的索引,除非你调用的时候明确传入了 inplace 参数,比如:.reset_index(inplace=True)
——然后用 .set_index() 方法,将 DataFrame 里的某一列作为索引来用。比如,我们在这个表里新建一个名为 “ID” 的列:
注意,不像 .reset_index() 会保留一个备份,然后才用默认的索引值代替原索引,.set_index() 将会完全覆盖原来的索引值。
多级索引(MultiIndex)以及命名索引的不同等级
多级索引其实就是一个由元组(Tuple)组成的列表,每一个元组都是独一无二的。
——你可以从一个包含许多数组的列表中创建多级索引(调用 MultiIndex.from_arrays ),
——也可以用一个包含许多元组的列表(调用 MultiIndex.from_tuples )
——或者是用一对可迭代对象的集合(比如两个列表,互相两两配对)来构建(调用MultiIndex.from_product )。
我们从元组中创建多级索引:
在 Python 3.x 中为了减少内存,zip() 返回的是一个对象。如需展示列表,需手动 list() 转换。zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
最后这个 list(zip()) 的嵌套函数,把上面两个列表合并成了一个每个元素都是元组的列表。这时 my_index 的内容是这样的:[(‘O Level’, 21), (‘O Level’, 22), (‘O Level’, 23), (‘A Level’, 21), (‘A Level’, 22), (‘A Level’, 23)]
接下来,我们调用 .MultiIndex.from_tuples(my_index) 生成一个多级索引对象,:
最后,将这个多级索引对象转成一个 DataFrame:
要获取多级索引中的数据,还是用到 .loc[] 。比如,先获取 ‘O Level’ 下的数据:
然后再用一次 .loc[],获取下一层 21 里的数据:
如上所示,df 这个 DataFrame 的头两个索引列没有名字,鉴于需要,我们可以用 .index.names 给它们加上名字:
我们可以用 .xs() 方法轻松获取到多级索引中某些特定级别的数据。比如,我们需要找到所有 Levels 中,Num = 22 的行:
缺失值的处理:
在许多情况下,如果你用 Pandas 来读取大量数据,往往会发现原始数据中会存在不完整的地方。在 DataFrame 中缺少数据的位置, Pandas 会自动填入一个空值,比如以下这个图中的NaN 。
缺失值的删除:.dropna() 来丢弃这些自动填充的值,当你使用 .dropna() 方法时,就是告诉 Pandas 删除掉存在一个或多个空值的行(或者列)。删除行用的是 .dropna(axis=0) ,删除列用的是 .dropna(axis=1) ,默认axis = 0。
缺失值的填充:.fillna() 来自动给这些空值填充数据,使用 .fillna() 方法,Pandas 将对这个 DataFrame 里所有的空值位置填上你指定的默认值。比如,将表中所有 NaN 替换成 20 :
同样地,.dropna()方法 和 .fillna() 方法并不会永久性改变你的数据,除非你传入了inplace=True 参数。‘
’
分组统计
Pandas 的分组统计功能可以按某一列的内容对数据行进行分组,并对其应用统计函数,比如求和,平均数,中位数,标准差等
首先初始化一个Dataframe,如下图,
用 .groupby() 方法,我们可以对下面这数据表按 ‘Company’ 列进行分组,并用 .mean() 求每组的平均值:
用 .count() 方法,能对 DataFrame 中的某个元素出现的次数进行计数,如下
数据描述
.describe() 方法将对 DataFrame 里的数据进行分析,并一次性生成多个描述性的统计指标,方便用户对数据有一个直观上的认识。生成的指标,从左到右分别是:计数、平均数、标准差、最小值、25% 50% 75% 位置的值、最大值:
然后用 .transpose() 方法获得一个竖排的格式:
使用[],可以只看指定的指标:
堆叠(Concat)
堆叠基本上就是简单地把多个 DataFrame 堆在一起,拼成一个更大的 DataFrame。当你进行堆叠的时候,堆叠时要注意数据表的索引和列的延伸方向,堆叠的方向要和它一致。
默认按行的方向堆叠,把每个表的索引按顺序叠加。
按列的方向堆叠,那你需要传入 axis=1 参数:
由上图可知出现了一大堆空值。因为我们用来堆叠的3个 DataFrame 里,有许多索引是没有对应数据的。因此使用 pd.concat() 的时候,一定要注意堆叠方向的坐标轴(行或列)含有所需的所有数据。
归并(Merge)
使用 pd.merge() 函数,能将多个 DataFrame 归并在一起,它的合并方式类似合并 SQL 数据表的方式。
归并操作的基本语法:
pd.merge(left, right, how='inner', on='Key')
其中 left 参数代表放在左侧的 DataFrame,而 right 参数代表放在右边的 DataFrame;
how='inner' 指的是当左右两个 DataFrame 中存在不重合的 Key 时,取结果的方式:默认:inner 内连接,取交集”,outer 外连接,取并集,并用nan填充”,left 左连接, 左侧取全部,右侧取部分”,right 右连接,左侧取部分,右侧取全部”
最后,on='Key' 代表需要合并的键值所在的列,最后整个表格会以该列为准进行归并。
对于两个都含有 key 列的 DataFrame,我们可以这样归并:
也可以传入多个 on 参数,这样就能按多个键值进行归并:
连接(Join)
若要把两个表连在一起,然而它们之间没有太多共同的列,可以选择使用.join() 方法。和 .merge() 不同,连接采用索引作为公共的键,而不是某一列。
同样inner 表示内连接,取交集”,outer 外连接,取并集,并用nan填充”,left 左连接, 左侧取全部,右侧取部分”,right 右连接,左侧取部分,右侧取全部”
查找不重复的值
不重复值在Dataframe中被视为独一无二的,找到不重复的值,在数据分析中有助于避免样本偏差。在 Pandas 里,主要用到 3 种相关的API方法:
—— .unique() 方法。比如在下面这个 DataFrame 里,查找 col2 列中所有不重复的值:
.nunique() 方法,获取所有不重复值的个数:
.value_counts() 同时获得所有值和对应值的计数:
apply() 方法
.apply() 方法,可以对 DataFrame 中的数据应用自定义函数,进行数据处理。
比如,我们先定义一个 square() 函数,然后对表中的 col1 列应用这个函数:
函数会被应用到这一列里的每一个元素上。这样,我们就也可以调用任意的内置函数。比如对 col3 列取长度 len :
用 lambda 表达式(匿名函数)来代替函数定义,简化代码。比如,我们可以用这样的 lambda 表达式代替上面 In[47] 里的函数定义:
获取 DataFrame 的属性
DataFrame 的属性包括列和索引的名字。假如你不确定表中的某个列名是否含有空格之类的字符,你可以通过 .columns 来获取属性值,以查看具体的列名。
排序(sort)
.sort_values() 将整个表按某一列的值进行排序:
注意:表格变成按 col2 列的值从小到大排序。要注意的是,表格的索引 index 还是对应着排序前的行,并没有因为排序而丢失原来的索引数据。
查找空值
数据集很庞大时,使用用 Pandas 的 .isnull() 方法,方便快捷地发现表中的空值:
该方法返回的是一个新的 DataFrame,里面用布尔值(True/False)表示原 DataFrame 中对应位置的数据是否是空值。
数据透视表
使用 Excel 的时候,有数据透视表的功能,同样,pandas也有。数据透视表是一种汇总统计表,它展现了原表格中数据的汇总统计结果。Pandas 的数据透视表能自动帮你对数据进行分组、切片、筛选、排序、计数、求和或取平均值,并将结果直观地显示出来。
举个李子,这里有个关于动物的统计表:
Pandas 数据透视表的语法是:
df .pivot_table(data, values='', index=[''], columns=[''])
#values代表我们需要汇总统计的数据所在的列
#index 表示按该列进行分组索引
#columns 则表示最后结果将按该列的数据进行分列
还可以在 Pandas 的官方文档中找到更多数据透视表的详细用法和例子。
下面,我们就来给这个动物统计表创建一个数据透视表:
——可以直接用上述语法(data就是源Dataframe):
——也可以直接将data作为对象调用该方法:
注意:若原数据里没有对应的条件下的数据,数据透视表的该位置就是是 NaN 空值。
导入导出数据(文件操作)
pd.read_ 这样的方法,你可以用 Pandas 读取各种不同格式的数据文件,包括 Excel 表格、CSV 文件、SQL 数据库,甚至 HTML 文件等。
——读取 CSV 文件:
pd.read_csv() 就能将 CSV 文件里的数据转换成 DataFrame 对象:
——写入 CSV 文件:
DataFrame 对象存入 .csv 文件的方法是 .to_csv(),例如,我们先创建一个 DataFrame 对象,然后我们将这个 DataFrame 对象存成 ‘New_dataframe’ 文件,Pandas 会自动在磁盘上创建这个文件:
上图中传入 index=False 参数是因为不希望 Pandas 把索引列的 0~5 也存到文件中。
——读取 Excel 表格文件:
Excel 文件是一个不错的数据来源。使用 pd.read_excel() 方法,我们能将 Excel 表格中的数据导入 Pandas 中。但是请注意,Pandas 只能导入表格文件中的数据,其他对象,例如宏、图形和公式等都不会被导入。如果文件中存在有此类对象,可能会导致 pd.read_excel() 方法执行失败:
注意:每个 Excel 表格文件有可能含有一个或多个工作表,传入 sheet_name=‘Sheet1’ 这样的参数,就表示只读取 ‘excel_output.xlsx’ 中的 Sheet1 工作表中的内容。
——写入 Excel 表格文件:
与写入 CSV 文件类似,我们可以将一个 DataFrame 对象存成 .xlsx 文件,语法是 .to_excel() ,我们数据存到 ‘excel_output.xlsx’ 文件中:
——读取 HTML 文件中的数据:
为了读取 HTML 文件,首先需要安装 htmllib5,lxml 以及 BeautifulSoup4 库
我们来举个栗子,我们使用Pandas 读取这个页面的数据: 由于一个页面上含有多个不同的表格,我们需要通过下标 [0, …, len(tables) - 1] 访问表格列表中的不同元素。
pandas.date_range(start=None, end=None, periods=None, freq=‘D’, tz=None, normalize=False, name=None,closed=None, **kwargs)
功能:返回一个固定的频率DatetimeIndex,以日(日历D)作为默认频率
参数:start : string or datetime-like, default None 生成日期的左边界
end : string or datetime-like, default None 生成日期的右边界
periods : integer, default None 要生成的时间段数
freq : string or DateOffset, default ‘D’ (日历日期) 频率字符串可以有多个,例如“S”表示秒频率
返回:rng : DatetimeIndex
注意:在三个参数中:start,and和periods,必须指定两个参数。
举个例子,接下来的四个示例生成相同的DatetimeIndex,但会改变start,end和periods的组合。
——使用默认的每日频率指定开始和结束:
——指定开始和期间,期间数(天):
——指定开始,结束和期间 ; 频率自动生成(线性间隔):
——将频率(频率)更改为’M’(月末频率):
———可以通过时间序列来绘图:
ts=pd.Series(np.random.randn(1000),index=pd.date_range("20170301",periods=1000))
ts=ts.cumsum() #cumsum 返回DataFrame或Series轴上的累积和。
from pylab import * #需要导入绘图模块
ts.plot() #绘图
show() #展示
如下图:
恭喜你到这里,pandas的常用知识你就已经认识差不多了,可以在此基础上好好调教 Pandas。知识学了还不够,接下来,你需要的也是更重要的就是练习,练习,练习(重要的事情说遍!!!)。
下篇文章我们来总结学习scikit-learn(数据挖掘与机器学习)