Python 第三方库之 Pandas

一、Pandas简介

Python Data Analysis Library 或 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使Python成为强大而高效的数据分析环境的重要因素之一。

Pandas是python的一个数据分析包,最初由AQR Capital Management于2008年4月开发,并于2009年底开源出来,目前由专注于Python数据包开发的PyData开发team继续开发和维护,属于PyData项目的一部分。Pandas最初被作为金融数据分析工具而开发出来,因此,pandas为时间序列分析提供了很好的支持。 Pandas的名称来自于面板数据(panel data)和python数据分析(data analysis)。panel data是经济学中关于多维数据集的一个术语,在Pandas中也提供了panel的数据类型。

二、数据结构

  • Series:一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近,其区别是:List中的元素可以是不同的数据类型,而Array和Series中则只允许存储相同的数据类型,这样可以更有效的使用内存,提高运算效率。
  • Time- Series:以时间为索引的Series。
  • DataFrame:二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。以下的内容主要以DataFrame为主。
  • Panel :三维的数组,可以理解为DataFrame的容器。

Pandas 有两种自己独有的基本数据结构。读者应该注意的是,它固然有着两种数据结构,因为它依然是 Python 的一个库,所以,Python 中有的数据类型在这里依然适用,也同样还可以使用类自己定义数据类型。只不过,Pandas 里面又定义了两种数据类型:Series 和 DataFrame,它们让数据操作更简单了。

Series

Series 在python的中type()为<class 'pandas.core.series.Series'>。由于Series是一维结构的数据,我们可以直接通过数组来创建这种数据,像这样:

import pandas as pd
import numpy as np

series1 = pd.Series([1, 2, 3, 4])
print("series1:\n{}\n".format(series1))

# 这段代码输出如下:
series1:
0 1
1 2
2 3
3 4
dtype: int64

这段输出说明如下:

  • 输出的最后一行是Series中数据的类型,这里的数据都是int64类型的。
  • 数据在第二列输出,第一列是数据的索引,在pandas中称之为Index。

我们可以分别打印出Series中的数据和索引:

print("series1.values: {}\n".format(series1.values))
print("series1.index: {}\n".format(series1.index))
这两行代码输出如下:
series1.values: [1 2 3 4]
series1.index: RangeIndex(start=0, stop=4, step=1)

如果不指定(像上面这样),索引是[1, N-1]的形式。不过我们也可以在创建Series的时候指定索引。索引未必一定需要是整数,可以是任何类型的数据,例如字符串。例如我们以七个字母来映射七个音符。索引的目的是可以通过它来获取对应的数据,例如下面这样:

series2 = pd.Series([1, 2, 3, 4, 5],index=["C", "D", "E", "F", "G"])
print("series2:\n{}\n".format(series2))
print("E is {}\n".format(series2["E"]))

# 这段代码输出如下:
series2:
C 1
D 2
E 3
F 4
G 5
dtype: int64
E is 3

DataFrame

DateFrame 在python的中type()为<class 'pandas.core.frame.DataFrame'>

DateFrame的创建主要有三种方式:

1)通过二维数组创建数据框

arr2 = np.array(np.arange(16)).reshape(4,4)
df1 = pd.DataFrame(arr2)
  0   1   2   3
0 0   1   2   3
1 4   5   6   7
2 8   9   10  11
3 12  13  14  15

从这个输出我们可以看到,默认的索引和列名都是[0, N-1]的形式。我们可以在创建DataFrame的时候指定列名和索引,像这样:

扫描二维码关注公众号,回复: 9671692 查看本文章
df2 = pd.DataFrame(np.arange(16).reshape(4,4),columns=["column1", "column2", "column3", "column4"],index=["a", "b", "c", "d"])
print("df2:\n{}\n".format(df2))
# 结果如下
  column1        column2          column3         column4
a 0              1                2               3
b 4              5                6               7
c 8              9                10              11
d 12             13               14              15

我们也可以直接指定列数据来创建DataFrame:

df3 = pd.DataFrame({"note" : ["C", "D", "E", "F", "G", "A", "B"],"weekday": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]})
print("df3:\n{}\n".format(df3))
# 这段代码输出如下:
note weekday
0 C Mon
1 D Tue
2 E Wed
3 F Thu
4 G Fri
5 A Sat
6 B Sun

请注意:
DataFrame的不同列可以是不同的数据类型
如果以Series数组来创建DataFrame,每个Series将成为一行,而不是一列,例如:

noteSeries = pd.Series(["C", "D", "E", "F", "G", "A", "B"],index=[1, 2, 3, 4, 5, 6, 7])
weekdaySeries = pd.Series(["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],index=[1, 2, 3, 4, 5, 6, 7])
df4 = pd.DataFrame([noteSeries, weekdaySeries])
print("df4:\n{}\n".format(df4))
df4的输出如下:
  1 2 3 4 5 6 7
0 C D E F G A B
1 Mon Tue Wed Thu Fri Sat Sun

2)通过字典的方式创建数据框
以下以两种字典来创建数据框,一个是字典列表,一个是嵌套字典。

dic2 = {'a':[1,2,3,4],'b':[5,6,7,8],'c':[9,10,11,12],'d':[13,14,15,16]}
df2 = pd.DataFrame(dic2)
dic3 = {'one':{'a':1,'b':2,'c':3,'d':4},'two':{'a':5,'b':6,'c':7,'d':8},'three':{'a':9,'b':10,'c':11,'d':12}}
df3 = pd.DataFrame(dic3)
结果如下:
  a b c d
0 1 5 9 13
1 2 6 10 14
2 3 7 11 15
3 4 8 12 16
  one two three
a 1 5 9
b 2 6 10
c 3 7 11
d 4 8 12

字典的“键”("name","marks","price")就是 DataFrame 的 columns 的值(名称),字典中每个“键”的“值”是一个列表,它们就是那一竖列中的具体填充数据。
上面的dic2定义中没有确定索引,所以,按照惯例(Series 中已经形成的惯例)就是从 0 开始的整数。从上面的结果中很明显表示出来,这就是一个二维的数据结构(类似 excel 或者 mysql 中的查看效果)。
上面的数据显示中,columns 的顺序没有规定,就如同字典中键的顺序一样,但是在 DataFrame 中,columns 跟字典键相比,有一个明显不同,就是其顺序可以被规定,向下面这样做:
dic2_1 = DataFrame(dic2,columns=['b','a','c','d'])

3)通过数据框的方式创建数据框
df4 = df3[['one','three']] #即选取df3 的one和three列
s3 = df3['one'] #即选取df3的one列

三、Index对象

pandas的Index对象包含了描述轴的元数据信息。当创建Series或者DataFrame的时候,标签的数组或者序列会被转换成Index。可以通过下面的方式获取到DataFrame的列和行的Index对象:

series1 = pd.Series([1, 2, 3, 4])
print(series1.index)
代码输出如下:
RangeIndex(start=0, stop=4, step=1)

dic3 = {'one':{'a':1,'b':2,'c':3,'d':4},'two':{'a':5,'b':6,'c':7,'d':8},'three':{'a':9,'b':10,'c':11,'d':12}}
df3 = pd.DataFrame(dic3)
print(df3.columns)
print(df3.index)
这两行代码输出如下:
Index(['one', 'two', 'three'], dtype='object')
Index(['a', 'b', 'c', 'd'], dtype='object')

注意:
Index并非集合,因此其中可以包含重复的数据
Index对象的值是不可以改变,因此可以通过它安全的访问数据
DataFrame提供了下面两个操作符来访问其中的数据:
loc:通过行和列的索引来访问数据
iloc:通过行和列的下标来访问数据

print(df3[['one','two']])                 # df3[列索引]
print(df3.loc[['a','b'], ['one','two']])  # loc[行索引,列索引]
print(df3.iloc[[0, 1], 0])                # iloc[行下标,列下标]

第二行代码访问了行索引为0和1,列索引为“note”的元素。第三行代码访问了行下标为0和1(对于df3来说,行索引和行下标刚好是一样的,所以这里都是0和1,但它们却是不同的含义),列下标为0的元素。

   one  two
a    1    5
b    2    6
c    3    7
d    4    8

   one  two
a    1    5
b    2    6

a    1
b    2
Name: one, dtype: int64

2、自动化对齐
如果有两个序列,需要对这两个序列进行算术运算,这时索引的存在就体现的它的价值了—自动化对齐.

s5 = pd.Series(np.array([10,15,20,30,55,80]),index = ['a','b','c','d','e','f'])
s6 = pd.Series(np.array([12,11,13,15,14,16]),index = ['a','c','g','b','d','f'])
s5 + s6
s5/s6
结果如下
a    22.0
b    30.0
c    31.0
d    44.0
e     NaN
f    96.0
g     NaN
dtype: float64

a    0.833333
b    1.000000
c    1.818182
d    2.142857
e         NaN
f    5.000000
g         NaN
dtype: float64

由于s5中没有对应的g索引,s6中没有对应的e索引,所以数据的运算会产生两个缺失值NaN。注意,这里的算术结果就实现了两个序列索引的自动对齐,而非简单的将两个序列加总或相除。对于数据框的对齐,不仅仅是行索引的自动对齐,同时也会自动对齐列索引(变量名)
DataFrame中同样有索引,而且DataFrame是二维数组的推广,所以其不仅有行索引,而且还存在列索引,关于数据框中的索引相比于序列的应用要强大的多,这部分内容将放在数据查询中讲解。

四、文件操作

pandas库提供了一系列的read_函数来读取各种格式的文件,它们如下所示:
read_csv
read_table
read_fwf
read_clipboard
read_excel
read_hdf
read_html
read_json
read_msgpack
read_pickle
read_sas
read_sql
read_stata
read_feather
注:要读取Excel文件,还需要安装另外一个库:xlrd,通过pip可以这样完成安装:
sudo pip3 install xlrd

接下来我们看一个读取Excel的简单的例子:

import pandas as pd
import numpy as np
df1 = pd.read_excel("data/test.xlsx")
print("df1:\n{}\n".format(df1))
这个Excel的内容如下:
df1:
C Mon
0 D Tue
1 E Wed
2 F Thu
3 G Fri
...

我们再来看读取CSV文件的例子,CSV文件内容如下:
C,Mon
D,Tue
E,Wed
F,Thu
...
读取的方式也很简单:
df2 = pd.read_csv("data/test1.csv")
print("df2:\n{}\n".format(df2))

如果分隔符不是,我们可以通过指定分隔符的方式来读取这个文件,像这样:
df3 = pd.read_csv("data/test2.csv", sep="|")
print("df3:\n{}\n".format(df3))

实际上,read_csv支持非常多的参数用来调整读取的参数,如下表所示:

参数 说明
path 文件路径
sep或者delimiter 字段分隔符
header 列名的行数,默认是0(第一行)
index_col 列号或名称用作结果中的行索引
names 结果的列名称列表
skiprows 从起始位置跳过的行数
na_values 代替NA的值序列
comment 以行结尾分隔注释的字符
parse_dates 尝试将数据解析为datetime。默认为False
keep_date_col 如果将列连接到解析日期,保留连接的列。默认为False
converters 列的转换器
dayfirst 当解析可以造成歧义的日期时,以内部形式存储。默认为False
data_parser 用来解析日期的函数
nrows 从文件开始读取的行数
iterator 返回一个TextParser对象,用于读取部分内容
chunksize 指定读取块的大小
skip_footer 文件末尾需要忽略的行数
verbose 输出各种解析输出的信息
encoding 文件编码
squeeze 如果解析的数据只包含一列,则返回一个Series
thousands 千数量的分隔符

注:UTF-8以字节为编码单元,它的字节顺序在所有系统中都是一様的,没有字节序的问题,也因此它实际上并不需要BOM(“ByteOrder Mark”)。但是UTF-8 with BOM即utf-8-sig需要提供BOM。
简单的说,utf-8-sig是对字节编码有序的。
这种情况发生在pandas在read csv的时候,如果报错,key error,  File "pandas/index.pyx", line 137, in pandas.index.IndexEngine.get_loc (pandas/index.c:4154)
File "pandas/index.pyx", line 159, in pandas.index.IndexEngine.get_loc (pandas/index.c:4018)
File "pandas/hashtable.pyx", line 675, in pandas.hashtable.PyObjectHashTable.get_item (pandas/hashtable.c:12368)
File "pandas/hashtable.pyx", line 683, in pandas.hashtable.PyObjectHashTable.get_item (pandas/hashtable.c:12322)
这种情况要考虑使用utf-8-sig这种编码,即encdoinf='utf-8-sig'
遇到中文乱码的时候也可以试试改成这个编码

详细的read_csv函数说明请参见这里:pandas.read_csv

五、1 查询数据

引入数据集
student = pf.read_csv( '文件路径名' , header = None) (header 表示返回的数据是否有别名)

student.shape    # 查看数据的形状
data.columns     # 查看所有的列名
data.index       # 查看索引
data.dtypes      # 查看每一列数据的类型
data.ndim        # 查看数据的维度

# 查询前几行 或 后几行
student.head(5)
student.tail(5)

# 查询指定的行
student.ix[ ]     # 索引是字符串或数字,多行索引必须使用两个中括号student.ix[[ ]]
student.loc['a']    # 索引字符串
student.iloc[1]   # 索引数字

# 查询指定的列
student[列名] 或 student.列名    #注意当我们提取了一列,Pandas将返回一个series,而不是一个dataframe。
student [['Name' , 'Height' , 'Weight']]    #如果多个列的话,必须使用双重中括号
student.ix [:,['Name' , 'Height' , 'Weight']]    #通过ix查询指定的列

# 查询指定的行和列
student.ix [[0,2,4],['Name' , 'Height' , 'Weight']]

下面通过布尔索引来实现特定信息的查询
student[student['sex'] == F] --- 查询所有性别为女生的信息
student[(student['sex'] == F) & (stuent['age'] > 18)] -- 多条件查询,查询所有性别为女且年龄大于18岁的信息
student[(student['sex'] == F) & (stuent['age'] > 18)] [['name' , 'height']] --查询性别为女,年龄大于18的学生的姓名 和 体重

五、2 统计分析

pandas模块为我们提供了非常多的描述性统计分析的指标函数,如总和、均值、最小值、最大值等,我们来具体看看这些函数:
首先随机生成三组数据

np.random.seed(1234)
d1 = pd.Series(2*np.random.normal(size = 100)+3)
d2 = np.random.f(2,4,size = 100)
d3 = np.random.randint(1,100,size = 100)

d1.count() #非空元素计算
d1.min() #最小值
d1.max() #最大值
d1.idxmin() #最小值的位置,类似于R中的which.min函数
d1.idxmax() #最大值的位置,类似于R中的which.max函数
d1.quantile(0.1) #10%分位数
d1.sum() #求和
d1.mean() #均值
d1.median() #中位数
d1.mode() #众数
d1.var() #方差
d1.std() #标准差
d1.mad() #平均绝对偏差
d1.skew() #偏度
d1.kurt() #峰度
上述方法一维和二维均可用。

d1.describe() #一次性输出多个描述性统计指标,descirbe方法只能针对序列或数据框,一维数组是没有这个方法的

除以上的简单描述性统计之外,还提供了连续变量的相关系数(corr)和协方差矩阵(cov)的求解,这个跟R语言是一致的用法。
df.corr()

关于相关系数的计算可以调用pearson方法或kendell方法或spearman方法,默认使用pearson方法。
df.corr('spearman')

如果只想关注某一个变量与其余变量的相关系数的话,可以使用corrwith,如下方只关心x1与其余变量的相关系数:
df.corrwith(df['x1'])

数值型变量间的协方差矩阵
df.cov()

转置
df3.T

对轴进行排序
a.sort_index(axis=1,ascending=False);
其中axis=1表示对所有的columns进行排序,下面的数也跟着发生移动。后面的ascending=False表示按降序排列,参数缺失时默认升序。

对DataFrame中的值排序
a.sort(columns='x')
即对a中的x这一列,从小到大进行排序。注意仅仅是x这一列,而上面的按轴进行排序时会对所有的columns进行操作。

5.3类似于SQL的操作

1)增加新行或新列

OUT:

OUT:

虽然d2数据框只有3行1列,d3经过concat方法后,变成6行4列,d3的行数=d1的行数+d2的行数,d3的列数=d1的列数+d2的列数
concat函数可以自动对齐两个数据框的变量,新增的列没有赋值,就会出现空NaN的形式

新增一列--- 并为不存在的列赋值会创建新列
d1['four'] = 11

2) 删除

1)删除dataframe --- del d1
2) 删除dataframe指定的行 ---d1.drop(['a' , 'b'] ) ,删除 d1数据框索引值为a和b的数据
3) 删除dataframe指定的列  ---  d1.drop('one' , 'two' ,axis =1) ,通过指定axis的值来表明是删除列还是行,axis默认值是0,0为行,1为列
4)布尔索引对数据框的查询,实际上也是删除数据操作,返回满足条件的数据
d1.drop(d1['three']>11)

3)改,修改数据中的值

4)查,重点讲解聚合、排序、多表链接操作

4.1)group by 聚合函数
聚合:pandas模块中可以通过groupby()函数实现数据的聚合操作


如果不对聚合函数做限制的话,group by会对数值型数据进行聚合计算,如students数据框,有name,height,weight,sex,age列,name列是字符串,所以不会进行计算.

通过drop删除该变量

groupby还可以设置多个分组变量,例如对年龄和性别分组,来计算年龄和身高的平均值

还可以对每个分组进行多个统计量的计算,通过agg([ , ,])

4.2) 排序

排序在日常的统计分析中还是比较常见的操作,我们可以使用order、sort_index和sort_values实现序列和数据框的排序工作:

我们再试试降序排序的设置:

上面两个结果其实都是按值排序,并且结果中都给出了警告信息,即建议使用sort_values()函数进行按值排序。
在数据框中一般都是按值排序,例如:

4.3) 多表连接

多表之间的连接也是非常常见的数据库操作,连接分内连接和外连接,在数据库语言中通过join关键字实现,pandas我比较建议使用merger函数实现数据的各种连接操作。
如下是构造一张学生的成绩表

现在想把学生表student与学生成绩表score做一个关联,该如何操作呢?

注意,默认情况下,merge函数实现的是两个表之间的内连接,即返回两张表中共同部分的数据。可以通过how参数设置连接的方式,left为左连接;right为右连接;outer为外连接。

左连接实现的是保留student表中的所有信息,同时将score表的信息与之配对,能配多少配多少,对于没有配对上的Name,将会显示成绩为NaN。

六、缺失值处理

不想写了,上链接吧   http://www.cnblogs.com/nxld/p/6058591.html

https://www.cnblogs.com/lingLongBaby/p/7147378.html

http://www.cnblogs.com/WoLykos/p/9349581.html

https://www.cnblogs.com/zuizui1204/p/6423069.html

发布了33 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/fenglepeng/article/details/104739623