#!/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[ ]: