Python数据分析笔记

第一章 NumPy基础:数组和矢量计算

1.Numerical Python是高性能科学计算和数据分析的基础包。它提供了一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组ndarray;用于对整组数据进行快速运算的标准数学函数(无需编写循环);用于读写磁盘数据的工具以及用于操作内存映射文件的工具;线性代数、随机数生成以及傅里叶变换功能;用于集成由C、C++、Fortran等语言编写的代码的工具;提供了一个简单易用的CAPI。

2.NumPy最重要的特点就是其N维数组对象(即ndarray),是一个快速灵活的大数据集容器;是一个通用的同构数据多维容器,即所有元素必须为相同类型的。每个数组都有一个shape(一个表示各维度大小的元组)和一个dtype(一个用于说明数组数据类型的对象)。

3.ndarray的创建,array函数,zeros函数,ones函数,empty函数,arange函数(注意与range和xrange函数的区别),eye和identity函数。

4.ndarray的数据类型,dtype,也可以通过astype函数转换数组的类型。注意:调用astype无论如何都会创建出一个新的数组(原始数据的一份拷贝),即使新dtype与老dtype相同也是如此。

5.数组和标量之间的运算,不用编写循环就可以对数据执行批量运算,即矢量化。大小相等的数组之间的任何算术运算都会将运算应用到元素级;数组与标量之间的运算也会将那个标量传播到各个元素;不同大小的数组之间的运算叫做广播(broadcasting)。

6.数组基本的索引和切片。当将一个标量值赋值给一个切片时(如arr[5:8]= 12),该值会自动传播到整个选区。跟列表最重要的区别在于,数组切片是原始数组的视图,这意味着数据不会被复制,视图上的任何修改都会直接映射到源数组上。由于NumPy的设计目的是处理大数据,所以可以想象,假如NumPy坚持要将数据复制来复制去的话会产生何等的性能和内存的问题。也可以显式地进行复制操作,例如arr[5:8].copy()。二维数组元素的索引访问的两种方式,例如arr0,arr[0,2]。切片索引;布尔型索引,通过布尔型索引选取数组中的数据,将总是创建数据的副本,即使返回一模一样的数组也是如此;花式索引(Fancyindexing),花式索引跟切片不一样,它总是将数据复制到新数组中。

7.数组转置和轴对称。转置(transpose)是重塑的一种特殊形式,它返回的是数据的视图(不会进行任何复制操作),tanspose方法和T属性,swapaxes方法。

8.通用函数(ufunc):快速的元素级数组函数。一些一元ufunc和一些二元ufunc。

9.利用数组进行数据处理,用数组表达式代替循环的做法,通常被称为矢量化。(1)将条件逻辑表述为数组运算,numpy.where(condition, x , y)函数是三元表达式xif condition else y的矢量化版本;(2)数学和统计方法,例如numpy.sum(arr, axis = 0)函数(也可写成arr.sum(axis = 0)),还有一些其他的函数,如mean,std,var,min(注意与通用函数minimum的区别),max(注意与通用函数maximum的区别),argmin,argmax,cumsum,cumprod;(3)用于布尔型数组的方法,例如:arr= randn(100),(arr > 0).sum(),另外还有两个方法,any和all,这两个方法也能用于非布尔型数组,所有非0元素将会被当做True;(4)排序,arr.sort(1)为在第1维上的就地排序,会修改原数组本身,而*方法numpy.sort(1)为在第1维上的复制排序,返回的是数组的已排序副本,利用排序后的数组可以计算数组的百分位数;(5)唯一化以及其他的集合逻辑,numpy提供了一些针对一维ndarray的基本集合运算,最常用的numpy.unique()函数,与sorted(set())的功能类似,numpy.in1d函数用于测试一个数组中的值在另一个数组中的成员资格,返回一个布尔型数组,其他方法例如intersect1d(x,y),union1d(x,y),setdiff1d(x,y),setxor1d(x,y)。

10.用于数组的文件输入输出。(1)将数组以二进制格式保存到磁盘,numpy.save,numpy.load,数组文件格式为.npy,将多个数组保存到一个压缩文件中numpy.savez,numpy.load,数组文件格式为.npz;(2)存取文本文件,NumPy中提供numpy.loadtxt,numpy.savetxt,numpy.genfromtxt。

11.线性代数。NumPy提供了一个用于矩阵乘法的dot函数(既是一个数组方法也是numpy命名空间中的一个函数),numpy.linalg库中有一组标准的矩阵分解运算以及诸如求逆和行列式之类的东西,例如diag,trace,det,eig,inv,svd,solve。

12.随机数生成。numpy.random模块提供了一些用于高效生成多种概率分布的样本值的函数。例如:rand(均匀分布),randint(随机整数),randn(正态分布),binomial(二项分布),normal(正态分布),beta(Beta分布),chisquare(卡方分布),gamma(Gamma分布),uniform(在[0,1]之间均匀分布)。

第二章 pandas入门

1.pandas的两个主要数据结构:Series和DataFrame。

2.Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。Series的字符串表现形式为:索引在左边,值在右边。可通过Series的values和index属性来获取其值和索引对象。在创建Series的时候可以通过index作为关键字参数手动指定每个值的索引。可通过索引的方式选取Series中的单个或一组值。Series类型的对象进行的运算(如根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引和值之间的链接。Series可以被看成是一个 定长有序 字典(注意与字典的区别),因为它是索引值到数据值的一个映射。如果数据被存放在一个Python字典中,也可以直接通过这个字典来创建Series。pandas中的isnull和notnull函数(Series对象也可直接使用这两个函数)可用于检测缺失数据。Series最重要的一个功能是:它在算术运算中会自动对齐不同索引的数据。Series对象本身及其索引都有一个name属性。Series的索引可以通过赋值的方式就地修改。

3.DataFrame是一个表格型的数据结构。它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引。构建DataFrame最常用的一种方法是直接传入一个由等长列表或NumPy数组组成的字典。如果指定了列序列(通过关键字参数columns指定),则DataFrame的列就会按照指定顺序进行排列,当然也可以指定行索引(通过关键字参数index指定)。跟Series一样,如果传入的列在数据中找不到,就会自动产生NaN值。通过类似字典标记的方式或者属性的方式,可以将DataFrame的列获取为一个Series。行也可以通过位置或名称的方式进行获取,比如用索引字段ix。列可以通过赋值的方式进行修改,将列表或数组赋值给某个列时,其长度必须跟DataFrame的长度相匹配,如果赋值的是一个Series,就会精确匹配DataFrame的索引。为不存在的列赋值会创建一个新列。关键字del用于删除列。另一种常见的数据形式是嵌套字典,外层字典的键作为列,内层键则作为行索引。可以设置DataFrame的index和columns的name属性。DataFrame的values属性会以二维ndarray的形式返回DataFrame中的数据。

4.索引对象。pandas的索引对象负责管理轴标签和其他元数据(比如轴名称等)。Index对象是不可修改的(immutable),因此用户不能对其进行修改,不可修改性非常重要,因为这样才能使Index对象在多个数据结构之间安全共享。

5.重新索引。pandas的一个重要方法reindex,作用是创建一个适应新索引的新对象。例如调用Series的reindex方法将会根据新索引进行重排,如果某个索引值当前不存在,就引入缺失值或者用关键字参数fill_value指定。对于时间序列这样的有序数据,重新索引时可能需要做一些插值处理,关键字参数method选项即可达到此目的。对于DataFrame,reindex可以修改(行)索引、列,或两个都修改。如果仅传入一个序列,则会重新索引行,使用columns关键字参数即可重新索引列,也可以同时对行和列进行重新索引,而插值则只能按行应用(即轴0)。利用ix的标签索引功能,重新索引任务可以变得更简洁。

6.丢弃指定轴上的项。丢弃某条轴上的一个或多个项很简单,只要一个索引数组或列表即可,drop方法返回的是一个在指定轴上删除了指定值的新对象。对于DataFrame,可以删除任意轴上的索引值(用axis关键字参数指定除轴0以外的其他轴)。

7.索引、选取和过滤。Series索引(obj[…])的工作方式类似于NumPy数组的索引,只不过Series的索引值不只是整数,既可以通过整数索引访问也可以通过Series原有的索引访问,也可由索引组成的列表访问多个项,也可通过布尔型列表选取和过滤访问部分项,也可通过整数切片索引访问部分项。 注意 利用标签(Series的指定索引)的切片运算与普通的Python切片运算不同,其末端是包含的。对DataFrame进行索引其实就是获取一个或多个列。与Series一样也可以通过切片或布尔型数组选取行。另一种用法是通过布尔型DataFrame进行索引,这使DataFrame在语法上更像ndarray。索引字段ix可以使我们通过NumPy式的标记法以及轴标签从DataFrame中选取行和列的子集。

8.算术运算和数据对齐。pandas最重要的一个功能是它可以对不同索引的对象进行算术运算。在将Series对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。自动的数据对齐操作在不重叠的索引处引入了NaN值。对于DataFrame,对齐操作会同时发生在行和列上。算术运算方法有add、sub、div、mul。DataFrame和Series之间的运算,默认情况下,DataFrame和Series之间的算术运算会将Series的索引匹配到DataFrame的列,然后沿着行一直向下广播,对于在DataFrame或Series中找不到的索引值,则参与运算的两个对象就会被重新索引以形成并集,如果希望匹配行且在列上广播,则必须使用算术运算方法,例如df.sub(ser,axis = 0)。

9.函数应用和映射。NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象。另外用DataFrame的apply方法可以将函数应用到各列或行所形成的一维数组上。除标量值外,传递给apply的函数还可以返回由多个值组成的Series。另外DataFrame的applymap方法可以接受元素级的python函数,同样Series的map方法也可以接受元素级的python函数。

10.排序和排名。根据条件对数据集进行排序(sorting)也是一种重要的内置运算。可使用sort_index方法,它将返回一个已排序的新对象。对于Series对象,是对其索引排序(按字典顺序)。对于DataFrame对象,则可以根据任意一个轴上的索引进行排序,使用axis关键字参数,也可以指定为降序排序,使用ascending= False关键字参数。若要按值对Series进行排序,可使用其order方法,在排序时,任何缺失值(numpy.nan)默认都会被放到Series的末尾。在DataFrame上,若希望根据一个或多个列中的值进行排序,则将一个或多个列的名字传递给sort_index方法的by关键字选项即可。Series和DataFrame的排名(ranking)方法为rank。

11.带有重复值的轴索引。索引的is_unique属性可以告诉你它的值是否是唯一的,例如obj.index.is_unique。

12.汇总和计算描述统计。DataFrame的sum和mean方法将会返回一个含有列小计的Series,传入axis= 1将会按行进行求和运算,通过skipna= False关键字选项可以禁用自动排除NaN值的功能。有些方法(如idxmax和idxmin)返回的是间接统计(比如达到最小值或最大值的索引)。另一些方法则是累计型的,如cumsum方法。还有一些方法既不是约简型也不是累计型,如describe方法用于一次性产生多个汇总统计。

13.相关系数与协方差。Series和DataFrame都可以用corr和cov方法分别计算相关系数和协方差。利用DataFrame的corrwith方法可以计算其列或行跟另一个Series或DataFrame之间的相关系数,传入axis= 1可按行进行计算。

14.唯一值、值计数以及成员资格。对于Series,用unique方法可以得到Series中的唯一值数组,返回的唯一值是未排序的,可以用sort方法对结果再次进行排序。value_counts用于计算一个Series中各值出现的频率,为了便于查看,结果Series是按值频率降序排列的。value_counts还是一个*pandas方法,可用于任何数组或序列。isin方法用于判断矢量化集合的成员资格,可用于选取Series中或DataFrame列中数据的子集。

15.处理缺失数据。pandas的设计目标之一就是让缺失数据的处理任务尽量轻松,pandas对象上的所有描述统计都排除了缺失数据。Python内置的None值也会被当做NaN处理。可以用isnull方法来判断对象是否存在NaN值。(1)过滤缺失数据。对于一个Series,dropna返回一个仅含非空数据和索引值的Series,也可以通过布尔型索引达到这个目的。对于DataFrame对象,可能希望丢弃全NaN或含有NaN的行或列,dropna默认丢弃任何含有缺失值的行,传入how= ‘all’将只丢弃全为NaN的那些行,要用这种方式丢弃列,只需传入axis= 1即可,另一个滤除DataFrame行的问题涉及时间序列数据,可以用thresh参数实现此目的。(2)填充缺失数据。fillna方法用于填充缺失数据,其参数若为一个常数则将会将全部缺失值替换为那个常数值;其参数若为一个字典则可以实现对不同列填充不同的值;fillna默认会返回新对象,但也可以对现有的对象进行就地修改(使用关键字参数inplace= True);对reindex方法有效的那些插值方法也可用于fillna方法,例如关键字参数method= ‘ffill’为前向填充,limit = 2表示可以连续填充的最大数量为2。

16.层次化索引(hierarchicalindexing)。层次化索引使你能在一个轴上拥有多个索引级别,也就是能以低纬度形式处理高纬度数据。(1)对于Series,创建一个Series,并用一个由列表或数组组成的列表作为索引。层次化索引在数据重塑和基于分组的操作(透视表的生成)中扮演着重要角色,例如,对于一个创建好的层次化索引的Series对象,可以通过其unstack方法被重新安排到一个DataFrame中,unstack的逆运算是stack。(2)对于一个DataFrame,每条轴都可以有分层索引,各层都可以有名字(names)。也可以单独创建MultiIndex然后复用(MultiIndex.from_arrays())。由于有了分部的列索引,因此可以轻松选取列分组。(3)重排分级顺序。有时需要重新调整某条轴上各级别的顺序,或根据指定级别上的值对数据进行排序。swaplevel方法接受两个级别编号或名称,并返回一个互换了级别的新对象(但数据不会发生变化)。而sortlevel方法则根据单个级别中的索引值对数据进行排序(稳定的)。交换级别时,常常也会用到sortlevel,这样最终结果就是有序的了。注意:在层次化索引的对象上,如果索引是按字典方式从外到内排序(即调用sortlevel(0)或sort_index()的结果),数据选取操作的性能要好很多。(4)根据级别汇总统计。许多对DataFrame和Series的描述和汇总统计方法(如sum方法)都有一个level选项,它用于指定在某条轴上求和的级别。默认在轴0上,传入axis= 1可以在轴1上求。(5)使用DataFrame的列。DataFrame的set_index函数会将其一个或多个列转换为行索引,并创建一个新的DataFrame,默认情况下那些列会从DataFrame中移除,但也可以通过关键字参数drop= False将其保留下来,reset_index的功能与set_index刚好相反,层次化索引的级别会被转移到列里面。

17.其他有关pandas的话题。(1)整数索引。当索引值为整数时,到底是基于标签的还是基于位置的索引,为了避免歧义,一般情况下是基于标签的索引,如果需要可靠的、不考虑索引类型的、基于位置的索引,可以使用Series的iget_value方法和DataFrame的irow和icol方法。(2)面板数据。pandas的Panel数据结构,可以被看做一个三维版的DataFrame,可以用一个由DataFrame对象组成的字典或一个三维ndarray来创建Panel对象。Panel对象有一个to_frame方法,相应的DataFrame有一个逆运算to_panel方法。

第三章 数据加载、存储与文件格式

1.输入输出通常可以划分为几个大类:读取文本文件和其他更高效的磁盘存储格式,加载数据库中的数据,利用WebAPI操作网络资源。

2.读写文本格式的数据。pandas提供了一些用于将表格型数据读取为DataFrame对象的函数。例如常用的read_csv(分隔符为逗号)和read_table(分隔符为制表符),也可以用read_table读取分隔符为逗号的文本,这时需要关键字参数sep= ‘ , ’即可。默认会将文本的第一行读取为列标签,也可以用header= None关键字参数来为其重新分配默认列标签,也可以用names= []关键字参数来自己定义列标签。如果希望将某一列做成DataFrame的索引,用参数index_col指定列标签或者列编号即可,若希望将多个列做成一个层次化索引,只需传入由列编号或列标签组成的列表即可。若文件各个字段由数量不定的空白符分隔,则可以用正则表达式sep= ‘\s+’表示。可以用关键字参数skiprows跳过文件的一行或多行。可以用关键字参数na_values接受一组用于表示缺失值的字符串。

3.逐块读取文本文件。如果只想读取几行(避免读取整个文件),通过关键字参数nrows进行指定即可。要逐块读取文件,需要设置chunksize(行数)。

4.将数据写出到文本格式。数据也可以被输出(又叫存储或者写入)为分隔符格式的文本。利用DataFrame的to_csv方法可以将数据写到一个以逗号分隔的文件中,当然可以用sep参数指定其他分隔符。缺失值在输出结果中会被表示为空字符串,也可以用参数na_rep将其表示为别的标记值,例如na_rep= ‘NULL’。如果没有设置其他选项,则会写出行和列的标签,当然也可以用参数index =False, header = False禁用。可以只写出一部分的列,并以指定的顺序排列,使用参数cols= [],列表中为需要输出的列标签或列编号。Series也有一个to_csv方法,只是无header行,第一列作为索引。

5.手工处理分隔符格式。对于任何单字符分隔符文件,可以直接使用Python内置的csv模块,将任意已打开的文件或文件型的对象传给csv.reader方法。要手工输出分隔符文件可以使用csv.writer方法。

6.JSON(JavaScriptObject Notation的简称)数据。它是通过HTTP请求在Web浏览器和其他应用程序之间发送数据的标准格式之一。它的基本数据类型有对象(字典)、数组(列表)、字符串、数值、布尔值以及null,对象中所有的键都必须是字符串。可以通过Python标准库中的json模板调用loads方法即json.loads即可将JSON字符串转换成Python形式,相反,json.dumps则将Python对象转换为JSON格式。

7.XML和HTML:Web信息收集。Python第三方库lxml可以用来读写HTML和XML格式的数据。lxml.html模板处理HTML,lxml.objectify模板处理XML。首先需要获取数据的URL,利用Python标准库urllib2中的urlopen方法将其打开,然后用lxml解析得到的数据流。

8.二进制数据格式。实现数据二进制格式存储最简单的办法是使用Python内置的pickle序列化。pandas对象都有一个用于将数据以pickle形式保存到磁盘的save方法,用pandas.load方法将数据读回到Python。(1)使用HDF5格式。HDF5是一个流行的能实现高效读写磁盘上以二进制格式存储的科学数据的工业级库,它是一个C库,提供多种语言(Java、Python、MATLAB)的接口。HDF5中的HDF指的是层次型数据格式(hierarchicaldata format)。Python中的HDF5库有两个接口(即PyTables和h5py),h5py提供了一种直接而高级的HDF5API访问接口,而PyTables则抽象了HDF5的许多细节以提供多种灵活的数据容器、表索引、查询功能以及对核外计算技术的某些支持。注意:HDF5适合用作“一次写多次读”的数据集,适合海量数据处理。(2)读取MicrosoftExcel文件。pandas的ExcelFile类支持读取存储在Excel中的表格型数据,通过传入一个xls或者xlsx文件的路径即可创建一个ExcelFile实例,存放在某个工作表(例如Sheet1)中的数据可以通过parse方法读取到DataFrame中。

9.使用HTML和WebAPI。许多网站都有一些通过JSON或其他格式提供数据的公共API。通过Python访问这些API的一个简单易用的办法是第三方包requests的get方法。

10.使用数据库。基于SQL的关系型数据库,pandas有一个read_frame方法(位于pandas.io.sql模块),只需传入select语句和连接对象即可。对于NoSQL非关系型数据库,例如MongoDB,可以通过pymongo库来驱动。

第四章 数据规整化:清理、转换、合并、重塑

1.合并数据集。(1)pandas.merge可根据一个或多个键将不同DataFrame中的行连接起来。(2)pandas.concat可以沿着一条轴将多个对象堆叠到一起。(3)实例方法combine_first可以将重复数据编接在一起,用一个对象中的值填充另一个对象中的缺失值。

2.数据库风格的DataFrame合并。数据集的合并(merge)或连接(join)运算是通过一个或多个键将行链接起来的。这些运算是关系型数据库的核心。pandas的merge函数是对数据应用这些算法的主要切入点。如果没有指明用哪个列进行连接,merge就会将重叠列的列名当作键。不过,最好用关键字参数on显式指定一下。如果两个对象的列名不同,也可以用参数left_on和right_on分别进行指定。默认情况下,merge做的是how= ‘inner’连接,结果中的键是交集。其他方式还有left、right、outer。外连接求取的是键的并集,组合了左连接和右连接的效果。多对多连接产生的是行的笛卡尔积。要根据多个键进行合并的话,传入一个由列名组成的列表即可。可以利用参数suffixes来处理两个DataFrame的中重复列名。

3.索引上的合并。有时候,DataFrame中的连接键位于其索引中。在这种情况下,你可以在pandas.merge方法中传入left_index= True或right_index= True(或两个都传)以说明索引应该被用作连接键。DataFrame还有一个join实例方法,它能更为方便地实现按索引合并,它还可用于合并多个带有相同或相似索引的DataFrame对象,而不管它们之间有没有重叠的列。DataFrame的join方法默认是在连接键上做左连接,它还支持参数DataFrame的索引跟调用者DataFrame的某个列之间的连接。对于简单的索引合并,还可以向join传入一组DataFrame。

4.轴向连接。另一种数据合并运算也被称作连接(concatenation)、绑定(binding)或堆叠(stacking)。NumPy有一个用于合并原始NumPy数组的concatenate函数。对于pandas对象,带有标签的轴能够进一步推广数组的连接运算,pandas的concat函数。

5.合并重叠数据。还有一种数据组合问题不能用简单的合并或连接运算来处理,可能有索引全部或部分重叠的两个数据集。可以用NumPy数组的where函数来实现这种重叠数据的合并,它用于表达一种矢量化的if- else。还可以直接使用pandas对象的实例方法combine_first,它可以实现一样的功能,而且会进行数据对齐。

6.重塑和轴向旋转。有许多用于重新排列表格型数据的基础运算,这些函数也称作重塑(reshape)或轴向旋转(pivot)运算。(1)重塑层次化索引。层次化索引为DataFrame数据的重排任务提供了一种具有良好一致性的方式,主要功能:实例方法stack将数据的列“旋转”为行(例如DataFrame转变为Series);实例方法unstack将数据的行“旋转”为列(例如Series转变为DataFrame)。默认情况下,stack和unstack方法操作的是最内层的索引,传入分层级别的编号或名称即可对其他级别进行操作。如果不是所有的级别值都能在各分组中找到的话,则unstack操作可能会引入缺失数据,stack默认会滤除缺失数据,因此该运算是可逆的。(2)将“长格式”旋转为“宽格式”。DataFrame的pivot方法可以用来实现该功能。Pivot其实只是一个快捷方式而已:用set_index创建层次化索引,再用unstack重塑。

7.数据转换。(1)移除重复数据。移除DataFrame中出现的重复行,DataFrame的duplicated方法返回一个布尔型Series,表示各行是否是重复行。还有一个与此相关的drop_duplicates方法,它用于返回一个移除了重复行的DataFrame。这两个方法默认会判断全部列,也可以指定部分列进行重复项判断。duplicated和drop_duplicates默认保留的是第一个出现的值组合,也可以传入take_last = True则保留最后一个。(2)利用函数或映射进行数据转换。Series的map方法可以接受一个函数或含有映射关系的字典型对象,使用map是一种实现元素级转换以及其他数据清理工作的便捷方式。(3)替换值。利用fillna方法填充缺失数据可以看做值替换的一种特殊情况。虽然前面提到的map可用于修改对象的数据子集,而replace则提供了一种实现该功能的更简单、更灵活的方法。(4)重命名轴索引。跟Series中的值一样,轴标签也可以通过函数或映射进行转换,从而得到一个新对象,轴还可以被就地修改,而无需新建一个数据结构。跟Series一样,轴标签也有一个map方法。如果想创建数据集的转换版(而不是修改原始数据),比较实用的方法是rename,rename方法的参数index和columns可以被赋值为函数(如str.title)或可以结合字典型对象实现对部分轴标签的更新。如果希望就地修改某个数据集,传入inplace = True即可。(5)离散化和面元划分。为了便于分析,连续数据常常被离散化或拆分为“面元”(bin),使用pandas的cut函数实现该功能,返回的是一个特殊的Categorical对象。Categorical对象有一个labels属性和一个levels属性。可以用pandas的value_counts方法统计落在各个面元中值的个数。如果想要设置自己的面元名称,将labels选项设置为一个指定的列表或数组即可。如果向cut传入的是面元的数量而不是确切的面元边界,则它会根据数据的最小值和最大值计算等长面元。pandas的qcut方法是一个非常类似于cut的函数,它可以根据样本分位数对数据进行面元划分,可以指定一个正整数n,表示按n分位数进行切割,也可以设置自定义的分位数(0到1之间的数值,包括端点)组成的列表。(6)检测和过滤异常值。异常值(outlier)的过滤或变换运算在很大程度上其实就是数组运算。(7)排列和随机采样。利用numpy.random.permutation函数可以轻松实现对Series或DataFrame的列的排列工作,permutation的参数为需要排列的轴的长度,返回一个表示新顺序的整数数组。然后可以在基于ix的索引操作或take函数中使用该数组了。(8)计算指标/哑变量。一种常用于统计建模或机器学习的转换方式是:将分类变量(categorical variable)转换为哑变量矩阵(dummy matrix)或指标矩阵(indicator matrix)。如果DataFrame的某一列中含有k个不同的值,则可以派生出一个k列矩阵或DataFrame(其值全为1和0)。pandas有一个get_dummies函数可以实现该功能。一个对统计应用有用的秘诀是:结合get_dummies和诸如cut之类的离散化函数。

8.字符串操作。大部分文本运算都直接做成了字符串对象的内置方法,对于更加复杂的模式匹配和文本操作,则可能需要用到正则表达式。pandas对此进行了加强,它使你能够对数组数据用字符串表达式和正则表达式,而且能够处理缺失数据。(1)字符串对象方法。例如用split方法拆分以逗号隔开的字符串;用strip方法修剪空白符(包括换行符);用加号可以将多个字符串连接为一个字符串;用逗号的join方法中传入一个字符串列表或字符串元组来将该列表或元组中的所有字符串连接为一个以逗号分隔的字符串。另一类方法关注子串的定位,检测某个串是否为另一个串的子串时,最佳方法为直接用in关键字(当然也可以用index和find方法),注意如果找不到字符串,index将引发异常,find将返回-1;还有一个count方法,用来返回指定子串的出现次数;replace方法用于将指定模式替换为另一个模式,它也常常用于删除模式:传入空字符串。(2)正则表达式。正则表达式(通常称作regex)提供了一种灵活的在文本中搜索或匹配字符串模式的方式。正则表达式是根据正则表达式语言编写的字符串。Python内置的re模块负责对字符串应用正则表达式。re模块的函数可分为三大类:模式匹配、替换以及拆分。描述一个或多个空白符的regex是\s+。例如调用re.split(‘\s+’, text)时,正则表达式会先被编译,然后再在text上调用其split方法。可以用re.compile方法自己编译regex以得到一个可重用的regex对象。若只希望得到匹配regex的所有模式,则可以用findall方法。若打算对许多字符串应用同一条正则表达式,强烈建议通过re.compile创建regex对象,这样可以节省大量的CPU时间。match和search方法跟findall方法功能类似,search方法只返回第一个匹配项,match方法只匹配字符串的首部。另外还有一个sub方法,它会将匹配到的模式替换为指定字符串,并返回所得到的新字符串。(3)pandas中矢量化的字符串函数。清理待分析的散乱数据时,常常需要做一些字符串规整化工作,更为复杂的情况是含有字符串的列有时还含有缺失数据。通过Series或DataFrame对象的map方法,所有字符串和正则表达式方法都能被应用于(传入lambda表达式或其他函数)各个值,但是如果存在NA就会报错。为了解决这个问题,Series有一些能够跳过NA值的字符串操作方法,通过Series的str属性即可访问这些方法。

第五章 绘图和可视化

1.matplotlibAPI函数都位于matplotlib.pyplot模块中,引入约定为import matplotlib.pyplot as plt。IPython以pylab模式启动(windows命令行下命令ipython –pylab,或anaconda里面魔术命令%pylab)后,则IPython会自动导入matplotlib和numpy模块,且是以GUI的方式绘图。若不以pylab模式启动,则需手动导入各模块,且是以命令行的方式绘图。

2.Figure和Subplot。matplotlib的图像都位于Figure对象中,用plt.figure创建一个新的Figure。不能通过空Figure绘图,必须用add_subplot创建一个或多个subplot才行。由于根据特定布局创建Figure和Subplot是一件非常常见的任务,于是便出现了一个更为方便的方法(plt.subplots),它可以创建一个新的Figure,并返回一个含有已创建的Subplot对象的NumPy数组,可以对数组进行索引,其关键字参数sharex = True和sharey = True分别用来使各个subplot对象共享x轴和y轴。如果想要调整Subplot周围的间距,可以利用Figure的subplots_adjust方法,同时它也是一个*函数,其关键字参数wspace和hspace用于控制宽度和高度的百分比,可以用作subplot之间的间距。

3.颜色、标记和线型。plot函数的关键字参数color,marker,linestyle,或简化为例如’ko--’。

4.刻度、标签和图例。plt的xlim()方法和xlim([0,10])分别用来返回x轴的范围和设置x轴的范围。也可以用AxesSubplot对象的实例方法get_xlim和set_xlim。set_title方法设置标题,set_xlabel方法设置x轴标签,set_xticks设置x轴刻度,set_xticklabels设置替代的刻度标签。图例可以用画图函数plot的关键字参数label来指定图例元素名,在之后调用*和实例方法legend(loc = ‘best’)生成。

5.注解以及在Subplot上绘图。注解可以通过text、arrow和annotate等函数进行添加。matplotlib有一些表示常见图形的对象,这些对象被称为块(patch),其中有些可以在matplotlib.pyplot中找到(如Rectangle和Circle),但完整集合位于matplotlib.patches。要在图表中添加一个图形,需要先创建一个块对象,然后通过AxeSubplot对象的实例方法add_patch()将其添加到subplot中。

6.将图表保存到文件及matplotlib配置。利用plt.savefig方法可以将当前图表保存到文件,该方法相当于Figure对象的实例方法savefig,其参数为带文件路径的文件名及扩展名、关键字参数dpi(分辨率)、bbox_inches = ‘tight’(剪除当前图表周围的空白部分)。plt的rc方法用来进行matplotlib的自定义配置(如图像大小、subplot边距、配色方案、字体大小、网格类型等)。

7.pandas中的绘图函数。matplotlib实际上是一种比较低级的工具,因为它要根据数据制作一张图表通常都需要用到多个对象。而pandas有许多能够利用DataFrame对象数据组织特点来创建标准图表的高级绘图方法。(1)线型图。Series和DataFrame都有一个用于生成各类图表的plot方法。默认情况下,它们所生成的是线型图。Series对象的索引会被传给matplotlib,并用以绘制X轴,可以通过Series对象的plot方法的参数use_index = False禁用该功能。DataFrame的plot方法会在一个subplot中为各列绘制一条线,并自动创建图例。(2)柱状图。在生成线型图的代码中加上kind = ‘bar’(垂直柱状图)或kind = ‘barh’(水平柱状图)即可生成柱状图。这时,Series和DataFrame的索引将会被用作X(bar)或Y(barh)刻度。对于DataFrame,柱状图会将每一行的值分为一组,设置关键字参数stacked = True即可为DataFrame生成堆积柱状图,这样每行的值就会被堆积在一起。(3)直方图和密度图。通过Series的hist方法,可以绘制直方图来体现Series中各值出现的频率。密度图也被称作KDE(Kernel Density Estimate,核密度估计)图,调用plot时加上kind = ‘kde’即可生成一张密度图。(4)散布图。散布图(scatter plot)是观察两个一维数据序列之间关系的有效手段。matplotlib的scatter方法是绘制散布图的主要方法。在探索式数据分析工作中,同时观察一组变量的散布图是很有意义的,这也被称为散布图矩阵(scatter plot matrix)。pandas提供了一个能从DataFrame创建散布图矩阵的scatter_matrix函数,它还支持在对角线上放置各变量的直方图或密度图。

8.Python的其他主要的图形化工具。(1)Chaco是由Enthought开发的一个绘图工具包,它既可以绘制静态图又可以生成交互式图形。(2)mayavi项目是一个基于开源C++图形库VTK的3D图形工具包。(3)其他库,有用于绘制地图和投影的basemap工具集以及用于3D图形的mplot3d。总体趋势:大部分库都在向基于Web的技术发展,并逐渐远离桌面图形技术。

第六章 数据聚合与分组运算

1.GoupBy技术。pandas对象中的数据会根据你所提供的一个或多个键被拆分(split)为多组,拆分操作是在对象的特定轴上执行的,然后,将一个函数应用(apply)到各个分组并产生一个新值,最后,所有这些函数的执行结果会被合并(combine)到最终的结果对象中。

2.对分组进行迭代。GoupBy对象支持迭代,可以产生一组二元元组(由分组名和数据块组成)。对于多重键的情况,元组的第一个元素将会是由键值组成的元组。goupby默认是在axis = 0上进行分组的,通过设置也可以在其他任何轴上进行分组。

3.选取一个或一组列。对于由DataFrame产生的GoupBy对象,如果用一个(单个字符串)或一组(字符串数组)列名对其进行索引,就能实现选取部分列进行聚合的目的。

4.通过字典或Series进行分组。字典或者Series可以作为用来分组的键值,它们可以被看做一个固定大小的映射。

5.通过函数进行分组。也可以将函数跟数组、列表、字典、Series混合使用,因为任何东西最终都会被转换为数组。

6.根据索引级别分组。层次化索引数据集最方便的地方就在于它能够根据索引级别进行聚合。要实现该目的,通过level关键字传入级别编号或名称即可。

7.数据聚合。对于聚合,指的是任何能够从数组产生标量值的数据转换过程。许多常见的聚合运算都有就地计算数据集统计信息的优化实现,也可以使用自己发明的聚合运算,只需将自己的聚合函数传入aggregate或agg方法即可,但自定义聚合函数要比那些经过优化的函数慢得多,这是因为在构造中间分组数据块时存在非常大的开销(函数调用、数据重排等)。

8.面向列的多函数应用。向agg方法传入由函数组成的列表或二元元组列表或从列名映射到函数的字典。

9.以“无索引”的形式返回聚合数据。只需向groupby传入as_index = False即可。

10.分组级运算和转换。聚合只不过是分组运算的其中一种而已,它是数据转换的一个特例,也就是说,它接受能够将一维数组简化为标量值的函数。而transform和apply方法能够执行更多其他的分组运算。

11.透视表和交叉表。透视表:pivot_table函数;交叉表:crosstab函数。

第七章 时间序列

1.Python标准库包含用于日期(date)和时间(time)数据的数据类型,而且还有日历方面的功能。我们主要会用到datetime、time以及calendar模块。datetime.datetime是用得最多的数据类型,datetime以毫秒形式存储日期和时间。datetime.timedelta对象表示两个datetime对象之间的时间差。另外datetime模块中还有date和time数据类型。datetime对象有year、month、day、hour、minute、second属性。datetime模块的*now函数用来获取当前的datetime数据类型的日期和时间。

2.字符串和datetime的相互转换。利用str或strftime方法,datetime对象和pandas的Timestamp对象可以格式化为字符串。datetime.strptime可以用这些格式化编码将字符串转换为日期,但还有一种简单直接不用定义格式的方法为第三方包dateutil中的parser.parse方法。pandas通常是用于处理成组日期的,不管这些日期是DataFrame的轴索引还是列,to_datetime方法可以解析多种不同的日期表示形式。

3.时间序列基础。pandas最基本的时间序列类型就是以时间戳(通常以Python字符串或datetime对象表示)为索引的Series。跟其他Series一样,不同索引的时间序列之间的算术运算会自动按日期对齐。pandas用NumPy的datetime64数据类型以纳秒形式存储时间戳。

4.索引、选取、子集构造。由于TimeSeries是Series的一个子类,所以在索引以及数据选取方面它们的行为是一样的。这里切片所产生的是源时间序列的视图,跟NumPy数组的切片运算是一样的。此外,还有一个等价的truncate实例方法也可以截取两个日期之间的TimeSeries。

5.带有重复索引的时间序列。通过检查索引的is_unique属性可以判断时间序列是否带有重复索引。假设想要对具有非唯一时间戳的数据进行聚合,一个办法是使用groupby,并传入level = 0(索引的唯一一层)。

6.日期的范围、频率以及移动。(1)生成日期范围。pandas.date_range函数可用于生成指定长度的DatetimeIndex,默认情况下,date_range会产生按天计算的时间点。如果只传入起始(start)或结束(end)日期,那就还得用periods传入一个表示一段时间的数字。date_range默认会保留起始和结束时间戳的时间信息,如果希望产生一组被规范化到午夜的时间戳,normalize = True选项即可实现该功能。(2)频率和日期偏移量。pandas中的频率是由一个基础频率(base frequency)和一个乘数组成的,基础频率通常以一个字符串别名表示,比如“M”表示每月,对于每个基础频率,都有一个被称为日期偏移量(date offset)的对象与之对应。在基础频率别名前面放上一个整数即可创建倍数。有些频率所描述的时间点并不是均匀的,例如,“M”(日历月末)和“BM”(每月最后一个工作日),将这些称为锚点偏移量。频率都是由date_range函数的freq关键字确定的。(3)移动(超前和滞后)数据。移动(shifting)指的是沿着时间轴将数据前移或后移。Series和DataFrame都有一个shift方法用于执行单纯的前移或后移操作,保持索引不变。由于单纯的移位操作不会修改索引,所以部分数据会被丢弃,因此,如果频率已知,则可以将其传给shift以便实现对时间戳进行位移而不是对数据进行简单位移。pandas的日期偏移量还可以用在datetime或Timestamp对象上,通过offset.rollforward和offset.rollback方法可以显式地将日期向前或向后滚动。

7.时区处理。在Python中,时区信息来自第三方库pytz。(1)本地化和转换。默认情况下,pandas中的时间序列是单纯的(naive)时区,时间序列的索引的tz字段为None。在生成日期范围的时候还可以用参数tz = ‘UTC’加上一个时区集。从单纯到本地化的转换是通过tz_localize方法处理的,一旦时间序列被本地化到某个特定时区,就可以用tz_convert将其转换到别的时区了。(2)操作时区意识型Timestamp对象。跟时间序列和日期范围差不多,Timestamp对象也能被从单纯型(naive)本地化为时区意识型(time zone- aware),并从一个时区转换到另一个时区。(3)不同时区之间的运算。如果两个时间序列的时区不同,在将它们合并到一起时,最终结果就会是UTC。由于时间戳其实是以UTC存储的,所以这是一个很简单的运算,并不需要发生任何转换。

8.时期及其算术运算。时期(period)表示的是时间区间,Period类所表示的就是这种数据类型,只需对Period对象加上或减去一个整数即可达到根据其频率进行位移的效果,如果两个Period对象拥有相同的频率,则它们的差就是它们之间的单位数量。period_range函数可用于创建规则的时期(注意不是日期)范围,PeriodIndex类保存了一组Period,它可以在任何pandas数据结构中被用作轴索引。

9.重采样及频率转换。重采样(resampling)指的是将时间序列从一个频率转换到另一个频率的处理过程。高频率数据聚合到低频率数据称为降采样(downsampling),而将低频率数据转换到高频率则称为升采样(upsampling)。pandas对象都带有一个resample方法,它是各种频率转换工作的主力函数,resample方法的主要参数有转换后的频率、降采样时的聚合方式,如how = ‘mean’、聚合的类型,如kind = ‘period’。而升采样时,就不需要聚合了,升采样时默认会引入缺失值,也可以用resample方法的参数fill_method = ‘ffill’或‘bfill’填充缺失值,可以用limit参数来限制填充的最大距离。

10.移动窗口函数。在移动窗口上计算的各种统计函数也是一类常见于时间序列的数组变换,称之为移动窗口函数(moving window function),包括窗口不定长的函数,移动窗口函数也会自动排除缺失值。例如pandas.rolling_mean函数。

第八章 NumPy高级应用

1.ndarray对象的内部机理。NumPy的ndarray提供了一种将同质数据块解释为多维数组对象的方式,ndarray内部由以下内容组成:一个指向数组的指针;数据类型dtype;数组形状元组shape;跨度元组stride(它是构建非复制式数组视图的重要因素)。

2.高级数组操作。(1)只需向数组的实例方法reshape传入一个表示新形式的元组即可实现数组重塑的目的。与reshape运算过程相反的运算通常称为扁平化(flattening)或散开(raveling),ravel方法一般产生的是数组的视图,flatten方法返回的是数组的副本。(2)默认情况下,NumPy数组是按行优先顺序创建的,行和列优先顺序又分别称为C和Fortran顺序。像reshape和ravel这样的函数,都可以接受一个表示数组数据存放顺序的order参数,一般可以是’C’或’F’。(3)数组的合并和拆分,numpy.concatenate可以按指定轴将一个由数组组成的序列(如元组、列表等)连接到一起。对于常见的连接操作,NumPy提供了一些比较方便的方法(如vstack和hstack)。与此相反,split用于将一个数组沿指定轴拆分为多个数组。此外NumPy命名空间中还有两个特殊的对象——r和c,可以使数组的堆叠操作更为简洁。

 

上一篇:pandas对数据的操作


下一篇:【Kubernetes Series】Kubernetes 简介