#!/usr/bin/env python # coding: utf-8 #

Table of Contents

#
# pandas建造在NumPy之上,它使得以NumPy为中心的应用很容易使用。 # In[4]: import numpy as np import pandas as pd from pandas import Series, DataFrame # # Pandas 数据结构入门 # ## Series # # Series 是一个一维的类似的数组对象,包含一个数组的数据(任何 NumPy 的数据类型)和一个与数组关联的数据标签,被叫做 索引 。最简单的 Series 是由一个数组的数据构成: # In[5]: obj = Series([4, 7, -5, 3]) obj # Seriers 的交互式显示的字符窜表示形式是索引在左边,值在右边。 # 因为我们没有给数据指定索引,一个包含整数 0 到 N-1 (这里 N 是数据的长度)的默认索引被创建。 可以分别的通过它的 values 和 index 属性来获取 Series 的数组表示和索引对象: # In[6]: obj.values # In[7]: obj.index # 通常,需要创建一个带有索引来确定没一个数据点的Series: # In[8]: obj2 = Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c']) obj2 # 与正规的 NumPy 数组相比,你可以使用索引里的值来选择一个单一值或一个值集: # In[11]: obj2['a'] # In[12]: obj2['d'] = 6 obj2[['c', 'a', 'd']] # NumPy 数组操作,例如通过一个布尔数组过滤,纯量乘法,或使用数学函数,将会保持索引和值间的关联: # In[13]: obj2 # In[14]: obj2[obj2 > 0] # In[15]: obj2 * 2 # In[16]: np.exp(obj2) # **另一种思考的方式**是,Series 是一个定长的,有序的字典,因为它把索引和值映射起来了。它可以适用于许多期望一个字典的函数: # In[18]: 'b' in obj2 # In[19]: 'e' in obj2 # 如果你有一些数据在一个 Python 字典中,你可以通过传递字典来从这些数据创建一个 Series: # In[20]: sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000} # In[21]: obj3 = Series(sdata) obj3 # 只传递一个字典的时候,结果 Series 中的索引将是排序后的字典的键。 # In[24]: states = ['California', 'Ohio', 'Oregon', 'Texas'] obj4 = Series(sdata, index=states) obj4 # 在这种情况下, sdata 中的3个值被放在了合适的位置,但因为没有发现对应于 ‘California’ 的值,就出现了 NaN (不是一个数),这在 pandas 中被用来标记数据缺失或 NA 值。使用 “missing” 或 “NA” 来表示数度丢失。 # **在 pandas 中用函数 isnull 和 notnull 来检测数据丢失:** # In[26]: pd.isnull(obj4) # In[27]: pd.notnull(obj4) # In[28]: obj4.isnull() # 在许多应用中 Series 的一个重要功能是在算术预算中它会自动对齐不同索引的数据: # In[29]: obj3 # In[30]: obj4 # In[31]: obj3 + obj4 # Series 对象本身和它的索引都有一个 name 属性,它和 pandas 的其它一些关键功能整合在一起: # In[32]: obj4.name = 'population' # In[33]: obj4.index.name = 'state' obj4 # Series 的索引可以通过赋值就地更改: # In[34]: obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan'] # In[35]: obj # ## DataFrame # 一个 Datarame 表示一个表格,类似电子表格的数据结构,包含一个经过排序的列表集,它们每一个都可以有不同的类型值(数字,字符串,布尔等等)。 # Datarame 有行和列的索引;它可以被看作是一个 Series 的字典(每个 Series 共享一个索引)。 # 与其它你以前使用过的(如 R 的 data.frame )类似 Datarame 的结构相比,在 DataFrame 里的面向行和面向列的操作大致是对称的。 # 在底层,数据是作为一个或多个**二维数组**存储的,而不是列表,字典,或其它一维的数组集合。 # 因为 DataFrame 在内部把数据存储为一个二维数组的格式,因此你可以采用分层索引以表格格式来表示高维的数据。 # 有很多方法来构建一个 DataFrame,但最常用的一个是用一个相等长度列表的字典或 NumPy 数组: # In[229]: data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 'year': [2000, 2001, 2002, 2001, 2002], 'pop': [1.5, 1.7, 3.6, 2.4, 2.9]} frame = DataFrame(data) # 由此产生的 DataFrame 和 Series 一样,它的索引会自动分配,并且对列进行了排序: # In[230]: frame # 如果你设定了一个列的顺序,DataFrame 的列将会精确的按照你所传递的顺序排列: # In[38]: DataFrame(data, columns=['year', 'state', 'pop']) # 和 Series 一样,如果你传递了一个行,但不包括在 data 中,在结果中它会表示为 NA 值: # In[64]: frame2 = DataFrame(data, columns=['year', 'state', 'pop', 'debt'],index=['one', 'two', 'three', 'four', 'five']) frame2 # 和 Series 一样,在 DataFrame 中的一列可以通过字典记法或属性来检索: # In[41]: frame2['state'] # In[40]: frame2.year # **注意**,返回的 Series 包含和 DataFrame 相同的索引,并它们的 name 属性也被正确的设置了。 # # 行也可以使用一些方法通过位置或名字来检索,例如 ix 索引成员(field)(更多的将在后面介绍): # In[42]: frame2.ix['three'] # 列可以通过赋值来修改。例如,空的 ‘debt’ 列可以通过一个纯量或一个数组来赋值: # In[65]: frame2['debt'] = 16.5 frame2 # In[66]: frame2['debt'] = np.arange(5.) frame2 # 通过列表或数组给一列赋值时,所赋的值的长度必须和 DataFrame 的长度相匹配。**否则全部为 NA**。 # # 如果你使用 Series 来赋值,它会代替在 DataFrame 中精确匹配的索引的值,并在说有的空洞插入丢失数据: # In[58]: val2 = Series([-1.2, -1.5, -1.7]) # In[60]: frame2['debt'] = val2 frame2 # In[62]: val = Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five']) # In[67]: frame2['debt'] = val frame2 # 给一个不存在的列赋值,将会创建一个新的列。 像字典一样 del 关键字将会删除列: # In[68]: frame2['eastern'] = frame2.state == 'Ohio' frame2 # **注意:**索引 DataFrame 时返回的列是底层数据的一个视窗,而不是一个拷贝。因此,任何在 Series 上的就地修改都会影响 DataFrame。列可以使用 Series 的 copy 函数来显式的拷贝。 # **另一种通用的数据形式是一个嵌套的字典的字典格式:** # In[69]: pop = {'Nevada': {2001: 2.4, 2002: 2.9}, 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}} # In[70]: pop # 如果被传递到 DataFrame,它的外部键会被解释为列索引,内部键会被解释为行索引: # In[72]: frame3 = DataFrame(pop) frame3 # 当然,总是可以对结果转置: # In[73]: frame3.T # 内部字典的键被结合并排序来形成结果的索引。如果指定了一个特定的索引,就不是这样的了: # In[74]: DataFrame(pop, index=[2001, 2002, 2003]) # Series 的字典也以相同的方式来处理: # In[75]: pdata = {'Ohio': frame3['Ohio'][:-1], 'Nevada': frame3['Nevada'][:2]} # In[76]: pdata # In[77]: DataFrame(pdata) # 如果一个 DataFrame 的 index 和 columns 有它们的 name ,也会被显示出来: # In[79]: frame3.index.name = 'year'; frame3.columns.name = 'state' frame3 # 像 Series 一样, values 属性返回一个包含在 DataFrame 中的数据的二维 ndarray: # In[80]: frame3.values # 如果 DataFrame 的列有不同的 dtypes,返回值数组将会给所有的列选择一个合适的 dtyps: # In[82]: frame2 # In[81]: frame2.values # **可能的传递到DataFrame的构造器** # |二维ndarray| 一个数据矩阵,有可选的行标和列标| # |----------|----------------------------| # |数组,列表或元组的字典|每一个序列成为DataFrame中的一列。所有的序列必须有相同的长度。| # |NumPy的结构/记录数组| 和“数组字典”一样处理| # |Series的字典| 每一个值成为一列。如果没有明显的传递索引,将结合每一个Series的索引来形成结果的行索引。| # |字典的字典| 每一个内部的字典成为一列。和“Series的字典”一样,结合键值来形成行索引。| # |字典或Series的列表| 每一项成为DataFrame中的一列。结合字典键或Series索引形成DataFrame的列标。| # |列表或元组的列表| 和“二维ndarray”一样处理| # |另一个DataFrame| DataFrame的索引将被使用,除非传递另外一个| # |NumPy伪装数组(MaskedArray)| 除了蒙蔽值在DataFrame中成为NA/丢失数据之外,其它的和“二维ndarray”一样| # ## 索引对象 # pandas 的索引对象用来保存坐标轴标签和其它元数据(如坐标轴名或名称)。构建一个 Series 或 DataFrame 时任何数组或其它序列标签在内部转化为索引: # In[84]: obj = Series(range(3), index=['a', 'b', 'c']) index = obj.index index # In[86]: index[1:] # 索引对象是不可变的,因此不能由用户改变: # In[87]: index[1] = 'd' # **索引对象的不可变性非常重要,这样它可以在数据结构中结构中安全的共享:** # In[88]: index = pd.Index(np.arange(3)) obj2 = Series([1.5, -2.5, 0], index=index) obj2.index is index # 下表是库中内建的索引类清单。通过一些开发努力,索引可以被子类化,来实现特定坐标轴索引功能。 # |索引类型|说明| # |-------|---| # |Index|最通用的索引对象,使用Python对象的NumPy数组来表示坐标轴标签。| # |Int64Index|对整形值的特化索引。| # |MultiIndex|“分层”索引对象,表示单个轴的多层次的索引。可以被认为是类似的元组的数组。| # |DatetimeIndex|存储纳秒时间戳(使用NumPy的datetime64 dtyppe来表示)。| # |PeriodIndex|对周期数据(时间间隔的)的特化索引。| # 除了类似于阵列,索引也有类似固定大小集合一样的功能: # In[92]: frame3 # In[93]: 'Ohio' in frame3.columns # In[94]: 2003 in frame3.index # 每个索引都有许多关于集合逻辑的方法和属性,且能够解决它所包含的数据的常见问题。这些都总结在下表中。 # |方法 | 属性| # |----|-----| # |append |链接额外的索引对象,产生一个新的索引| # |diff |计算索引的差集| # |intersection |计算交集| # |union |计算并集| # |isin |计算出一个布尔数组表示每一个值是否包含在所传递的集合里| # |delete |计算删除位置i的元素的索引| # |drop |计算删除所传递的值后的索引| # |insert |计算在位置i插入元素后的索引| # |is_monotonic |返回True,如果每一个元素都比它前面的元素大或相等| # |is_unique |返回True,如果索引没有重复的值| # |unique |计算索引的唯一值数组| # # 重新索引:reindex # pandas 对象的一个关键的方法是 reindex ,意味着使数据符合一个新的索引来构造一个新的对象。来看一下下面一个简单的例子: # In[105]: obj = Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c']) obj # 在 Series 上调用 reindex 重排数据,使得它符合新的索引,如果那个索引的值不存在就引入缺失数据值: # **注意:**reindex 并不改变 index 的数值,只是重排数据。(索引对象的不可变性) # In[106]: obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e']) obj2 # In[107]: obj.reindex(['a', 'b', 'c', 'd', 'e'], fill_value=0) # 为了对**时间序列**这样的数据排序,**当重建索引的时候可能想要对值进行内插或填充**。 method 选项可以是你做到这一点,使用一个如 ffill 的方法来向前填充值: # In[110]: obj3 = Series(['blue', 'purple', 'yellow'], index=[0, 2, 4]) # In[111]: obj3 # In[109]: obj3.reindex(range(6), method='ffill') # 下是可用的 method 选项的清单。在此,内差比正向和反向填充更复杂。 # - reindex 的 method(内插)选项 # # |参数|描述| # |---|---| # |ffill或pad |前向(或进位)填充| # |bfill或backfill |后向(或进位)填充| # 对于 DataFrame, reindex 可以改变(行)索引,列或两者。当只传入一个序列时,结果中的行被重新索引了: # In[112]: frame = DataFrame(np.arange(9).reshape((3, 3)), index=['a', 'c', 'd'], columns=['Ohio', 'Texas', 'California']) # In[113]: frame # In[114]: frame2 = frame.reindex(['a', 'b', 'c', 'd']) # In[115]: frame2 # 使用 **columns** 关键字可以使列重新索引: # In[116]: states = ['Texas', 'Utah', 'California'] # In[118]: frame.reindex(columns=states) # 再次注意索引对象的不可变性 # 一次可以对两个重新索引,可是插值只在**行侧(0坐标轴)**进行: # In[121]: frame # In[119]: frame.reindex(index=['a', 'b', 'c', 'd'], method='ffill', columns=states) # 正如你将看到的,使用带标签索引的 **ix** 可以把重新索引做的更简单: # In[120]: frame.ix[['a', 'b', 'c', 'd'], states] # - **reindex** 函数的参数 # # |参数|说明| # |---|---| # |index |作为索引的新序列。可以是索引实例或任何类似序列的Python数据结构。一个索引被完全使用,没有任何拷贝。| # |method |插值(填充)方法,见表格5-4的选项| # |fill_value |代替重新索引时引入的缺失数据值| # |limit |当前向或后向填充时,最大的填充间隙| # |level |在多层索引上匹配简单索引,否则选择一个子集| # |copy |如果新索引与就的相等则底层数据不会拷贝。默认为True(即始终拷贝)| # # 从一个坐标轴删除条目 # 从坐标轴删除一个多或多个条目是很容易的,如果你有一个索引数组或列表且没有这些条目,但是这可能需要一点修改和集合逻辑。 drop 方法将会返回一个新的对象并从坐标轴中删除指定的一个或多个值: # In[122]: obj = Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e']) # In[124]: new_obj = obj.drop('c') new_obj # In[125]: obj.drop(['d', 'c']) # 对于 DataFrame,可以从任何坐标轴删除索引值: # In[126]: data = DataFrame(np.arange(16).reshape((4, 4)), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four']) # In[127]: data.drop(['Colorado', 'Ohio']) # In[128]: data.drop('two', axis=1) # In[129]: data.drop(['two', 'four'], axis=1) # ## 索引,挑选和过滤 # Series 索引 ( obj[...] )的工作原理类似与 NumPy 索引,除了可以使用 Series 的索引值,也可以仅使用整数来索引。下面是关于这一点的一些例子: # In[138]: obj = Series([2,3,1,5], index=['a', 'b', 'c', 'd']) obj # In[139]: obj['b'], obj[1] # In[140]: obj[['b', 'a', 'd']] # In[142]: obj[[1, 3]] # 索引位置 # In[143]: obj[obj < 2] # 使用标签来切片和正常的 Python 切片并不一样,**它会把结束点也包括在内**: # In[144]: obj['b':'c'] # In[146]: obj['b':'c'] = 5 obj # 正如上面你所见到的,索引 DataFrame 来检索一个或多个列,可以使用一个单一值或一个序列: # In[256]: data = DataFrame(np.arange(16).reshape((4, 4)), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four']) # In[257]: data # In[258]: data['two'] # In[259]: data[['three', 'one']] # 像这样的索引有一些特殊的情况。首先,可以通过切片或一个布尔数组来选择行: # In[151]: data[:2] # In[260]: data[(data.one >=1 ) & (data.one < 7) ] # 多个逻辑条件组合 # In[152]: data[data['three'] > 5] # 另一种用法是在索引中使用一个布尔 DataFrame,例如通过纯量比较产生的: # In[153]: data < 5 # In[156]: data[data <5] = 0 # In[157]: data # 在这种情况下使得 DataFrame 的语法更像一个 ndarry。为了使 DataFrame 可以在行上进行标签索引,我将介绍特殊的索引字段 ix 。这使你可以从 DataFrame 选择一个行和列的子集,使用像 NumPy 的记法再加上轴标签。正如我早先提到的,这也是一种不是很冗长的重新索引的方法: # In[158]: data.ix['Colorado', ['two', 'three']] # In[161]: data.ix[['Colorado', 'Utah'], [3, 0, 1]] # 3,0,1 表示位置顺序 # In[163]: data.ix[2] # 第 2 行 # In[166]: data.ix[:,2] # 第 2 列 # In[167]: data.ix[:'Utah', 'two'] # In[173]: data.ix[data.three > 5, :] # In[174]: data.ix[data.three > 5, :3] # 因此,有很多方法来选择和重排包含在 pandas 对象中的数据。对于 DataFrame , 下表是这些方法的简短概要。稍后你将接触到分层索引,那时你会有一些额外的选项。 # **注意**:在设计 pandas 时,我觉得不得不敲下 frame[:, col] 来选择一列,是非常冗余的(且易出错的),因此列选择是最常见的操作之一。 # 因此,我做了这个设计权衡,把所有的富标签索引引入到 ix 。 # |切片命令|说明| # |------|-----| # |obj[val] |从DataFrame选择单一列或连续列。特殊情况下的便利:布尔数组(过滤行),切片(行切片),或布尔DataFrame(根据一些标准来设置值)。| # |obj.ix[val] |从DataFrame的行集选择单行| # |obj.ix[:, val] |从列集选择单列| # |obj.ix[val1, val2] |选择行和列| # |reindex 方法 |转换一个或多个轴到新的索引| # |xs 方法 |通过标签选择单行或单列到一个Series| # |icol, irow 方法 |通过整数位置,分别的选择单行或单列到一个Series| # |get_value, set_value 方法 |通过行和列标选择一个单值| # **其他切片方式:** # In[185]: data # ### 使用标签选取数据 # In[183]: # df.loc[行标签,列标签] data.loc['Colorado':'New York'] # 选取 a:b 行数据 # In[182]: data.loc[:,'one'] # 选取 one 列的数据 # ### 使用位置选取数据 # In[184]: # df.iloc[行位置,列位置] data.iloc[1,1] # 选取第二行,第二列的值,返回的为单个值 # In[189]: data.iloc[[0,2], :] #选取第一行及第三行的数据 # In[190]: data.iloc[0:2,:] # 选取第一行到第三行(不包含)的数据,就是前两行的数据 # In[191]: data.iloc[:,1] # 选取所有记录的第一列的值,返回的为一个 Series # In[192]: data.iloc[1,:] # 选取第二行数据,返回的为一个 Series # ## 算术运算 # 当把对象加起来时,如果有任何的索引对不相同的话,在结果中将会把各自的索引联合起来。 # 在索引不重合的地方引入了 NA 值。 # ### 广播 # In[197]: arr = np.arange(12.).reshape(3,4) # In[198]: arr[0] # In[199]: arr-arr[0] # **以下内容参考至**:[Python中的结构化数据分析利器-Pandas简介](http://cloga.info/python/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6/2013/09/17/pandasintro) # # 文件操作 # In[ ]: # 从 CSV 中读取数据 df = pd.read_csv('foo.csv') # In[ ]: #将 DataFrame 写入 CSV df.to_csv('foo.csv') # In[ ]: # 从 Excel 中读取数据:先定义一个 Excel 文件, # 用 xls.parse 解析 sheet1 的内容,index_col 用于指定 index 列,na_values 定义缺失值的标识。 xls = ExcelFile('foo.xlsx') xls.parse('sheet1', index_col=None, na_values=['NA']) # In[ ]: # 将DataFrame 写入 Excel 文件 df.to_excel('foo.xlsx', sheet_name='sheet1') # # 基本运算 # In[142]: data = DataFrame(np.arange(16).reshape((4, 4)), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four']) # In[16]: data # In[7]: data.mean() # 计算列的平均值,参数为轴,可选值为 0 或 1.默认为 0,即按照列运算 # In[8]: data.sum(1) # 计算行的和 # In[9]: # 将一个函数应用到 DataFrame 的每一列,这里使用的是匿名 lambda 函数,与 R 中 apply 函数类似 data.apply(lambda x: x.max() - x.min()) # In[95]: # 应用到某一列 # 推荐 data['one'] = data['one'].apply(lambda x: x+1) data # In[143]: # 应用到某一列 # 首元素会多执行一遍 def addone(v): v[0] += 1 return v data.apply(addone, axis=1) # In[73]: def addone(v): v += 1 return v data['one'] = data['one'].map(addone) data # # 常用操作 # ## 排序 # In[234]: df = DataFrame(np.arange(9).reshape((3, 3)), index=['a', 'c', 'd'], columns=['Ohio', 'Texas', 'California']) # In[235]: df # In[238]: df.ix["a"] = [10,11,12] # In[251]: df # sort_index 可以以轴的标签进行排序。axis 是指用于排序的轴,可选的值有 0 和 1,默认为 0 即行标签(Y 轴),1 为按照列标签排序。 ascending 是排序方式,默认为 True 即降序排列。 # In[252]: df.sort_index(axis=0, ascending=False) # 对行进行排序 d,c,a # In[212]: df # In[254]: df.sort_index(axis=1, ascending=False) # 对列进行排序 Texas, Ohio, California # DataFrame 也提供按照指定列进行排序,可以仅指定一个列作为排序标准(以单独列名作为 columns 的参数),也可以进行多重排序(columns 的参数为一个列名的 List,列名的出现顺序决定排序中的优先级),在多重排序中 ascending 参数也为一个 List,分别与 columns 中的 List 元素对应。 # In[243]: df.sort_values(by='Ohio', ascending=False) # In[246]: df.ix[1,1]=9 # In[247]: df # In[250]: df.sort_values(by=['Ohio','Texas'],ascending=[0,1]) # ## 重命名列 # In[ ]: df.rename(columns={u'one':'1'}, inplace=True) # ## 设置索引 # In[ ]: df.set_index('one') # ## 重设索引 # In[ ]: df.reset_index(inplace=True) # ## 查看最大最小值 # In[ ]: pd.Series.max() pd.Series.idxmax() # ## 改变数据类型 # In[ ]: df['A'].astype(float) # ## 计算 Series 每个值的频率 # In[ ]: df['A'].value_counts() # # DataFrame 的合并 # ## Concat # In[267]: ds = [{'one' : 4,'two':2},{'one' : 5,'two' : 3},{'one' : 6,'two' : 4},{'two' : 7,'three':10}] dfs = pd.DataFrame(ds,index=['e','f','g','h']) # In[269]: dfs # In[292]: ##构建一个新的 DataFrame,dfs df_t=pd.concat([dfs,dfs],axis=1) # 合并两个 DataFrame # In[293]: df_t # In[294]: ##构建一个新的 DataFrame,dfs df_t=pd.concat([dfs,dfs],axis=0) # 合并两个 DataFrame # In[295]: df_t # ## Merge # In[296]: left = pd.DataFrame({'key': ['foo1', 'foo2'], 'lval': [1, 2]}) right = pd.DataFrame({'key': ['foo1', 'foo2'], 'rval': [4, 5]}) #构建了两个DataFrame pd.merge(left, right, on='key')#按照key列将两个DataFrame join在一起 # In[297]: left # In[298]: right # ## Groupby # In[300]: import random # In[305]: df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'], 'B' : ['one', 'one', 'two', 'three','two', 'two', 'one', 'three'], 'C' :np.random.randn(8), 'D' : np.random.randn(8)}); # In[306]: df # In[307]: df.groupby('A').sum() # 按照 A 列的值分组求和 # In[308]: df.groupby(['A','B']).sum() # 按照 A、B 两列的值分组求和 # **在实际应用中,先定义 groups,然后再对不同的指标指定不同计算方式。** # In[ ]: groups = df.groupby('A') # 按照 A 列的值分组求和 groups['B'].sum() # 按照 A 列的值分组求 B 组和 groups['B'].count() # 按照 A 列的值分组 B 组计数 # In[309]: groups = df.groupby('A') # 按照 A 列的值分组求和 # In[312]: groups['C'].sum() # 按照 A 列的值分组求 B 组和 # In[314]: groups['B'].count() # 按照 A 列的值分组 B 组计数 # **默认会以 groupby 的值作为索引,如果不将这些值作为索引,则需要使用 as_index=False** # In[316]: df # In[317]: df.groupby(['A','B'], as_index=False).sum() # 注意与 In [308] 对比 # # 透视表 # 使用 pivot_table 和 crosstab 都可以创建数据透视表 # ## pivot_table # In[318]: df = pd.DataFrame({'A' : ['one', 'one', 'two', 'three'] * 3,'B' : ['A', 'B', 'C'] * 4, 'C' : ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2, 'D' : np.random.randn(12), 'E' : np.random.randn(12)}) # In[319]: df # In[324]: pd.pivot_table(df, values = 'D', index = ['A', 'B'], columns = ['C']) #以 A、B 为行标签,以 C 为列标签将 D 列的值汇总求和 # ## crosstab # In[336]: df # In[335]: pd.crosstab([df.A, df.B], df.C, margins=True) # 以 A、B 为行标签,以 C 为列标签将 D 列的值汇总求个数 # In[338]: pd.crosstab([df.A, df.B], df.C, margins=False) # 以 A、B 为行标签,以 C 为列标签将 D 列的值汇总求个数 # # 时间序列分析 # pandas 提供 to_datetime 方法将代表时间的字符转化为 Timestamp 对象: # In[339]: s = '2013-09-16 21:00:00' ts = pd.to_datetime(s) # In[340]: ts # 有时我们需要处理时区问题: # In[342]: ts=pd.to_datetime(s,utc=True).tz_convert('Asia/Shanghai') # In[343]: ts # 构建时间序列: # In[345]: rng = pd.date_range('1/1/2012', periods=5, freq='M') ts = pd.Series(np.random.randn(len(rng)), index=rng) # In[346]: rng # In[347]: ts # Pandas 提供 resample 方法对时间序列的时间粒度进行调整: # In[349]: ts_h=ts.resample('H').count() # M,5Min,1s # 以上是将时间序列调整为小时,还可以支持月(M),分钟(Min)甚至秒(s)等。 # In[351]: ts_h.head() # In[353]: type(ts_h) # # 参考网站 # # - [Cloga 的互联网笔记 ](http://cloga.info/python/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6/2013/09/17/pandasintro)大神~ # - [Python For Data Analysis 0.1](http://pda.readthedocs.io/en/latest/chp5.html) # In[ ]: