利用Python进行数据分析 学习笔记

import os
os.getcwd() 获得工作目录, 如使用相对路径,是相对于这个工作目录的路劲
import sys
sys.path.append() 这个是增加引用,或引入文件的路径
In [28]: path='book/ch02/usagov_bitly_data2012-03-16-1331923249.txt'
In [29]: open(path).readline()
json 模块, 可以将json字符串(web数据格式)转换成python 字典对象
In [35]: import json


In [36]: records=[json.loads(line) for line in open(path)]


In [37]: records[0]
type(records) 查看对象类型
isinstance(records,list)


time_zones=[rec['tz'] for rec in records if 'tz' in rec]  因为有的rec里面没有tz 会报key error,所以要有if 


In [45]: from collections import defaultdict


In [46]: def get_counts2(sequence):
    ...:     counts=defaultdict(int)
    ...:     for x in sequence:
    ...:         counts[x]+=1
    ...:     return counts    字典设置默认值


def top_counts(count_dict, n=10):
    ...:     value_key_pairs=[(count,tz) for tz, count in count_dict.items()] 注意 tz, count的次序和代表的含义
    ...:     value_key_pairs.sort()
    ...:     return value_key_pairs[-n:]  获得前10


In [60]: from collections import Counter
In [61]: counts=Counter(time_zones)
In [62]: counts.most_common(10)    使用简便的方法
 from pandas import DataFrame, Series
 import pandas as pd; import numpy as np
  frame=DataFrame(records)
  tz_counts=frame['tz'].value_counts()


In [79]: clean_tz=frame['tz'].fillna('Missing')  fillna换掉缺失值(NA)


In [80]: clean_tz[clean_tz=='']='Unknown'


In [81]: tz_counts=clean_tz.value_counts()


In [82]: tz_counts[:10]
ipython --pylab 打开ipython的同时打开pylab
tz_counts[:10].plot(kind='barh',rot=0) 用pylab画图
 results=Series([x.split()[0] for x in frame.a.dropna()])
cframe=frame[frame.a.notnull()]  移除空
In [23]: operating_system=np.where(cframe['a'].str.contains('Windows'),'Windows','Not Windows')
In [24]: by_tz_os=cframe.groupby(['tz',operating_system])  分组
In [25]: agg_counts=by_tz_os.size().unstack().fillna(0)
In [27]: indexer=agg_counts.sum(1).argsort()
count_subset.plot(kind='barh',stacked=True)


In [31]: import pandas as pd  
In [32]: unames=['user_id','gender','age','occupation','zip']
users=pd.read_table('book\ch02\movielens\users.dat',sep='::',header=None,names=unames)
data=pd.merge(pd.merge(ratings,users),movies)  合并
mean_ratings=data.pivot_table('rating',cols='gender',aggfunc='mean')
rating_std_by_title=data.groupby('title')['rating'].std()  分组并计算标准差
rating_std_by-title=rating_std_by_title.ix[active_titles] 过滤
rating_std_by_title.order(ascendgin=False)[:10]




names1880=pd.read_csv('book/ch02/names/yob1880.txt',names=['name','sex','births']) 导入数据
names1880.groupby('sex').births.sum()  分组求和




In [66]: pieces=[]          批量处理表
In [67]: columns=['name','sex','births']
In [68]: for year in years:
    ...:     path='book/ch02/names/yob%d.txt' % year
    ...:     frame=pd.read_csv(path,names=columns)
    ...:     frame['year']=year
    ...:     pieces.append(frame)


 names=pd.concat(pieces,ignore_index=True)  整合到单个datafrome里面
In [77]: total_births=names.pivot_table('births',index='year',columns='sex',aggfunc=sum)  图表
total_births.plot(title='Total births by sex and year')


def add_prop(group):
    ...:     births=group.births.astype(float)
    ...:     group['prop']=births/births.sum()
    ...:     return group
    ...:


In [80]: names=names.groupby(['year','sex']).apply(add_prop)
 np.allclose(names.groupby(['year','sex']).prop.sum(),1)  检查是否等于1
subset.plot(subplots=True,figsize=(12,10),grid=False,title="number of births per year")
subset=total_births[['John', 'Harry','Mary','Marilyn']] 注意这种写法是选择了一个列表, 如果不用列表的话可用切片,一个[报错
prop_cumsum=df.sort_index(by='prop').prop.cumsum()
get_last_letter=lambda x:x[-1] 取出最后一个字母
last_letters=names.name.map(get_last_letter)
import matplotlib.pyplot as plt
fig,axes=plt.subplots(2,1,figsize(10,8))
letter_prop['M'].plot(kind='bar',rot=0,ax=axes[0],title='Male')
mask=np.array(['lesl' in x.lower() for x in all_names])






ipython:  一种互交式计算和开发环境
from numpy.random import randn
data={i:randn() for i in range(7)}
ipython 中按下tab 出来方法和属性, 但会隐藏拿下以下划线开头的方法和属性。但是如果输入一个下划线,然后按tab可以看到
在变量前面或后面加上问好,就可以把变量的通用信息显示出来
tab也可识别路径,注意路径后带/  如boo_scripts/<tab>
 np.*load*? 通配符
在Ipython中,所有文件都可通过%run命令当作python程序来运行
按下Crtl+C 终止代码
%paste %cpaste 粘贴剪贴板的内容 
ipython 使用%作为魔术命令,比如%xmode,  %timeit np.dot(a,a) 计算时间, %reset? %pdb 发生异常后进入调试, % who 等等
安装了pyQt或Pyside后, 启动 ipython qtconsole  --pylab=inline
ipython --pylab 启动matplotlib
Crtl+p crtl+R  搜索
ipython 把最近的两个输出结果分别保存在_(一个下划线)和__(两个下滑线)中
输入的文本被保存在_iX 的变量中, 其中X是输入的行号 _i27
%logstart 开始记录日志
ipython 和系统的shell结合很紧密
以!开头的命令行表示气候的所有内容需要在系统shell中执行, 还可以将shell命令的控制台输出存放的变量
!cmd, 
%debug 在发生异常后立即写入  %pdb 命令可以让Ipython在出现异常之后自动条用调试器, 注意在pdb 中使用u, p等


调试器还可以为代码开发工作提供帮助,尤其是当你要设置断点或对函数/脚本进行但不调试以查看各条语句的执行情况是, 使用-d选项的%run 
run -d cho3/ipython_bug.py
ipython 调试命令:b, s, n, u, a, d l 等
测试代码执行时间 %time, %timeit 相比前面产生一个非常精确的平均执行时间。


%time method1=[x for x in strings if x.startswith('foo')]
基本性能分析:%prun 和%run -p  cProfile模块
python -m cProfile cprof_example.py
%prun 的格式和cProfile差不多, 但是它分析的是Python语句而不是整个.py文件
逐行分析函数性能, %Iprun 使用line_profile的小型库
%lprun -f add_and_sum add_and_sum(x,y)
在ipython中, 
import some_lib
reload(some_lib)  防止在import some_lib后出现some_lib文件变化修改。使用此格式。 dreload:递归加载


def main():
  x=6
  y=7.5
  result=x+y


if __name__=='__main__':
   main()


在Ipython中访问不到main函数定义的对象, 好点的办法是直接在该模块的全区命名空间中执行main中的代码, 代码放在'__main__‘:快中
当运行%run的时候,就可以看到对象了
Ipython会获取__repr__方法返回的字符串




Numpy基础: 数组和矢量计算
 data=np.array([[1,2,3,4],[3,4,5,6,]])
In [16]: data.shape  表示维度大小的元组
Out[16]: (2, 4)
In [17]: data.dtype  表示对象类型、
Out[17]: dtype('int32')
ndarray是一个通用的同构数据多维容器
In [20]: data1=[6,7.5,8,0,1]
In [21]: arr1=np.array(data1)
嵌套序列将会被转换为一个多维数组
In [23]: data2=[[1,2,3,4],[5,6,7,8]]
In [24]: arr2=np.array(data2)
In [25]: arr2.shape
Out[25]: (2, 4)
In [26]: arr2.ndim
Out[26]: 2
除非显示说明,np.array会尝试为新建的这个数组推断出一个较为适合的数据类型, 数据类型保存在一个特殊的dtype中
 np.zeros(10)  创建为零的数组
 np.zeros((3,6))
np.empty((2,3,4))创建没有任何值的数组,其实里面是任意值
 np.ones((2,3)) 创建值为1的数组
arange是PYthon内置函数range的数组版
np.arange(15)
In [37]: arr1=np.array([1,2,3],dtype=np.float64)  指定数据类型
可以通过ndarray的astype方法显式的转换类型
In [38]: arr=np.array([1,2,3,4,5])
In [39]: arr.dtype
Out[39]: dtype('int32')
In [40]: float_arr=arr.astype(np.float64)
In [41]: float_arr.dtype
Out[41]: dtype('float64')
In [42]: float_arr
Out[42]: array([ 1.,  2.,  3.,  4.,  5.])
dtype还有如下用法
In [43]: int_array=np.arange(10)
In [44]: calibers=np.array([.22,.270,.357,.380,.44,.50], dtype=np.float64)
In [46]: int_array.astype(calibers.dtype)
Out[46]: array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])
empty_uint32=np.empty(8,dtype='u4') 这种用法
数组很重要,因为它是你不用编写循环即可对数据执行批量运算,大小不同的数组之间运算叫做广播
In [54]: arr=np.arange(10)
In [58]: arr[5:8]=12
In [59]: arr
Out[59]: array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])
In [60]: arr_slice=arr[5:8]
In [61]: arr_slice
Out[61]: array([12, 12, 12])
In [62]: arr_slice[1]=12345
In [63]: arr
Out[63]: array([    0,     1,     2,     3,     4,    12, 12345,    12,     8,     9])  数组切片是原始数组的试图,这意味着数组不会被复制,视图上的任何修改都会直接反映到源数据组上
如想想要得到副本而非视图,需要复制arr[5:8].copy()
In [64]: arr2d=np.array([[1,2,3],[4,5,6],[7,8,9]])
In [65]: arr2d[2]
Out[65]: array([7, 8, 9])
In [66]: arr2d[2][1]  数组的索引
Out[66]: 8             


切片索引
In [67]: arr2d=np.array([[1,2,3],[4,5,6],[7,8,9]])


In [68]: arr2d
Out[68]:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])


In [69]: arr2d[1]
Out[69]: array([4, 5, 6])


In [70]: arr2d[:2]
Out[70]:
array([[1, 2, 3],
       [4, 5, 6]])


In [71]: arr2d[:3]
Out[71]:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])


In [72]: arr2d[:2,1:]
Out[72]:
array([[2, 3],
       [5, 6]])


In [73]: arr2d[:2,:2]
Out[73]:
array([[1, 2],
       [4, 5]]) 
降低维度
In [74]: arr2d[1,:2] 注意   :2 不包含2, 1: 包含1
Out[74]: array([4, 5])


布尔型索引:
 names=np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])


In [76]: names
Out[76]:
array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'],
      dtype='|S4')


In [79]: data=np.random.randn(7,4)


In [80]: names=='Bob'
Out[80]: array([ True, False, False,  True, False, False, False], dtype=bool)


In [82]: data[names=='Bob']  布尔型索引
Out[82]:
array([[-0.48887923, -1.24969215, -1.52086376, -0.2070552 ],
       [-0.69952345,  0.8816831 , -1.23041435, -0.14274545]])
In [83]: mask=(names=='Bob')|(names=='Will')


In [84]: data[mask]
Out[84]:
array([[-0.48887923, -1.24969215, -1.52086376, -0.2070552 ],
       [ 0.3888584 , -0.93839398, -0.63899487,  0.77611545],
       [-0.69952345,  0.8816831 , -1.23041435, -0.14274545],
       [-0.72619138, -1.21360294,  0.8742219 , -0.82865351]])
Python关键字and和or在布尔型数组中无效
data[data<0]=0
data[names!='Joe']=7
花式索引: arr[[4,3,0,6]]
In [90]: arr=np.arange(32).reshape(8,4)


In [91]: arr
Out[91]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23],
       [24, 25, 26, 27],
       [28, 29, 30, 31]])


In [92]: arr[[1,5,7,2],[0,3,1,2]]   注意选出的是单个元素
Out[92]: array([ 4, 23, 29, 10])


In [94]: arr[[1,5,7,2]][:,[0,3,1,2]]  选出的是方形元素
Out[94]:
array([[ 4,  7,  5,  6],
       [20, 23, 21, 22],
       [28, 31, 29, 30],
       [ 8, 11,  9, 10]])
使用np.ix_函数,它可以将两个一维整数数组转换为一个用于选取方形区域的索引器
In [95]: arr[np.ix_([1,5,7,2],[0,3,1,2])]
Out[95]:
array([[ 4,  7,  5,  6],
       [20, 23, 21, 22],
       [28, 31, 29, 30],
       [ 8, 11,  9, 10]])
花式索引跟切片不一样,它总是将数据复制到新数组中。
转置是重塑的一种特殊形式,它返回的是源数据的视图
arr=np.arange(15).reshape((3,5))
arr.T
np.dot计算矩阵的内积 XTX
np.dot(arr.T,arr)
对于高维数组,transpose需要得到一个由轴编号组成的元组才能对这些轴进行转置
In [96]: arr=np.arange(16).reshape((2,2,4))
通用函数
np.sqrt(arr)
np.exp(arr)
np.maximum(x,y)
isifinite, isinf


In [97]: arr
Out[97]:
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],


       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])


In [98]: arr.transpose((1,0,2))
Out[98]:
array([[[ 0,  1,  2,  3],
        [ 8,  9, 10, 11]],


       [[ 4,  5,  6,  7],
        [12, 13, 14, 15]]])


swapaxes只接受一个轴编号:返回的也是视图


利用数组进行数据处理
用数组表达式代替循环的做法, 通常被称为矢量化,


In [119]: points1=np.arange(-5,5,1)


In [120]: points2=np.arange(-3,3,1)


In [121]: xs,ys=np.meshgrid(points1,points2)   注意meshgrid的用法, 产生两个m*n的矩阵,一个按照行排列,一个按照列排列


In [122]: xs
Out[122]:
array([[-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4]])


In [123]: ys
Out[123]:
array([[-3, -3, -3, -3, -3, -3, -3, -3, -3, -3],
       [-2, -2, -2, -2, -2, -2, -2, -2, -2, -2],
       [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1],
       [ 2,  2,  2,  2,  2,  2,  2,  2,  2,  2]])


In [128]: import matplotlib.pyplot as plt


In [129]: z=np.sqrt(xs**2+ys**2)


In [131]: plt.imshow(z,cmap=plt.cm.gray);plt.colorbar()
Out[131]: <matplotlib.colorbar.Colorbar object at 0x07ED0790>


In [132]: plt.title("image plot of $\sqrt{x^2+y^2}$ for a grid of values")
Out[132]: <matplotlib.text.Text object at 0x07E343B0>
将条件逻辑表达式作为数据运算
numpy.where函数是三元表达式x if condition else y的矢量化版本, 
In [133]: xarr=np.array([1.1,1.2,1.3,1.4,1.5])


In [134]: yarr=np.array([2.1,2.2,2.3,2.4,2.5])


In [135]: cond=np.array([True,False, True, True, False])


In [136]: result=[(x if c else y) for x,y,c in zip(xarr,yarr,cond)]


In [137]: result
Out[137]: [1.1000000000000001, 2.2000000000000002, 1.3, 1.3999999999999999, 2.5]


In [138]: result=np.where(cond,xarr,yarr)


In [139]: result
Out[139]: array([ 1.1,  2.2,  1.3,  1.4,  2.5])


np.where 的第二和第三个参数可以是标量
np.where(arr>0,2,arr)
np.where(cond1 & cond2, 0, np.where(cond1,1, np.where(cond2,2,3)))
布尔值在计算过程中可以被当作0或1处理,因此可以写成如下数据
result=1*(cond1-cond2)+2*(cond2 & -cond1) +3* -(cond1|cond2)
mean和sum这类的函数可以接受一个axis参数(用于计算该周
In [144]: arr=np.array([[1,2,3,2,2],[4,3,5,6,7]])
In [145]: arr.mean(axis=1) 按行
Out[145]: array([ 2.,  5.])
In [146]: arr
Out[146]:
array([[1, 2, 3, 2, 2],
       [4, 3, 5, 6, 7]])
In [148]: arr.mean(0)  按列
Out[148]: array([ 2.5,  2.5,  4. ,  4. ,  4.5])
cumsum和cumprod之类的方法则不聚合,产生一个由中间结果组成的数组
In [150]: arr.cumsum(0)
Out[150]:
array([[1, 2, 3, 2, 2],
       [5, 5, 8, 8, 9]])


In [151]: arr.cumprod(0)
Out[151]:
array([[ 1,  2,  3,  2,  2],
       [ 4,  6, 15, 12, 14]])


In [152]: arr.cumprod(axis=1)
Out[152]:
array([[   1,    2,    6,   12,   24],
       [   4,   12,   60,  360, 2520]])


In [153]: arr.cumprod(axis=0)
Out[153]:
array([[ 1,  2,  3,  2,  2],
       [ 4,  6, 15, 12, 14]])


argmin, argmax分别为最大和最小元素的索引
布尔型数组的方法, 布尔型强制转换为1或0
arr=randn(100)
(arr>0).sum()
bools=nparray([False,Falise, True,False])
bools.any(), bools.all() any和all
排序:
arr=randn(8)
arr.sort()
多维数组可以在任何一个轴上进行排序,,只需将轴号传给sort
np.sort返回的是数组的已经排序的副本,本人会修改数组本身
In [163]: arr=np.random.randn(1000)


In [164]: arr.sort()


In [165]: arr[int(0.05*len(arr))]
Out[165]: -1.567756069649612 取5分位数


np.unique用于找出数组中的唯一值缤纷返回已排序的结果
np.unique(names) 和它等价的Pyton 代码
sorted(set(names))
np.in1用于测试一个数组中的值在另一个数组中的成员资格,返回一个布尔数组
np.save('some_array',arr) 保存为.npy文件
np.load('some_array.npy')
np.savez('array_archive.npz',a=arr,b=arr) 保存为压缩文件, 将数组以关键字参数的形式传入即可
arch=np.load('array_archive.npz')
arch['b']
!type book\ch04\array_ex.txt  Window下打出文本
 arr=np.loadtxt('book\ch04\array_ex.txt',delimiter=',')  导入文件
genfromtxt 和loadtxt差不多, 只不过面向结构化数组和缺失数据处理


线性代数
In [186]: x
Out[186]:
array([[1, 2, 3],
       [2, 3, 4]])


In [187]: y
Out[187]:
array([[1, 2],
       [3, 4],
       [5, 6]])


In [188]: np.dot(x,y)  矩阵乘法
Out[188]:
array([[22, 28],
       [31, 40]])


numpy.linalg中有一组标准的矩阵运算函数
In [195]: from numpy.linalg import inv, qr


In [196]: x
Out[196]:
array([[1, 2, 3],
       [2, 3, 4]])


In [197]: x.T
Out[197]:
array([[1, 2],
       [2, 3],
       [3, 4]])


In [198]: mat=x.T.dot(x)


In [199]: mat
Out[199]:
array([[ 5,  8, 11],
       [ 8, 13, 18],
       [11, 18, 25]])


In [200]: inv(mat)
Out[200]:
array([[ -2.25179981e+15,   4.50359963e+15,  -2.25179981e+15],
       [  4.50359963e+15,  -9.00719925e+15,   4.50359963e+15],
       [ -2.25179981e+15,   4.50359963e+15,  -2.25179981e+15]])


随机数生成
sample=np.random.normal(size=(4,4))


 import random


In [208]: postition=0


In [210]: walk=[postition]


In [211]: steps=1000


In [212]: for i in xrange(steps):
     ...:     step=1 if random.randint(0,1) else -1    注意写法
     ...:     postition+=step
     ...:     walk.append(postition)


In [221]: nwalks=5000


In [222]: nsteps=1000


In [223]: draws=np.random.randint(0,2,size=(nwalks,nsteps))


In [224]: steps=np.where(draws>0,1,-1)


In [225]: walks=steps.cumsum(1)


In [226]: walks
Out[226]:
array([[  1,   0,   1, ...,  74,  75,  74],
       [  1,   0,  -1, ...,  -4,  -5,  -4],
       [ -1,  -2,  -1, ..., -40, -41, -42],
       ...,
       [  1,   0,  -1, ...,  -2,  -3,  -4],
       [ -1,   0,   1, ...,  50,  51,  52],
       [ -1,   0,   1, ...,  18,  17,  16]])
In [227]: hits30=(np.abs(walks)>30).any(1)


In [228]: hits30
Out[228]: array([ True,  True,  True, ..., False,  True,  True], dtype=bool)


In [229]: hits30.sum()
Out[229]: 3264




Pandas 入门
pandas 数据结构
Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)及一组与之相关的数据标签(索引)组成。
In [231]: from pandas import Series, DataFrame


In [232]: import pandas as pd


In [233]: obj=Series([4,7,-5,3])


In [234]: obj
Out[234]:
0    4
1    7
2   -5
3    3
dtype: int64
In [235]: obj.values
Out[235]: array([ 4,  7, -5,  3], dtype=int64)


In [236]: obj.index
Out[236]: RangeIndex(start=0, stop=4, step=1)
In [239]: obj2=Series([4,7,-5,3],index=['d','b','a','c'])


In [240]: obj2
Out[240]:
d    4
b    7
a   -5
c    3
dtype: int64


Numpy数组运算都会保留索引与值之间的连接, 注意Series是由Numpy类型和索引组成的
Series看成是一个定长的有序字典,因为它是索引值的一个映射。
In [242]: 'b' in obj2
Out[242]: True
因此也可以用字典来创建Series 
In [243]: sdata={'Ohio':35000,'Texas':71000,'Oregon':16000,'Utah':5000}
In [244]: obj3=Series(sdata)
In [246]: obj3
Out[246]:
Ohio      35000
Oregon    16000
Texas     71000
Utah       5000
dtype: int64
如果只传入一个字典,则Series中的索引就是原字典的键
In [253]: states=['Ohio','Oregon','JJJ']


In [254]: obj4=Series(sdata,index=states)


In [255]: obj4
Out[255]:
Ohio      35000.0
Oregon    16000.0
JJJ           NaN
dtype: float64 JJJ由于没有在字典中找到
pandas中的isnull和notnull用于检测缺失值
In [256]: pd.isnull(obj4)
Out[256]:
Ohio      False
Oregon    False
JJJ        True
dtype: bool


In [257]: pd.notnull(obj4)
Out[257]:
Ohio       True
Oregon     True
JJJ       False
dtype: bool
Series 会自动补全不同索引数据
In [258]: obj3
Out[258]:
Ohio      35000
Oregon    16000
Texas     71000
Utah       5000
dtype: int64


In [259]: obj4
Out[259]:
Ohio      35000.0
Oregon    16000.0
JJJ           NaN
dtype: float64


In [260]: obj3+obj4
Out[260]:
JJJ           NaN
Ohio      70000.0
Oregon    32000.0
Texas         NaN
Utah          NaN
dtype: float64
Series对象本身及其索引都有一个name属性
Series的索引可以通过赋值的方式就地修改
DataFrame既有行索引也有列索引,它可以被看作由Series组成的字典(共同一个索引)跟其它类似的数据结构相比(R data.frame)DataFrame中面向行和列的操作基本是平行的
,其实DataFrame中的数据是以一个或多个二维块存放的(不是列表,字典或一维结构)
In [4]: data={'state':['Ohio','Ohio','Ohio','Nevada','Nevada'],
   ...: 'year':[2000,2001,2002,2001,2002],
   ...: 'pop':[1.5,1.7,3.6,2.4,2.9]}


In [5]: frame=DataFrame(data)


In [6]: frame
Out[6]:
   pop   state  year
0  1.5    Ohio  2000
1  1.7    Ohio  2001
2  3.6    Ohio  2002
3  2.4  Nevada  2001
4  2.9  Nevada  2002
注意到DataFrame自动增加了索引,平且列被排序
如果指定了列序列, 则DataFrame的列就会按照指定顺序进行排列
In [7]: DataFrame(data,columns=['year','state','pop'])
Out[7]:
   year   state  pop
0  2000    Ohio  1.5
1  2001    Ohio  1.7
2  2002    Ohio  3.6
3  2001  Nevada  2.4
4  2002  Nevada  2.9
和Series一样,如果传入的列在数据中找不到,就会产生NA
In [8]: frame2=DataFrame(data,columns=['year','state','pop','debt'],
   ...:                index=['one','two','three','four','five'])


In [9]: frame2
Out[9]:
       year   state  pop debt
one    2000    Ohio  1.5  NaN
two    2001    Ohio  1.7  NaN
three  2002    Ohio  3.6  NaN
four   2001  Nevada  2.4  NaN
five   2002  Nevada  2.9  NaN


In [11]: frame2['state']
Out[11]:
one        Ohio
two        Ohio
three      Ohio
four     Nevada
five     Nevada
Name: state, dtype: object


In [12]: frame2.year
Out[12]:
one      2000
two      2001
three    2002
four     2001
five     2002
Name: year, dtype: int64


In [14]: frame2.ix['three']
Out[14]:
year     2002
state    Ohio
pop       3.6
debt      NaN
Name: three, dtype: object


In [15]: frame2['debt']=np.arange(5.)  赋值


In [16]: frame2
Out[16]:
       year   state  pop  debt
one    2000    Ohio  1.5   0.0
two    2001    Ohio  1.7   1.0
three  2002    Ohio  3.6   2.0
four   2001  Nevada  2.4   3.0
five   2002  Nevada  2.9   4.0


del frame2['eastern'] 删除列
通过索引方式返回的列只是数据的视图而已


In [24]: pop={'Nevada':{2001:2.4,2002:2.9},  
    ...: 'Ohio':{2000:1.5,2001:1.7,2002:3.6}}  嵌套字典,外层是列名字,内层是索引
In [25]: frame3=DataFrame(pop)


In [26]: frame3
Out[26]:
      Nevada  Ohio
2000     NaN   1.5
2001     2.4   1.7
2002     2.9   3.6


In [27]: frame3.T
Out[27]:
        2000  2001  2002
Nevada   NaN   2.4   2.9
Ohio     1.5   1.7   3.6
如果设置了DataFrame的index和columns的name属性,信息也会显示出来
In [28]: frame3.index.name='state'


In [29]: frame3.columns.name='year'


In [30]: frame3
Out[30]:
year   Nevada  Ohio
state
2000      NaN   1.5
2001      2.4   1.7
2002      2.9   3.6


In [31]: frame3.values   注意以数组的方式表示
Out[31]:
array([[ nan,  1.5],
       [ 2.4,  1.7],
       [ 2.9,  3.6]])
pandas 的索引对象负责管理轴标签和其他元数据(比如轴名称), index对象是不可修改的。index的功能也类似一个固定大小的集合
In [38]: 'Ohio' in frame3.columns
Out[38]: True


In [39]: 2002 in frame3.index
Out[39]: True
每个索引都有一些方法和属性,用于设置逻辑等。 append。 diff。 delect(删除索引处的元素)insert,unique
pandas重要的方法,reindex,从新索引
In [45]: obj2
Out[45]:
a    0.0
b    1.0
c    2.0
d    NaN
dtype: float64
fill_value=0 填充
使用ffill可实现向前填充
使用colums关键字可重新索引列
也可同时进行行和列进行重新索引,而插值则智能按行应用(即轴0)
frame.reindex(index=['a','b','c','d'],method='ffill',columns=states)
利用ix的标签索引功能,重索引任务可变得更加简洁
drop方法返回的是一个指定轴上删除了指定值的新对象


In [46]: obj=Series(np.arange(5),index=['a','b','c','d','e'])


In [47]: new_ojb=obj.drop(['c','e'])


In [48]: new_ojb
Out[48]:
a    0
b    1
d    3
dtype: int32
对于DataFrame, 可以删除任意轴上的索引值
data.drop(['two','four'],axis=1)
过滤 obj[obj<2] Series 的索引和numpy一样,只不过索引值不只是整数
利用标签的切片用算与普通的Python切片运算不同,其末端是包含的,即封闭的
通过切片进行筛选
data[data['three']>5]
data.ix[['Colorado','Utah'],[3,0,1]]  通过索引字段产生子集
obj[val] 选取列 或一组列
obj.ix[val]选取行或一组行
obj.ix[val1,val2] 同时选取行和列
DataFrame加减运算时, 对齐操作发生在列上和行上同时发生
In [50]: df1=DataFrame(np.arange(12).reshape((3,4)),columns=list('abcd'))


In [51]: df2 =DataFrame(np.arange(20).reshape((4,5)),columns=list('abcde'))


In [52]: df1+df2
Out[52]:
      a     b     c     d   e
0   0.0   2.0   4.0   6.0 NaN
1   9.0  11.0  13.0  15.0 NaN
2  18.0  20.0  22.0  24.0 NaN
3   NaN   NaN   NaN   NaN NaN


In [53]: df1.add(df2,fill_value=0)  填充
Out[53]:
      a     b     c     d     e
0   0.0   2.0   4.0   6.0   4.0
1   9.0  11.0  13.0  15.0   9.0
2  18.0  20.0  22.0  24.0  14.0
3  15.0  16.0  17.0  18.0  19.0
计算一个二维数组与某行之间的差, 广播性质
如果希望匹配行且在列上广播,必须使用算数运算方法
frame.sub(series3,axis=0)
Numpy的ufuncs也可用于操作pandas对象
In [54]: frame=DataFrame(np.random.randn(4,3),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon'])


In [55]: np.abs(frame)
Out[55]:
               b         d         e
Utah    0.997062  0.711923  1.695475
Ohio    0.227092  0.930829  0.470029
Texas   0.282804  0.036711  0.961498
Oregon  1.199630  0.313844  0.383192


In [56]: f=lambda x: x.max()-x.min()


In [57]: frame.apply(f,axis=1) apply函数
Out[57]:
Utah      2.692536
Ohio      1.400858
Texas     0.924787
Oregon    1.513474
dtype: float64


In [58]: def f(x):
    ...:     return Series([x.min(),x.max()],index=['min','max'])
    ...:


In [59]: frame.apply(f)
Out[59]:
            b         d         e
min -0.997062 -0.313844 -0.961498
max  1.199630  0.930829  1.695475


In [60]: format=lambda x: '%.2f' % x


In [61]: frame.applymap(format)  因为Seriesy已经有了map方法,这里用applymap
Out[61]:
            b      d      e
Utah    -1.00   0.71   1.70
Ohio     0.23   0.93  -0.47
Texas   -0.28  -0.04  -0.96
Oregon   1.20  -0.31   0.38




排名:
obj.sort_index()
frame.sort_index(axis=1,ascending=False) 在任意轴上进行
对于Series,可以用order obj.order()
frame.sort_index(by=['a','b'])按照两列排序
rank方法,排名,
In [62]: obj=Series([1,-3,7,3])


In [63]: obj.rank()   注意有很多参数
Out[63]:
0    2.0
1    1.0
2    4.0
3    3.0
dtype: float64
In [65]: obj.rank(method='first')
Out[65]:
0    2.0
1    1.0
2    4.0
3    3.0
dtype: float64
带有重复值的轴索引
如果某个索引对应多个值,则返回一个Series, 如果对应单个值,则返回一个标量, DataFrame 同理
df.mean(axis=1,skipna=False) 排除整个贴片  都是NA 
idxmin, idxmax 返回的是间接统计(达到最大值和最小值的索引)
一些方法是累计的,比如df.cumsum()
df.describe() 一次性产生多个汇总统计量
argmin,argmax 计算能够获得到最小值和最大值的索引位置(整数)
idxmin,idxmax 计算能够获取到最小值和最大值的索引值
corr, cov用于计算协方差和相关系数
data.corrwith(returns.IBM) corrwith用于计算其列或行跟另一个Series或DataFrame之间的相关系数
uniques=obj.unique(0
obj.value_counts()
pa.value_counts(obj.values,sort=False)
mask=obj.isin(['b','c'])
result=data.apply(pd.value_counts).fillna(0)   统计频次
处理缺失数据
NaN, 和Python内的None都当作NA处理
string_data.isnull()
dropna, fillna, isnull
滤除缺失值
data.dropna(), data[data.notnull()]
dat.dropna(axis=1,how='all') 在DataFrame中,丢弃列的方式
另外一个滤除DataFrame行的问题涉及时间序列数据,df.dropna(thresh=3)
填充缺失数据
df.fillna(0)
df.fillna({1:0.5,3:-1}) fillna默认返回新对象,但也可以对现有对象进行修改
_=df.fillna(0,inplace=True)
data.fillna(data.mean()) 用中位数填充
层次化索引
MultiIndex索引
In [72]: data=Series(np.random.randn(10),
    ...: index=[['a','a','a','b','b','b','c','c','d','d'],
    ...: [1,2,3,1,2,3,1,2,2,3]])


In [73]: data
Out[73]:
a  1   -0.684999
   2    1.417506
   3   -0.627559
b  1   -0.774957
   2   -1.936015
   3    0.815245
c  1   -0.611685
   2   -0.333658
d  2    1.470215
   3    1.001355
dtype: float64


In [74]: data.index
Out[74]:
MultiIndex(levels=[[u'a', u'b', u'c', u'd'], [1, 2, 3]],
           labels=[[0, 0, 0, 1, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 1, 2]])
In [78]: data['a':'b'] 此列中和下个面的方式等价
Out[78]:
a  1   -0.684999
   2    1.417506
   3   -0.627559
b  1   -0.774957
   2   -1.936015
   3    0.815245
dtype: float64


In [79]: data[['a','b']]
Out[79]:
a  1   -0.684999
   2    1.417506
   3   -0.627559
b  1   -0.774957
   2   -1.936015
   3    0.815245
dtype: float64


In [80]: data[:,2] 对内层进行选取
Out[80]:
a    1.417506
b   -1.936015
c   -0.333658
d    1.470215
dtype: float64


对于一个DataFrame,每条轴都可以有分层索引
In [81]: frame=DataFrame(np.arange(12).reshape((4,3)),
    ...:       index=[['a','a','b','b'],[1,2,1,2]],
    ...:       columns=[['Ohio','Ohio','Colorado'],['Green','Red','Green']])


In [82]: frame
Out[82]:
     Ohio     Colorado
    Green Red    Green
a 1     0   1        2
  2     3   4        5
b 1     6   7        8
  2     9  10       11


In [83]: frame.index.names=['key1','key2']


In [84]: frame.columns.names=['state','color']


In [85]: frame
Out[85]:
state      Ohio     Colorado
color     Green Red    Green
key1 key2
a    1        0   1        2
     2        3   4        5
b    1        6   7        8
     2        9  10       11


In [86]: frame['Ohio']
Out[86]:
color      Green  Red
key1 key2
a    1         0    1
     2         3    4
b    1         6    7
     2         9   10
swaplevel接受两个级别编号或名称,并返回一个互换了级别的新对象


frame.swaplevel('key1','key2')
frame.swaplevel(0,1).sortlevel(0)


许多对DataFrame和Series的描述和统计汇总都有一个level,它用于指定在某条轴上求和的级别
frame.sum(level='key2')
frame.sum(level='color',axis=1)
DataFrame的set_index函数会将其一个或多个列转换为行索引,默认情况下那些列会从DataFrame移除,但也可以保留下来
并创建一个新的Dataframe
frame2=frame.set_index(['c','d'])
frame.set_index(['c','d'],drop=False)
reset_index的功能跟set_index刚好相反
frame2.reset_index()
整数索引
In [87]: ser=Series(np.arange(3.))


In [88]: ser
Out[88]:
0    0.0
1    1.0
2    2.0
dtype: float64
In [90]: ser[-1] 此时产生错误
In [91]: ser=Series(np.arange(3.),index=['a','b','c'])


In [92]: ser[-1]
Out[92]: 2.0  此时正确运行 注意区分
如果要可靠的、不考虑索引类型的、基于未知的索引,使用Series的igetvalue和DataFrame的irow 和icol方法
ser3.iget_value(2)
面板数据
pdata.ix[:,'6/1/2012',:] ix 到了三位空间
pdata.ix[:,'6/1/2012',:].to_frame() 转为Dataframe
to_panel 转为面板数据
数据加载、储存与文件格式


df=pd.read_csv('book/ch06/ex1.csv')
df=pd.read_table('book/ch06/ex1.csv',sep=',')
In [101]: df=pd.read_table('book/ch06/ex1.csv',sep=',')


In [102]: df=pd.read_csv('book/ch06/ex2.csv',header=None)


In [103]: df=pd.read_csv('book/ch06/ex2.csv',names=['a','b','c','d','message'])


In [104]: df=pd.read_csv('book/ch06/ex2.csv',names=['a','b','c','d','message'],index_col='message')


In [105]: df
Out[105]:
         a   b   c   d
message
hello    1   2   3   4
world    5   6   7   8
foo      9  10  11  12




In [106]: df=pd.read_csv('book/ch06/csv_mindex.csv',index_col=['key1','key2'])  多层次索引


In [107]: df
Out[107]:
           value1  value2
key1 key2
one  a          1       2
     b          3       4
     c          5       6
     d          7       8
two  a          9      10
     b         11      12
     c         13      14
     d         15      16


 result=pd.read_table('book/ch06/ex3.txt',sep='\s+')  使用正则表达式分割


 pd.read_csv('****.csv',skiprows=[0,2,3]) 跳过行


In [123]: result=pd.read_csv('book/ch06/ex5.csv',na_values=4)  把4换成NA


In [124]: result
Out[124]:
  something  a   b     c     d message
0       one  1   2   3.0   NaN     NaN
1       two  5   6   NaN   8.0   world
2     three  9  10  11.0  12.0     foo
In [125]: sentinels={'message':['foo','NA'],'something':['two']}


In [126]: result=pd.read_csv('book/ch06/ex5.csv',na_values=sentinels)


In [127]: result
Out[127]:
  something  a   b     c   d message
0       one  1   2   3.0   4     NaN
1       NaN  5   6   NaN   8   world
2     three  9  10  11.0  12     NaN


In [131]: result=pd.read_csv('book/ch06/ex6.csv',nrows=5)


In [132]: result=pd.read_csv('book/ch06/ex6.csv',chunksize=1000) 按块读取




In [137]: tot=Series([])


In [138]: for piece in chunker:
     ...:     tot=tot.add(piece['key'].value_counts(),fill_value=0)


data.to_csv('***.csv') 文本写到文件
缺失值在输出结果中表示为空字符,可以用其它标志表示
data.to_csv(sys.stdout,na_rep=‘NULL’)
data.to_csv(sys.stdout,index=False,header=False)
手工处理分割符格式
Jason数据
XML和HTML
from lxml.html import parse
from urllib2 import urlopen
from pandas.io.parsers import TextParser
利用lxml.ojbectify 解析xml
读取excel文件
xls_file=pd.ExcelFile('data.xls')
table=xls_file.parse('Sheet1')
使用HTML和 Web API
使用requests包
import requests
url='http:....'
resp=requests.get(url)
respoinse对象的text属性含有GEt请求的内容
import json
data =json.loads(resp.text)
使用数据库
import sqlit3
query="""
   select * from jbe"""
con=sqlit3.connect(':memory:')
存取mongoDB
import pymongo
con=pymongo.connection('localhost',port=27017)
数据规整化:清理、转换、合并 重塑
数据库风格的DataFrame合并
merge 函数 


In [165]: df1=DataFrame({'key':['b','b','a','c','a','a','b'],'data1':range(7)})


In [166]: df2=DataFrame({'key':['a','b','d'],'data2':range(3)})


In [167]: pd.merge(df1,df2,on='key')
Out[167]:
   data1 key  data2
0      0   b      1
1      1   b      1
2      6   b      1
3      2   a      0
4      4   a      0
5      5   a      0


如果两个对象的列名不同,可以进行分别指定
pd.merge(df3,df4,left_on='lkey',right_on='rkey')
默认情况下, merge做的是inner,还可以left, right, outer
pd.merge(df1,df2,how='outer')
要根据多个键进行合并,传入一个由列组成的列表即可
pd.merge(left,right,on=['key1','key2'],how='outer')
注意: 在进行列-列连接时,DataFrame对象中的索引会被丢弃。
pd.merge(left,right,on='key1',suffixes=('_left','_right')
suffixes的作用是多左边的列和右边的列在合并的时候增加字符
DataFrame中的连接键位于索引中,在这种情况下,可以传入left_index=True和right_index
pd.merge(left1,right1,left_on='Key', right=index=Trut)
con.execute(query)
con.commit()
对于层次化索引的数据,必须用列表的形式指明用于合并键的多个列, 对重复索引值的处理和SQL一样。
DataFrame还有一个join实例方法,它能更为方便地实现索引合并,还可以用于合并多个带有相同或相似索引的DataFrame对象
left2.join(right2,how='outer')
pd.merge(lefth, righth,left_on=['key1','key2'], right_index=True)
pd.merge(lefth, righth,left_on=['key1','key2'], right_index=True, how='outer') 结果类似SQL
轴向连接
In [10]: arr=np.arange(12).reshape((3,4))
In [11]: arr
Out[11]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
In [12]: np.concatenate([arr,arr],axis=1)
Out[12]:
array([[ 0,  1,  2,  3,  0,  1,  2,  3],
       [ 4,  5,  6,  7,  4,  5,  6,  7],
       [ 8,  9, 10, 11,  8,  9, 10, 11]])
In [14]: np.concatenate([arr,arr],axis=0)
Out[14]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])


In [15]: s1=Series([0,1],index=['a','b'])


In [16]: s2=Series([2,3,4],index=['c','b','e'])


In [17]: s3=Series([5,6],index=['f','g'])


In [20]: pd.concat([s1,s2,s3],axis=1)
Out[20]:
     0    1    2
a  0.0  NaN  NaN
b  1.0  3.0  NaN
c  NaN  2.0  NaN
e  NaN  4.0  NaN
f  NaN  NaN  5.0
g  NaN  NaN  6.0


s4=pd.concat([s1*5,s3])
pd.concate([s1,s4],axis=1,join='inner')  只显示交集部分
Out[24]:
   0  1
a  0  0
b  1  5
可以通过join_axes指定要在其他轴上使用的索引
In [26]: pd.concat([s1,s4],axis=1,join_axes=[['a','f','g']])
Out[26]:
     0  1
a  0.0  0
f  NaN  5
g  NaN  6


In [27]: result=pd.concat([s1,s2,s3],keys=['one','two','three']) 连接后新的索引


In [28]: result
Out[28]:
one    a    0
       b    1
two    c    2
       b    3
       e    4
three  f    5
       g    6
dtype: int64




如果沿着axis=1对Series进行合并,则keys就会成为DataFrame的列头


In [33]: pd.concat([s1,s2,s3],axis=1,keys=['one','two','three'])
Out[33]:
   one  two  three
a  0.0  NaN    NaN
b  1.0  3.0    NaN
c  NaN  2.0    NaN
e  NaN  4.0    NaN
f  NaN  NaN    5.0
g  NaN  NaN    6.0


同样的逻辑也适用于DataFrame, 如果传入的不是列表而是一个字典,则字典的键就会被当作keys选项的值。
如果传入的不是列表而是一个字典,则字典的键就会被当作keys选项的值
pd.concat({'level1':df1,'level2':df2},axis=1)
 pd.concat([df1,df2],axis=1,keys=['level1','level2'],names=['upper','lower']) names表明了索引的层次


合并重叠数据
In [35]: a=Series([np.nan,2.5,np.nan,3.5,4.5,np.nan],index=['f','e','d','c','b','a'])
In [37]: b=Series(np.arange(len(a),dtype=np.float64),index=['f','e','d','c','b','a'])


In [46]: np.where(pd.isnull(a),b,a)
Out[46]: array([ 0. ,  2.5,  2. ,  3.5,  4.5,  nan])


In [51]: a[:].combine_first(b[:])     Series中的combine_first实现上述功能,而且能对齐
Out[51]:
f    0.0
e    2.5
d    2.0
c    3.5
b    4.5
a    NaN
dtype: float64
Data Frame, combine_first自然也会在列上做同样的操作, 可以看作用参数对象中的数据为调用者对象的缺失数据‘打补丁’


重塑和轴向旋转
stack 将数据的列“旋转”为行
unstack 将数据的行 “旋转”为列
默认情况下, unstack操作的是最内层(stack也如此),传入分层级别或编号可对其它级别进行unstack操作。
result.unstack(0) 
result.unstack('state')
如果不是所有级别的值都能在分组中找到的话, unstack操作会引入缺失值,同样stack会过滤掉缺失值
DataFrame进行unstack操作时,作为旋转轴的级别将会成为结果中最低级别
将长格式转换为宽格式
ldata如下:
data    item         value
1980    realgdp      2710.349
1981    infi         0.000000
可以通过DataFrame的pivot方法转换为 date列中的时间值作为索引,不同的item形成一列
pivoted=ldata.pivot('date','item','value')
前两个参数值分别作用行和索引的列名,最后一个参数值填充DataFrame的数据列的列名
如果忽略最后一个参数,得到有层次化的列
pivot其实只是一个快捷方式: 用set_index创建层次化索引,再用unstack重塑
unstacked=ldata.set_index(['date','item']).unstack('item')
移除重复值
 data.drop_duplicates()
 data.drop_duplicates(['k1'])
利用函数或映射进行数据转换
In [58]: data=DataFrame({'food':['bacon','pulled pork','bacon','Pastrami','corned beef','Bacon','pastrami','honey ham'
    ...: ,'nova lox'],'ounces':[4,3,12,6,7.5,8,3,5,6]})


In [59]: data
Out[59]:
          food  ounces
0        bacon     4.0
1  pulled pork     3.0
2        bacon    12.0
3     Pastrami     6.0
4  corned beef     7.5
5        Bacon     8.0
6     pastrami     3.0
7    honey ham     5.0
8     nova lox     6.0


In [62]: data['animal']=data['food'].map(str.lower).map(meat_to_animal)


In [63]: data
Out[63]:
          food  ounces  animal
0        bacon     4.0     pig
1  pulled pork     3.0     pig
2        bacon    12.0     pig
3     Pastrami     6.0     cow
4  corned beef     7.5     cow
5        Bacon     8.0     pig
6     pastrami     3.0     cow
7    honey ham     5.0     pig
8     nova lox     6.0  salmon


meat_to_animal={'bacon':'pig','pulled pork':'pig','pastrami':'cow','corned beef':'cow','honey ham':'pig','nov
    ...: a lox':'salmon'}
In [62]: data['animal']=data['food'].map(str.lower).map(meat_to_animal)


In [63]: data
Out[63]:
          food  ounces  animal
0        bacon     4.0     pig
1  pulled pork     3.0     pig
2        bacon    12.0     pig
3     Pastrami     6.0     cow
4  corned beef     7.5     cow
5        Bacon     8.0     pig
6     pastrami     3.0     cow
7    honey ham     5.0     pig
8     nova lox     6.0  salmon


data['food'].map(lambda x:meat_to_animal[x.lower()])


替换值
data.replace(-999,np.nan)
data.replace([-999,-1000],np.nan)
data.replace([-999,-1000],[np.nan,0]) 替换不同的值
data.replace({-999:np.nan,1000:0}) 也可传入数组
重命名轴索引
DataFrame中 Map
data.index.map(str.upper)
data.index=data.index.map(str.upper)
data.rename(index=str.title,columns=str.upper)
离散化和面元划分
cats=pd.cuts(ages,bins)
pandas返回的是一个特殊的Categorical对象,
cats.labels
cats.levels
pd.cut(ages,[18,26,36,61,100],right=False)
pd.cut(ages,bins,labels=group_names)
如果向cut传入的是面元的数据而不是确切的面元边界,则会根据数据的最小值和最大值计算等长绵远
pd.cut(data,4,percisiion=2)
cats=pd.qcut(data,4) qcut使用的是样本分位数
检测和过滤异常值
In [70]: col=data[3]
In [71]: col[np.abs(col)>3]
 data[(np.abs(data)>3).any(1)]  注意any方法,1代表的是轴
 data[np.abs(data)>3]=np.sign(data)*3
np.sign返回的是由1和-1组成的数组
排列和随机采样
通过需要排列的轴的长度条用permutation,可产生一个表示新顺序的整数数组,随机重排序
In [78]: df=DataFrame(np.arange(5*4).reshape(5,4))


In [79]: sampler=np.random.permutation(5)


In [80]: sampler
Out[80]: array([1, 0, 2, 3, 4])


In [81]: df
Out[81]:
    0   1   2   3
0   0   1   2   3
1   4   5   6   7
2   8   9  10  11
3  12  13  14  15
4  16  17  18  19


In [82]: df.take(sampler)  按照sampler 的顺序为index培训
Out[82]:
    0   1   2   3
1   4   5   6   7
0   0   1   2   3
2   8   9  10  11
3  12  13  14  15
4  16  17  18  19


df.take(np.random.permutation(len(df))[:3])  切下k个元素
要通过替换的方式产生样本,最快的方式是通过np.random.randint得到一组最忌整数
In [83]: sampler=np.random.randint(0,5,size=10)


In [84]: sampler
Out[84]: array([2, 4, 4, 4, 4, 2, 2, 2, 0, 3])


计算指标/哑变量  将分类变量转换为哑变量矩阵或指标矩阵
pandas 的get_dummies 函数可实现该功能
In [85]: df=DataFrame({'key':['b','b','a','c','a','b'],
    ...: 'data1':range(6)})


In [86]: df
Out[86]:
   data1 key
0      0   b
1      1   b
2      2   a
3      3   c
4      4   a
5      5   b


In [87]: pd.get_dummies(df['key'])
Out[87]:
   a  b  c
0  0  1  0
1  0  1  0
2  1  0  0
3  0  0  1
4  1  0  0
5  0  1  0


In [88]: dummies=pd.get_dummies(df['key'],prefix='key') 增加前缀
如果某行属于多个分类,如下面的genres列的行
In [90]: mnames=['movie_id','title','genres']
In [92]: movies[:3]
Out[92]:
   movie_id                    title                        genres
0         1         Toy Story (1995)   Animation|Children's|Comedy
1         2           Jumanji (1995)  Adventure|Children's|Fantasy
2         3  Grumpier Old Men (1995)                Comedy|Romance


In [93]: genre_iter=(set(x.split('|')) for x in movies.genres)


In [94]: genres=sorted(set.union(*genre_iter))
 dummies=DataFrame(np.zeros((len(movies),len(genres))),columns=genres)


  for i, gen in enumerate(movies.genres):
       dummies.ix[i,gen.split('1')]=1
 movies_windic=movies.join(dummies.add_prefix('Genre_'))  注意此类数据的处理方式
字符串对象方法
pieces=[ x.strip() for x in val.split(',')]
'::'.join(pieces)
val.index(',')
val.find(':')
find 和index 的区别,如果找不到字符串,index会引发一个Error
val.count(',')
val.replace(',','')
pandas中矢量化的字符串函数
通过data.map,所有的字符串和正则表达式方法都被应用于各个值,但遇到NA就会报错, Series的str属性可访问这些方法
In [117]: data.str.contains('gmail')
matches=data.str.findall(pattern,flags=re.IGNORECASE)
有两个办法可以实现矢量化的元素获取操作,
matches.str.get(1)
matches.str[0]


案列
In [118]: import json


In [119]: db=json.load(open('book/ch07/foods-2011-10-03.json'))


In [120]: len(db)
Out[120]: 6636


In [121]: db[:1]


In [128]: nutrients=DataFrame(db[0]['nutrients'])


In [130]: nutrients[:3]
In [133]: info_keys=['description','group','id','manufacturer']


In [134]: info=DataFrame(db,columns=info_keys)


In [135]: info[:4]
 pd.value_counts(info.group)[:10] 计算数量
In [147]: nutrients=[]


In [148]: for rec in db:
     ...:     fnuts=DataFrame(rec['nutrients'])
     ...:     fnuts['id']=rec['id']
     ...:     nutrients.append(fnuts)
nutrients=pd.concat(nutrients,ignore_index=True)
In [218]: nutrients.duplicated().sum()
Out[218]: 14179


In [219]: nutrients=nutrients.drop_duplicates()
In [221]: col_mapping={'description':'food',
     ...:              'group':'fgroup'}


In [231]: info=info.rename(columns=col_mapping,copy=False)
In [232]: col_mapping={'description':'nutrient','group':'nutgroup'}


In [233]: nutrients=nutrients.rename(columns=col_mapping,copy=False)
 ndata=pd.merge(nutrients,info,on='id',how='outer')
In [236]: ndata.ix[30000]
result=ndata.groupby(['nutrient','fgroup'])['value'].quantile(0.5)
In [240]: result['Zinc, Zn'].order().plot(kind='barh')
In [241]: by_nutrient=ndata.groupby(['nutgroup','nutrient'])


In [242]: get_maximun=lambda x: x.xs(x.value.idxmax())  注意


In [243]: get_minimun=lambda x: x.xs(x.value.idxmin())


 max_foods.food=max_foods.food.str[:50]
In [253]: max_foods.ix['Amino Acids']['food']
绘图和可视化
ipython --pylab
In [255]: plot(np.arange(10))
Out[255]: [<matplotlib.lines.Line2D at 0x19862310>]
In [256]: close()


虽然pandas的绘图函数能处理许多普通忍辱,如果需要自定义一些高级功能的话就必须使用matplotlib API
import matplotlib.pyplot as plt
matplotlib的图像都位于Figure对象中


In [259]: fig=plt.figure()
In [260]: ax1=fig.add_subplot(2,2,1)
In [261]: ax2=fig.add_subplot(2,2,2)
In [262]: ax3=fig.add_subplot(2,2,3)
In [272]: plt.plot(randn(50).cumsum(),'k--')
In [273]: _=ax1.hist(randn(100),bins=20,color='k',alpha=0.3)


In [274]: ax2.scatter(np.arange(30),np.arange(30)+3*randn(30))
Out[274]: <matplotlib.collections.PathCollection at 0x1988ca30>


 fig,axes=plt.subplots(2,3)
pyoplot.subplots 许多选项
In [278]: fig,axes=plt.subplots(2,2,sharex=True,sharey=True)


In [279]: for i in range(2):
     ...:     for j in range(2):
     ...:         axes[i,j].hist(randn(500),bins=50,color='k',alpha=0.5)
     ...: plt.subplots_adjust(wspace=0,hspace=0)  调整边框
 plot(randn(30).cumsum(),color='k',linestyle='dashed',marker='o')


 plt.plot(data,'k--',label='Default')
 plt.legend(loc='best')
plt.xlim() 返回当前的x轴绘图范围
plt.xlim([0,10]) 会将X轴的范围设为0-10
In [292]: fig=plt.figure();


In [293]: ax=fig.add_subplot(1,1,1)


In [294]: ax.plot(randn(1000).cumsum())
Out[294]: [<matplotlib.lines.Line2D at 0x1efb20d0>]


In [295]: ticks=ax.set_xticks([0,250,500,750,1000])


In [296]: labels=ax.set_xticklabels(['one','two','three','four','five'],rotation=30,fontsize='small')


In [297]: ax.set_title('My first matplotlib plot')
Out[297]: <matplotlib.text.Text at 0x19319bd0>


In [298]: ax.set_xlabel('Stages')
Out[298]: <matplotlib.text.Text at 0x1efb2ab0>


添加图例
 ax.plot(randn(1000).cumsum(),'k',label='one')
 ax.plot(randn(1000).cumsum(),'k--',label='two')
 ax.legend(loc='best')
注释可以通过text arrow 和annotate 等函数进行添加
In [307]: from datetime import datetime


In [308]: fig=plt.figure()


In [309]: ax=fig.add_subplot(1,1,1)


In [310]: data=pd.read_csv('book/ch08/spx.csv',index_col=0,parse_dates=True)


spx=data['SPX']
spx.plot(ax=ax,style='k-')


In [318]: crisis_data=[
     ...: (datetime(2007,10,11),'Peak of bull market'),
     ...: (datetime(2008,3,12),'Bear Stearns Dails'),
     ...: (datetime(2008,9,15),'Lehman Bankruptcy')
     ...: ]


In [319]: for date, label in crisis_data:
     ...:     ax.annotate(label,xy=(date,spx.asof(date)+50),
     ...:     xytext=(date,spx.asof(date)+200),
     ...:     arrowprops=dict(facecolor='black')
     ...:     horizontalalignment='left',verticalalignment='top')
ax.set_title('Import dates in 2008')
图像对象如Rectangle和Circle可在matplotlib.pypolt中找到,但完整的集合在matplotlib.batches中


In [322]: fig=plt.figure()


In [323]: ax=fig.add_subplot(1,1,1)


In [324]: rect=plt.Rectangle((0.2,0.75),0.4,0.15,color='k',alpha=0.3)


In [325]: ax.add_patch(rect)
Out[325]: <matplotlib.patches.Rectangle at 0x1f1005b0>


In [326]: plt.savefig('figpath.png',dpi=400,bbox_inches='tight')  保存文件


from io import StringIO
buffer=StringIO()
plot.savefig(buffer)         不一定写入磁盘,保存为StringIO 
plot_data=buffer.getvalue() 


matplotlib配置
plt.rc('figure',figsize=(10,10))
front_options={'family':'monospace','weight':'bold'}
plt.rc('front',**font_options)


pandas 中的绘图函数
In [327]: s=Series(np.random.randn(10).cumsum(),index=np.arange(0,100,10))


In [328]: s.plot(), Series对象的plot方法按照需求把参数传给matplotlib,




plot 的其它关键字参数会相应的传给matplotlib绘图函数,需要深入matplotlib API
Out[328]: <matplotlib.axes._subplots.AxesSubplot at 0x1f100570>


In [330]: df=DataFrame(np.random.randn(10,4).cumsum(0),columns=['A','B','C','D'],index=np.arange(0,100,10))


In [331]: df.plot()
Out[331]: <matplotlib.axes._subplots.AxesSubplot at 0x1f2298d0>


柱状图
In [334]: fig,axes=plt.subplots(2,1)   注意这种写法


In [335]: data=Series(np.random.rand(16),index=list('abcdefghijklmnop'))


In [336]: data.plot(kind='bar',ax=axes[0],color='k',alpha=0.7)
Out[336]: <matplotlib.axes._subplots.AxesSubplot at 0x196db8f0>


In [337]: data.plot(kind='barh',ax=axes[1],color='k',alpha=0.7)
Out[337]: <matplotlib.axes._subplots.AxesSubplot at 0x19598b50>


df=DataFrame(np.random.rand(6,4),index=['one','two','three','four','five','six],columns=pd.Index(['A','B','C','D'],name='Genus'))
df.plot(kind='bar')
df.plot(kind='barh',stacked=True,alpha=0.5) stacked=True 设置堆积
In [340]: tips=pd.read_csv('book/ch08/tips.csv')


In [341]: party_counts=pd.crosstab(tips.day,tips.size)
In [346]: party_counts=party_counts.ix[:,2:5]


party_pcts=party_counts.div(party_counts.sum(1).astype(float),axis=0)
直方图, 是一种对值频率进行离散化显示的柱状图。数据点被拆分到离散的,间隔均匀的面元中
tips['tip_pct']=tips['tip']/tips['total_bill']
tips['tip_pct'].hist(bins=50)
tips['tip_pct'].plot(kind='kde') 密度图






In [359]: macro=pd.read_csv('book/ch08/macrodata.csv')


In [360]: data=macro[['cpi','m1','tbilrate','unemp']]


In [361]: trans_data=np.log(data).diff().dropna()


In [362]: plt.scatter(trans_data['m1'],trans_data['unemp'])    散布图
 pd.scatter_matrix(trans_data,diagonal='kde',color='k',alpha=0.3)  散布矩阵图 都用于数据探索
绘制地图
 data=pd.read_csv('book/ch08/Haiti.csv')
data[['INCIDENT DATE','LATITUDE','LONGITUDE']][:10]
 data.describe()
 data=data[(data.LATITUDE>18 &(data.LATITUDE<20) & (data.LONGITUDE >-75) &(data.LONGITUDE <70) & data.CATEGORY
     ...: .notnull()]


In [376]: def to_cat_list(catstr):
     ...:     stripped=(x.strip() for x in catstr.split(','))
     ...:     return [x for  x in stripped if x]


In [377]: def get_all_categories(cat_series):
     ...:     cat_sets=(set(to_cat_list(x)) for x in cat_series)
     ...:     return sorted(set.union(*cat_sets))
     ...:


In [378]: def get_english(cat):
     ...:     code,names=cat.split('.')
     ...:     if '|' in names:
     ...:         names=names.split(' | ')[1]
     ...:         return code,names.strip()


  english_mapping=dice(get_english(x) for x in all_cats)


def get_code(seq):
    return [x.split('.')[0] for x in seq if x]
all_codes=get_code(all_cats)
code_index=pd.index(np.unique(all_codes))
dummy_frame=DataFrame(np.zeros((len(data),len(code_index))),index=data.index, columns=code_index)


数据聚合与分组计算
In [4]: df=DataFrame({'key1':['a','a','b','b','a'],
   ...:              'key2':['one','two','one','two','one'],
   ...:              'data1':np.random.randn(5),
   ...:              'data2':np.random.randn(5)})


In [5]: df
Out[5]:
      data1     data2 key1 key2
0  1.307785  0.265249    a  one
1 -0.692403  1.077600    a  two
2  0.644246  0.219224    b  one
3 -0.543699 -0.732631    b  two
4  0.441021  2.025165    a  one


In [9]: grouped.mean()
Out[9]:
key1
a    0.352134
b    0.050274
Name: data1, dtype: float64




In [12]: means=df['data1'].groupby([df['key1'],df['key2']]).mean()


In [14]: means.unstack()
Out[14]:
key2       one       two
key1
a     0.874403 -0.692403
b     0.644246 -0.543699


也可以如下
states=np.array(['Ohio','California'])
years=np.array([2005,2006])
df['data1'].groupby([states,years]).mean()
df.groupby(['key1','key2']).mean()
df.groupby(['key1','key2']).size() 返回一个含有分组大小的Series


对分组进行迭代


In [21]: for name,group in df.groupby('key1'):
    ...:     print name
    ...:     print group
    ...:
a
      data1     data2 key1 key2
0  1.307785  0.265249    a  one
1 -0.692403  1.077600    a  two
4  0.441021  2.025165    a  one
b
      data1     data2 key1 key2
2  0.644246  0.219224    b  one
3 -0.543699 -0.732631    b  two


这个地方names 为a, b 其它的为group
grouped=df.groupby(df.dtypes,axis=1) 在axis=1 上进行分组
df.groupby('key1')['data1']
df.groupby('key1')[['data2']]
通过字典或Series进行分组
In [36]: people=DataFrame(np.random.randn(5,5),columns=['a','b','c','d','e'],
    ...: index=['Joe','Steve','Wes','Jim','Travis'])


In [37]: people.ix[2:3,['b','c']]=np.nan


In [39]: mapping={'a':'red','b':'red','c':'blue','d':'blue','e':'red','f':'orangge'}


In [40]: by_column=people.groupby(mapping,axis=1)
 by_column.sum()
people.groupby(map_series,axis=1).count()




In [24]: for (k1,k2), group in df.groupby(['key1','key2']):
    ...:     print k1,k2
    ...:     print group


pieces=dict(list(df.groupby('key1')))
分组索引
In [33]: df.groupby('key1')[['data2']]  注意是DataFrame格式的
Out[33]: <pandas.core.groupby.DataFrameGroupBy object at 0x07E794F0>


In [35]: df.groupby('key1')['data2']   注意是Series格式的
Out[35]: <pandas.core.groupby.SeriesGroupBy object at 0x07DFC0F0>






通过函数进行分组
In [42]: people.groupby(len).sum()
Out[42]:
          a         b         c         d         e
3  0.264500  0.222157 -1.410616  5.870837  0.139462
5 -1.301742  0.211664  0.685027 -0.188834  1.109525
6  0.988436 -0.340683  0.777650  0.158592 -2.042725


In [43]: people
Out[43]:
               a         b         c         d         e
Joe    -1.013621  0.461850 -0.191093  0.831496  0.992449
Steve  -1.301742  0.211664  0.685027 -0.188834  1.109525
Wes     0.556571       NaN       NaN  1.888419  0.289088
Jim     0.721550 -0.239693 -1.219522  3.150922 -1.142074
Travis  0.988436 -0.340683  0.777650  0.158592 -2.042725




In [44]: key_list=['one','one','one','two','two']


In [45]: people.groupby([len,key_list]).min()


根据索引级别分组
In [47]: columns=pd.MultiIndex.from_arrays([['US','US','US','JP','JP'],[1,3,5,1,3]],names=['cty','tenor'])


In [48]: hier_df=DataFrame(np.random.randn(4,5),columns=columns)


In [53]: hier_df.groupby(level='cty',axis=1).count()
Out[53]:
cty  JP  US
0     2   3
1     2   3
2     2   3
3     2   3


In [54]: hier_df.groupby(level='tenor',axis=1).count()
Out[54]:
tenor  1  3  5
0      2  2  1
1      2  2  1
2      2  2  1
3      2  2  1
grouped=df.groupby('key1')


grouped['data1'].quantile(0.9) 分位数
如果要使用自己的聚合函数,只需将其传入aggregate或agg方法
def peak_to_peak(arr):
    return arr.max()-arr.min()
grouped.agg(peak_to_peak)
grouped.describe()


In [5]: tips=pd.read_csv('book/ch08/tips.csv')
面向列的多函数应用
tips=pd.read_csv('book/ch08/tips.csv')
tips['tip_pct']=tips['tip']/tips['total_bill']
In [11]: grouped=tips.groupby(['sex','smoker'])
In [12]: grouped_pct=grouped['tip_pct']
 grouped_pct.agg('mean')
如果传入一组函数或函数名,得到的DataFrame的列就会以相应的函数命名
 grouped_pct.agg(['mean','std',peak_to_peak])
grouped_pct.agg([('foo','mean'),('bar',np.std)])


In [17]: functions=['count','mean','max']


In [18]: result=grouped['tip_pct','total_bill'].agg(functions)  


ftuples=[('Durchschnitt','mean'),('Abweichung',np.var)]
grouped['tip_pct','total_bill'].agg(ftuples)


grouped.agg({'tip':np.max,'size':'sum'}) 不同的列应用不同的函数
grouped.agg({'tip_pct':['min','max','mean','std'],'size':'sum'})
tips.groupby(['sex','smoker'],as_index=False).mean()


分级运算和转换
In [25]: key=['one','two','one','two','one']


In [26]: people.groupby(key).mean()
Out[26]:
            a         b         c         d         e
one -0.076572  0.641193 -0.097059 -0.568914 -0.584621
two  0.355047 -0.644411 -0.435602 -0.457357 -0.771578


In [27]: people.groupby(key).transform(np.mean), transform 会将一个函数应用到各个分组,然后将结果放置到适当的位置
如果各分组产生的是一个标量值,则该值就被广播出去
Out[27]:
               a         b         c         d         e
Joe    -0.076572  0.641193 -0.097059 -0.568914 -0.584621
Steve   0.355047 -0.644411 -0.435602 -0.457357 -0.771578
Wes    -0.076572  0.641193 -0.097059 -0.568914 -0.584621
Jim     0.355047 -0.644411 -0.435602 -0.457357 -0.771578
Travis -0.076572  0.641193 -0.097059 -0.568914 -0.584621


In [28]: def demean(arr):
    ...:     return arr-arr.mean()
    ...:


In [29]: demeaned=people.groupby(key).transform(demean)


In [30]: demeaned
Out[30]:
               a         b         c         d         e
Joe     1.392273 -1.015625  1.708805 -1.033237  0.132633
Steve  -0.600416 -0.130226  0.244243 -0.095321 -0.461307
Wes    -0.450601  0.949336  0.564339  0.486065 -1.021922
Jim     0.600416  0.130226 -0.244243  0.095321  0.461307
Travis -0.941672  0.066289 -2.273144  0.547172  0.889290


apply: 一般性的“ 拆分--应用--合并”
In [32]: def top(df, n=5,column='tip_pct'):
    ...:     return df.sort_index(by=column)[-n:]
    ...:


In [33]: tips.groupby('smoker').apply(top)


tips.groupby(['smoker','day']).apply(top,n=1,column='total_bill')
禁止分组键
tips.groupby('smoker',group_keys=False).apply(top)
分位数和桶分析
In [34]: frame=DataFrame({'data1':np.random.randn(1000),
    ...: 'data2':np.random.randn(1000)})


In [38]: factor=pd.cut(frame.data1,4)


In [40]: def get_stats(group):
    ...:     return {'min':group.min(),'max':group.max(),'count':group.count(),'mean':group.mean()}


In [42]: grouped=frame.data2.groupby(factor)


In [43]: grouped.apply(get_stats).unstack()


用特定分组的值填充缺失值


In [48]: states=['Ohio','New York','Vermont','Florida','Oregon','Nevada','California','Idaho']


In [49]: group_key=['East']*4 +['West']*4


In [50]: data=Series(np.random.randn(8),index=states)


In [52]: data[['Vermont','Nevada','Idaho']]=np.nan
In [53]: data.groupby(group_key).mean()
In [54]: fill_mean=lambda g: g.fillna(g.mean())
In [55]: data.groupby(group_key).apply(fill_mean)


In [56]: fill_values={'East':0.5,'West':-1}


In [57]: fill_func=lambda g: g.fillna(fill_values[g.name])


In [58]: data.groupby(group_key).apply(fill_func)
随机采样和排列
def draw(deck,n=5):
    ...:     return deck.take(np.random.permutation(len(deck))[:n])


In [71]: get_suit=lambda card:card[-1]


In [72]: deck.groupby(get_suit).apply(draw,n=2) 每组进行取样
分组加权平均数和相关系数
In [74]: df=DataFrame({'category':['a','a','a','a','b','b','b','b'],
    ...:               'data':np.random.randn(8),
    ...:                'weights':np.random.rand(8)})


In [76]: grouped=df.groupby('category')


In [77]: get_wavg=lambda g: np.average(g['data'],weights=g['weights'])


In [78]: grouped.apply(get_wavg)


In [79]: close_px=pd.read_csv('book/ch09/stock_px.csv',parse_dates=True,index_col=0)


In [80]: rets=close_px.pct_change().dropna()


In [81]: spx_corr=lambda x: x.corrwith(x['SPX'])


In [82]: by_year=rets.groupby(lambda x: x.year)


In [83]: by_year.apply(spx_corr)


面向分组的线性回归
import statsmodels.api as sm
def regress(data, yvar, xvars):
    Y=data[yvar]
    X=data[xvars]
    X['intercept']=1.
    result = sm.OLS(Y,X).fit()
    return result.params 
by_year.apply(regress,'AAPL',['SPX'])


透视表和交叉表
tips.pivot_table(index=['sex','smoker'])
In [96]: tips.pivot_table(['tip_pct','size'],index=['sex','day'],columns='smoker')
Out[96]:
              tip_pct                size
smoker             No       Yes        No       Yes
sex    day
Female Fri   0.165296  0.209129  2.500000  2.000000
       Sat   0.147993  0.163817  2.307692  2.200000
       Sun   0.165710  0.237075  3.071429  2.500000
       Thur  0.155971  0.163073  2.480000  2.428571
Male   Fri   0.138005  0.144730  2.000000  2.125000
       Sat   0.162132  0.139067  2.656250  2.629630
       Sun   0.158291  0.173964  2.883721  2.600000
       Thur  0.165706  0.164417  2.500000  2.300000


tips.pivot_table(['tip_pct','size'],index=['sex','day'],columns='smoker',aggfunc=len,margins=True) 
margins 分类小计
In [99]: tips.pivot_table('size',index=['time','sex','smoker'],columns='day',aggfunc='sum',fill_value=0)
Out[99]:
day                   Fri  Sat  Sun  Thur
time   sex    smoker
Dinner Female No        2   30   43     2
              Yes       8   33   10     0
       Male   No        4   85  124     0
              Yes      12   71   39     0
Lunch  Female No        3    0    0    60
              Yes       6    0    0    17
       Male   No        0    0    0    50
              Yes       5    0    0    23


pd.crosstab(data.Gender,data.Handedness,margins=True)
pd.crosstab([tips.time,tips.day],tips.smoker,margins=True)


In [111]: unique_cands=fec.cand_nm.unique()
bins=np.array([0,1,10,100,1000,10000])
labels=pd.cut(fec_mrbo.contb_receipt_amt,bins)
grouped=fec_mrbo.groupby(['cand_nm',labels])
normed_sums=bucket_sums.div(bucket_sums.sum(axis=1),axis=0)
totals=grouped.contb_receipt_amt.sum().unstack(0).fillna(0)
totals=totals[totals.sum(1)>100000]
percent=totals.div(totals.sum(1),axis=0)
时间序列
In [114]: from datetime import datetime
In [115]: now=datetime.now()




In [121]: delta=datetime(2011,1,7)-datetime(2008,6,24,8,15)


In [122]: delta
Out[122]: datetime.timedelta(926, 56700)
datetime 以毫秒储存日期和时间


In [124]: start=datetime(2011,1,7)


In [125]: start+timedelta(12)
Out[125]: datetime.datetime(2011, 1, 19, 0, 0)
字符串和datetime的相互转换


In [126]: stamp=datetime(2011,1,3)


In [127]: str(stamp)
Out[127]: '2011-01-03 00:00:00'


In [129]: stamp.strftime('%Y-%m-%d')
Out[129]: '2011-01-03'


In [131]: datetime.strptime(value,'%Y-%m-%d')
Out[131]: datetime.datetime(2011, 1, 3, 0, 0)


from detautil.parser import parse 用detautil包解析日期
parse('2011-01-03')
datetime.datetime(2011,1,3,0,0)
pandas通常是用于处理成组日期的,不管这些日期是DataFrame的轴索引还是列。to_datetime方法可以解析多种不同的日期表示形式,
In [132]: idx=pd.to_datetime(datestrs+[None])
NaT是pandas中时间戳数据的NA值




In [137]: dates=[datetime(2011,1,2),datetime(2011,1,5),datetime(2011,1,7),datetime(2011,1,8),datetime(2011,1,10),datetim
     ...: e(2011,1,12)]


In [138]: ts=Series(np.random.randn(6),index=dates)


In [147]: ts+ts[::2]  注意按照时间对齐
Out[147]:
2011-01-02    1.447321
2011-01-05         NaN
2011-01-07   -0.621674
2011-01-08         NaN
2011-01-10    0.862545
2011-01-12         NaN
dtype: float64


pands用NumPy的datetime64数据类型以纳秒存储时间戳
对于较长的时间序列,只需传入"年",等轻松完成


In [151]: longer_ts=Series(np.random.randn(1000),index=pd.date_range('1/1/2000',periods=1000))
ts.truncate(after='1/9/2011')


In [153]: dates=pd.date_range('1/1/2000',periods=100,freq='W-Wed')
带有重复索引的时间序列
dates=pd.DatetimeIndex(['1/1/2000','1/2/2000','1/2/2000','1/2/2000','1/3/2000'])
In [158]: dup_ts=Series(np.arange(5),index=dates)
dup_ts.index.is_unique
In [160]: grouped=dup_ts.groupby(level=0)
日期的范围、频率及移动
将不规则的时间序列转换为一个固定频率的时间序列,resample 
ts.resample('D')
生成日期范围
 index=pd.date_range('4/1/2012','6/1/2012')
 pd.date_range(start='4/1/2012,periods=20)
pd.date_range('1/1/2000','12/1/2000',freq='BM')
有时,虽然起始和结束日期带有时间信息,但用normalize可以规范化到午夜的时间戳
In [168]: pd.date_range('5/2/2012 12:56:31',periods=5,normalize=True)
频率和日期偏移量
每个基础频率,都有一个日期偏移量的对象与之对应
from pandas.tseries.offsets import Hour, Minute
hour=Hour()
four_hours=Hour(4)
In [174]: Hour(2)+Minute(30)
Out[174]: <150 * Minutes>


In [175]: pd.date_range('1/1/2000',periods=10,freq='1h30min')
Out[175]:
DatetimeIndex(['2000-01-01 00:00:00', '2000-01-01 01:30:00',
               '2000-01-01 03:00:00', '2000-01-01 04:30:00',
               '2000-01-01 06:00:00', '2000-01-01 07:30:00',
               '2000-01-01 09:00:00', '2000-01-01 10:30:00',
               '2000-01-01 12:00:00', '2000-01-01 13:30:00'],
              dtype='datetime64[ns]', freq='90T')
WOM日期
WOM 日期非常使用的频率类
 rng=pd.date_range('1/1/2000','9/1/2012',freq='WOM-3FRI') 每月第三个星期五
移动(超前和滞后)数据
shift通常用于计算一个时间序列或多个时间序列中的百分比变化。
In [177]: ts=Series(np.random.randn(4),index=pd.date_range('1/1/2000',periods=4,freq='M'))


In [181]: ts/ts.shift(1)-1 对数据移动


In [182]: ts.shift(2,freq='M')  对时间戳移动
Out[182]:
2000-03-31   -0.885823
2000-04-30    0.063836
2000-05-31   -0.727056
2000-06-30    1.101101
Freq: M, dtype: float64
ts.shift(3,freq='D')  对时间戳移动
通过偏移量对日期进行位移
In [186]: from pandas.tseries.offsets import Day, MonthEnd
now=datetime(2011,11,17)
now+3*Day()


In [188]: now+MonthEnd()
Out[188]: Timestamp('2017-05-31 15:55:15.005000')


通过瞄点偏移量的rollforward和rolback方法,可以显示地将日期向前或向后滚动
offset=MonthEnd()
offset.rollforward(now)
offset.rollback(now)
结合groupby滚动
ts=Series(np.random.randn(20),index=pd.date_range('1/15/2000',periods=20,freq='4d'))
ts.groupby(offset.rollforward).mean()
ts.resample('M',how='mean')
时区处理
在Python中,时区信息来自第三方库pytz,
In [191]: import pytz


In [192]: pytz.common_timezones[-5:]
Out[192]: ['US/Eastern', 'US/Hawaii', 'US/Mountain', 'US/Pacific', 'UTC']


In [194]: tz=pytz.timezone('US/Eastern')


In [195]: tz
Out[195]: <DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>


默认情况下,pandas中的时间序列是单纯时区,


在生成日期范围的时候还可以加上一个时区集
pd.date_range('3/9/2012 9:30',periods=10,freq='D',tz='UTC')
ts_utc=ts.tz_localize('UTC') 本地化
操作时区意识型Timestamp对象
Timestamp对象也能被从单纯型本地化为时区意识型
stamp=pd.Timestamp('2011-03-12  04:00')
stamp_utc =stamp.tz_localize('utc')
stamp_utc.tz_convert('US/Eastern')
不同时区之间的运算
如果两个时间序列时区不同,将它们合并到一起时,最终结果就会使UTC
时间及算数运算
p=pd.Period(2007,freq='A-DEC')
p+5
In [198]: rng=pd.period_range('1/1/2000','6/30/2000',freq='M')
PeriodIndex类保存了一组period,可以做为轴索引
Series(np.random.randn(6),index=rng)
时期的频率转换
p=pd.Period('2007',freq='A-EDC')
p.asfreq('M',how='start')
rng=pd.period_range('2006','2009',freq='A-EDC')
ts=Series(np.random.randn(len(rng)),index=rng)
按季度计算的时间频率
p=pd.Period('2012Q4',freq='Q-JAN')
In [203]: p.asfreq('D','start')
Out[203]: Period('2011-11-01', 'D')
p4pm=(p.asfreq('B','e')-1).asfreq('T','s')+16*60
将Timestamp转换为Period
to_period


In [208]: rng=pd.date_range('1/29/2000',periods=6,freq='D')


In [209]: ts2=Series(randn(6),index=rng)


In [211]: ts2.to_period('M')
Out[211]:
2000-01   -1.050680
2000-01   -0.061141
2000-01    1.330820
2000-02   -0.376156
2000-02    0.059391
2000-02   -0.569472
Freq: M, dtype: float64


通过数组创建PeriodIndex
In [219]: data=pd.read_csv('book/ch08/macrodata.csv')


In [220]: index=pd.PeriodIndex(year=data.year,quarter=data.quarter,freq='Q-DEC')
In [227]: data.index=index
In [227]: data.infl
重采样及频率转换
重采样(resampling)指的是将时间序列从一个频率转换到另一个频率的处理过程


In [227]: rng=pd.date_range('1/1/2000',periods=100,freq='D')


In [228]: ts=Series(randn(len(rng)),index=rng)


IIn [229]: ts.resample('M',how='mean')
C:\Python27\Scripts\ipython:1: FutureWarning: how in .resample() is deprecated
the new syntax is .resample(...).mean()
Out[229]:
2000-01-31   -0.118807
2000-02-29    0.088835
2000-03-31    0.144549
2000-04-30   -0.691874
Freq: M, dtype: float64
In [231]: ts.resample('M',how='mean',kind='period')
C:\Python27\Scripts\ipython:1: FutureWarning: how in .resample() is deprecated
the new syntax is .resample(...).mean()
Out[231]:
2000-01   -0.118807
2000-02    0.088835
2000-03    0.144549
2000-04   -0.691874
Freq: M, dtype: float64
resample 是一个林火高效的方法


降采样
In [232]: rng=pd.date_range('1/1/2000',periods=12,freq='T')


In [233]: ts=Series(np.arange(12),index=rng)


In [234]: ts.resample('5min',how='sum')
C:\Python27\Scripts\ipython:1: FutureWarning: how in .resample() is deprecated
the new syntax is .resample(...).sum()
Out[234]:
2000-01-01 00:00:00    10
2000-01-01 00:05:00    35
2000-01-01 00:10:00    21
Freq: 5T, dtype: int32
In [235]: ts.resample('5min',how='sum',closed='left')
ts.resample('5min',how='sum',closed='left',label='left')
OLC重采样
In [236]: ts.resample('5min',how='ohlc')
通过groupby重采样
In [238]: rng=pd.date_range('1/1/2000',periods=100,freq='D')


In [239]: ts=Series(np.arange(100),index=rng)


In [240]: ts.groupby(lambda x: x.month).mean()


升采样和插值
In [241]: frame=DataFrame(np.random.randn(2,4),index=pd.date_range('1/1/2000',periods=2,freq='W-WED'),
     ...:             columns=['Colorado','Texas','New York','Ohio'])


In [242]: frame[:5]
Out[242]:
            Colorado     Texas  New York      Ohio
2000-01-05  1.688674  0.942025 -1.380204  0.261269
2000-01-12  0.101050 -1.422538  1.986201 -1.189550


In [243]: df_daily=frame.resample('D')


resampling的填充和插值方式跟fillna和reindex一样
frame.resample('D',fill_method='ffill')
frame.resample('D',fill_method='ffill',limit=2) 
In [248]: frame.resample('D',fill_method='ffill',limit=2)
C:\Python27\Scripts\ipython:1: FutureWarning: fill_method is deprecated to .resample()
the new syntax is .resample(...).ffill(limit=2)
Out[248]:
            Colorado     Texas  New York      Ohio
2000-01-05  1.688674  0.942025 -1.380204  0.261269
2000-01-06  1.688674  0.942025 -1.380204  0.261269
2000-01-07  1.688674  0.942025 -1.380204  0.261269
2000-01-08       NaN       NaN       NaN       NaN
2000-01-09       NaN       NaN       NaN       NaN
2000-01-10       NaN       NaN       NaN       NaN
2000-01-11       NaN       NaN       NaN       NaN
2000-01-12  0.101050 -1.422538  1.986201 -1.189550
通过时期进行重采样
时间序列绘图
In [250]: close_px_all=pd.read_csv('book/ch09/stock_px.csv',parse_dates=True,index_col=0)
In [256]: close_px=close_px_all[['AAPL','MSFT','XOM']]


In [257]: close_px=close_px.resample('B',fill_method='ffill')
C:\Python27\Scripts\ipython:1: FutureWarning: fill_method is deprecated to .resample()
the new syntax is .resample(...).ffill()
In [259]: close_px['AAPL'].plot()
close_px.ix['2009'].plot()
close_px['AAPL'].ix['01-2001':'03-2011'].plot()
移动窗口函数


In [264]: close_px.AAPL.plot()
In [265]: pd.rolling_mean(close_px.AAPL,250).plot()


In [265]: pd.rolling_mean(close_px.AAPL,250).plot()
C:\Python27\Scripts\ipython:1: FutureWarning: pd.rolling_mean is deprecated for Series and will be removed in a future version, replace with
        Series.rolling(window=250,center=False).mean()
Out[265]: <matplotlib.axes._subplots.AxesSubplot at 0xcfc86f0>


In [266]: appl_std250=pd.rolling_std(close_px.AAPL,250,min_periods=10)
C:\Python27\Scripts\ipython:1: FutureWarning: pd.rolling_std is deprecated for Series and will be removed in a future version, replace with
        Series.rolling(min_periods=10,window=250,center=False).std()


In [267]: appl_std250[5:12]
Out[267]:
2003-01-09         NaN
2003-01-10         NaN
2003-01-13         NaN
2003-01-14         NaN
2003-01-15    0.077496
2003-01-16    0.074760
2003-01-17    0.112368
Freq: B, Name: AAPL, dtype: float64
expanding_mean=lambda x: rolling_mean(x,len(x),min_periods=1)
pd.rolling_mean(close_px,60).plot(logy=True)
指数加权函数
In [270]: fig,axes=plt.subplots(nrows=2,ncols=1,sharex=True,sharey=True,figsize=(12,7))  注意这种写法
 appl_px=close_px.AAPL['2005':'2009']
In [274]: ma60=pd.rolling_mean(appl_px,60,min_periods=50)
 ewma60=pd.ewma(appl_px,span=60)


In [276]: appl_px.plot(style='k-',ax=axes[0])
Out[276]: <matplotlib.axes._subplots.AxesSubplot at 0x8560ab0>


In [277]: ma60.plot(style='k--',ax=axes[0])
Out[277]: <matplotlib.axes._subplots.AxesSubplot at 0x8560ab0>


In [278]: appl_px.plot(style='k-',ax=axes[1])
Out[278]: <matplotlib.axes._subplots.AxesSubplot at 0x10c3d850>


In [279]: ewma60.plot(style='k--',ax=axes[1])
Out[279]: <matplotlib.axes._subplots.AxesSubplot at 0x10c3d850>


In [280]: axes[0].set_title('Simple MA')
Out[280]: <matplotlib.text.Text at 0x850c090>


In [281]: axes[1].set_title('Exponentially-weighted MA')
Out[281]: <matplotlib.text.Text at 0xeead4b0>
二元移动窗口函数


In [284]: spx_px=close_px_all['SPX']


In [285]: spx_rets=spx_px/spx_px.shift(1)-1


In [286]: returns=close_px.pct_change()
In [292]: corr=pd.rolling_corr(returns.AAPL,spx_rets,spx_rets,125,min_periods=100)
corr.plot()
用户定义的移动窗口函数
rolling_apply函数使你能够在移动窗口上应用自己设计的数组函数,该函数要能从数组的各个片段中产生单个值


In [294]: from scipy.stats import percentileofscore


In [295]: score_at_2percent=lambda x: percentileofscore(x,0.02)


In [296]: result=pd.rolling_apply(returns.AAPL,250,score_at_2percent)
C:\Python27\Scripts\ipython:1: FutureWarning: pd.rolling_apply is deprecated for Series and will be removed in a future version, replace with
        Series.rolling(center=False,window=250).apply(args=<tuple>,func=<function>,kwargs=<dict>)


In [297]: result.plot()
Out[297]: <matplotlib.axes._subplots.AxesSubplot at 0x10c3d850>
性能和内存使用方面的注意事项
金融和经济应用


pandas可以在算术运算中自动对齐数据
prices * volume
vmap=(prices*volume).sum()./volume.sum()
可以使用DataFrame的align方法,进行对齐
prices.align(volume,join='inner')
通过一组索引可能不同的Series构建一个DataFrame
显示的定义索引,丢弃其余数据
DateFrame({'one':s1,'two':s2,'three':s3},index=list('face'))
频率不同的时间序列运算
频率转换和对齐的两个工具 resample 和reindex
In [5]: ts1=Series(np.random.randn(3),index=pd.date_range('2012-6-13',periods=3,freq='W-WED'))
In [9]: ts1.resample('B',fill_method='ffill')
C:\Python27\Scripts\ipython:1: FutureWarning: fill_method is deprecated to .resample()
the new syntax is .resample(...).ffill()
Out[9]:
2012-06-13   -0.731003
2012-06-14   -0.731003
2012-06-15   -0.731003
2012-06-18   -0.731003
2012-06-19   -0.731003
2012-06-20   -0.117476
2012-06-21   -0.117476
2012-06-22   -0.117476
2012-06-25   -0.117476
2012-06-26   -0.117476
2012-06-27    1.079147
Freq: B, dtype: float64






IIn [10]: dates=pd.DatetimeIndex(['2012-6-12','2012-6-17','2012-6-18','2012-6-12','2012-6-22','2012-6-29'])
In [12]: ts2=Series(np.random.randn(6),index=dates)


In [13]: ts2
Out[13]:
2012-06-12    1.121507
2012-06-17   -0.195729
2012-06-18   -1.865222
2012-06-12   -0.091561
2012-06-22   -0.718304
2012-06-29   -0.604624
dtype: float64


In [13]: ts2
Out[13]:
2012-06-12    1.121507
2012-06-17   -0.195729
2012-06-18   -1.865222
2012-06-12   -0.091561
2012-06-22   -0.718304
2012-06-29   -0.604624
dtype: float64
如果要将ts1中的值加到ts2上,一个办法是将两者重采样为规整频率后再加,另外是使用reindex


In [14]: ts1.reindex(ts2.index,method='ffill')
Out[14]:
2012-06-12         NaN
2012-06-17   -0.731003
2012-06-18   -0.731003
2012-06-12         NaN
2012-06-22   -0.117476
2012-06-29    1.079147
dtype: float64


In [17]: ts2+ts1.reindex(ts2.index,method='ffill')
Out[17]:
2012-06-12         NaN
2012-06-17   -0.926731
2012-06-18   -2.596224
2012-06-12         NaN
2012-06-22   -0.835780
2012-06-29    0.474523
dtype: float64
Period提供了另一种处理不同频率时间序列的办法
和Timestamp的时间序列不同,由Period索引的两个不同频率的时间序列之间的运算必须进行显示转换
infl_q=infl.asfreq('Q-SEP',how='end')
然后可以被重索引了
时间和“最当前”数据选取


rng=pd.date_range('2012-06-01 09:30','2012-06-01 15:59', freq='T')
rng=rng.append([rng+pd.offsets.BDay(i) for i in range(1,4)])
ts=Series(np.arange(len(rng),dtype=float),index=rng)
利用Python 的datetime.time对象进行索引即可抽取这些时间点上的值
from datetime import time
ts[time(10,0)]
 ts.at_time(time(10,0))
In [31]: ts.between_time(time(10,0),time(10,1)) 两个time对象之间的值
取时间点之前最后出现的数据
In [34]: indexer=np.sort(np.random.permutation(len(ts))[250:])


In [35]: irr_ts=ts.copy()


In [36]: irr_ts[indexer]=np.nan


如果将一组Timestamp传入asof方法,就能得到这些时间点处的有效值


In [38]: selection=pd.date_range('2012-06-01 10:00', periods=4, freq='B')


In [39]: irr_ts.asof(selection)
Out[39]:
2012-06-01 10:00:00     30.0
2012-06-04 10:00:00    387.0
2012-06-05 10:00:00    387.0
2012-06-06 10:00:00    387.0
Freq: B, dtype: float64


拼接多个数据源
在特定时刻从一个时间序列切换到另外一个,利用pandas.concat
In [40]: data1=DataFrame(np.ones((6,3),dtype=float),columns=['a','b','c'],
    ...: index=pd.date_range('6/12/2012',periods=6))


In [41]: data2=DataFrame(np.ones((6,3),dtype=float)*2,columns=['a','b','c'],index=pd.date_range('6/13/2012',periods=6))
In [44]: spliced=pd.concat([data1.ix[:'2012-06-14'],data2.ix['2012-06-15':]])


spliced_filled=spliced.combine_first(data2)  combine_first可以引入合并点之前的数据


spliced.update(data2,overwrite=False) 用update方法弥补空洞
收益指数和累计收益
price['2011-10-03']/price['2011-03-01']-1
returns=price.pct_change()
ret_index=1+returns.cumprod()
ret_ubdex[0]=1   #将第一个值设置为1
然后计算累计收益
m_returns=ret_index.resample('BM',how='last').pct_change()
m_rets=(1+returns).resample('M',how='prod',kind='period')-1
m_rets['2012']
如果知道了股息的派发日和支付率,就可以将它们计入到每日总收益中
returns[dividend_dates+=dividend_pcts
分组变换和分析
In [45]: import random;random.seed(0)
In [46]: import string


In [49]: def rands(n):
    ...:     choices=string.ascii_uppercase
    ...:     return ''.join([random.choice(choices) for _ in xrange(n)]) 注意此处的_,随机的次数,这个地方可以用任何字母代替, _和前面的random.choice 间接相关
    ...:


In [50]: tickers=np.array([rands(5) for _ in xrange(N)])   


In [68]: M=500


In [69]: df=DataFrame({'Momentum':np.random.randn(M)/200+0.03,
    ...: 'Value':np.random.randn(M)/200+0.08,
    ...: 'ShortInterest':np.random.randn(M)/200-0.02},
    ...: index=tickers[:M])


IIn [71]: ind_names=np.array(['FINANCIAL','TECH'])


In [72]: sampler=np.random.randint(0,len(ind_names),N)


In [73]: industries=Series(ind_names[sampler],index=tickers,name='industry')


In [83]: by_industry=df.groupby(industries)


In [84]: by_industry.mean()




 by_industry.describe()




In [86]: def zscore(group):
    ...:     return (group-group.mean())/group.std()
    ...:


In [87]: df_stand=by_industry.apply(zscore)


In [88]: df_stand.groupby(industries).agg(['mean','std'])


 by_industry.apply(lambda x: zscore(x.rank()))


分组因子暴露


In [90]: from numpy.random import rand


In [91]: fac1,fac2,fac3=np.random.rand(3,1000)


 ticker_subset=tickers.take(np.random.permutation(N)[:1000])


因子加权及噪声
 port=Series(0.7*fac1-1.2*fac2+0.3*fac3+rand(1000),index=tikcer_subset)
 factors=DataFrame({'f1':fac1,'f2':fac2,'f3':fac3},index=ticker_subset)


factors.corrwith(port)
计算因子暴露的标准方式是最小二乘回归,使用pandas.ols 
pd.ols(y=port,x=factors).beta


def beta_exposure(chunk,factors=None):
    return pd.ols(y=chunk,x=factors).beta
by_ind=port.groupby(industries)
exposures=by_ind.apply(beta_exposure,factors=factors)
exposures.unstack()
十分位和四分位分析
vol=pd.rolling_std(returns,250,min_periods=200)*np.sqrt(250)
def sharpe(rets,ann=250):
    return retslmean()/rets.std() *np.sqrt(ann)
trade_rets.groupby(pd.qcut(vol,4)).agg(sharpe)
示例应用
移动相关系数与线性回归
pd.rolling_corr(aapl_rets,msft_rets,250).plot()
他不能获动态差异性,最小二乘回归提供李毅中一个变量与一个或多个变量之间动态建模方法
mode=pd.ols(y=aapl_rets,x={'MSFT':msft_rets},window=250)
mode.beta['MSFT'].plot()
Numpy高级应用
ndarray:一个指向数组的指针,数据类型, 一个表示数组形状(shape)的元组,一个跨度元组(stride) 包含从一个唯独到下一个的距离
In [97]: np.ones((10,5)).shape
Out[97]: (10, 5)


In [100]: np.ones((3,4,5),dtype=np.float64).strides
Out[100]: (160, 40, 8)
numpy数据类型体系
dtype有超类,比如np.integer和np.floating
ints=np.ones(10,dtype=np.uint16)
np.issubdtype(ints.dtype,np.integer)


In [101]: np.float64.mro()  mro方法查看所有父类
Out[101]:
[numpy.float64,
 numpy.floating,
 numpy.inexact,
 numpy.number,
 numpy.generic,
 float,
 object]


数组重塑
In [102]: arr=np.arange(8)


In [103]: arr
Out[103]: array([0, 1, 2, 3, 4, 5, 6, 7])


In [104]: arr.reshape((4,2))
Out[104]:
array([[0, 1],
       [2, 3],
       [4, 5],
       [6, 7]])


In [105]: arr.reshape((4,2)).reshape((2,4))
Out[105]:
array([[0, 1, 2, 3],
       [4, 5, 6, 7]])


作为参数形状的其中一维可以是-1,它表示该维度的大小由数据本身推断而来
In [106]: arr=np.arange(15)


In [107]: arr.reshape((5,-1))
Out[107]:
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14]])
In [109]: other_arr=np.ones((3,5))  数组的shape 是一个元组,可以传入reshape


In [110]: other_arr.shape
Out[110]: (3, 5)


arr.reshape(other_arr.shape)


与reshape将一维数组转化为多维数组的运算过程相反的过程称为扁平化 或散开 flattening or  raveling
arr=np.arange(15).(5,3))
In [111]: arr=np.arange(15).reshape((5,3))


In [112]: arr.ravel()
Out[112]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])
flatten方法的行为类似于ravel,只不过返回数据的副本
C和Fortran顺序
像reshape和reval这样的函数,可以接受一个数组存放顺序的order参数,一般是‘C’or 'F'
In [113]: arr=np.arange(12).reshape((3,4))


In [114]: arr
Out[114]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])


In [115]: arr.ravel()
Out[115]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])


In [116]: arr.ravel('F')
Out[116]: array([ 0,  4,  8,  1,  5,  9,  2,  6, 10,  3,  7, 11])


数组的合并和拆分
In [117]: arr1=np.array([[1,2,3],[4,5,6]])


In [118]: arr2=np.array([[7,8,9],[10,11,12]])


In [119]: np.concatenate([arr1,arr2],axis=0)
Out[119]:
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12]])


In [120]: np.concatenate([arr1,arr2],axis=1)
Out[120]:
array([[ 1,  2,  3,  7,  8,  9],
       [ 4,  5,  6, 10, 11, 12]])


也可以用方便的方法 vstack, hstack
In [121]: np.vstack((arr1,arr2))
Out[121]:
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12]])


In [122]: np.hstack((arr1,arr2))
Out[122]:
array([[ 1,  2,  3,  7,  8,  9],
       [ 4,  5,  6, 10, 11, 12]])


Split用于将一个数组沿指定轴分为多个数组
first,second,third=np.split(arr,[1,3])


堆叠辅助类:r_和c_
np.c_[np.r_[arr1,arr2],arr]


In [124]: np.c_[1:6,-10:-5]
Out[124]:
array([[  1, -10],
       [  2,  -9],
       [  3,  -8],
       [  4,  -7],
       [  5,  -6]])
元素的重复操作:tile 和repeat


In [127]: arr=np.arange(3)


In [128]: arr.repeat(3)
Out[128]: array([0, 0, 0, 1, 1, 1, 2, 2, 2])
arr.repeat(2,axis=0)
多维数组沿指定轴重复
arr.repeat(2,axis=0)
arr.repeat([2,3],axis=0)
tile 是沿指定轴堆叠数组的副本。注意和repeat的区别,即重复和堆叠的区别
np.tile(arr,(3,2))
In [130]: arr=rand(2,2)


In [131]: arr
Out[131]:
array([[ 0.40255232,  0.19530132],
       [ 0.42589875,  0.460811  ]])


In [132]: arr.repeat([2,3],axis=0)
Out[132]:
array([[ 0.40255232,  0.19530132],
       [ 0.40255232,  0.19530132],
       [ 0.42589875,  0.460811  ],
       [ 0.42589875,  0.460811  ],
       [ 0.42589875,  0.460811  ]])


In [133]: np.tile(arr,(2,1))
Out[133]:
array([[ 0.40255232,  0.19530132],
       [ 0.42589875,  0.460811  ],
       [ 0.40255232,  0.19530132],
       [ 0.42589875,  0.460811  ]])








花式索引的等价函数: take和put
In [136]: arr=np.arange(10)*100


In [137]: inds=[7,1,2,6]


In [138]: arr[inds]
Out[138]: array([700, 100, 200, 600])


In [139]: arr.take(inds)
Out[139]: array([700, 100, 200, 600])


In [140]: arr.put(inds,42)  put的作用???
In [141]: arr
Out[141]: array([  0,  42,  42, 300, 400, 500,  42,  42, 800, 900])


In [142]: arr.put(inds,[40,41,42,43])


In [143]: arr
Out[143]: array([  0,  41,  42, 300, 400, 500,  43,  40, 800, 900])


arr.take(inds,axis=1)


广播(broadcasting)
如果两个数组的后缘维度的轴长相符或其中一方的长度为1,则认为它们是广播兼容的,广播会在缺失或长度为1的唯独上进行


低纬度的值是可以被广播到数组的任意维度的


沿其它轴广播
插入轴,np.newaxis属性及全切片来插入新轴
In [151]: arr=np.zeros((4,4))


In [152]: arr_3d=arr[:,np.newaxis,:]
In [156]: arr_3d.shape
Out[156]: (4, 1, 4)
In [157]: arr_1d=np.random.normal(size=3)


In [158]: arr_1d
Out[158]: array([ 0.84683331, -1.16065107, -0.36437986])


In [159]: arr_1d[:,np.newaxis]
Out[159]:
array([[ 0.84683331],
       [-1.16065107],
       [-0.36437986]])


如下三维数组,对轴2进行距平化
In [160]: arr=randn(3,4,5)


In [161]: arr
Out[161]:
array([[[-0.7655862 ,  1.72634777,  0.93045475, -2.25213106,  0.17861805],
        [-0.0028555 , -1.45961748,  0.14767238, -0.67441824,  0.59563923],
        [ 1.60785344, -0.46488842, -0.69169265,  0.88729479, -0.44788723],
        [ 1.47435324, -2.16741308,  1.22306068, -0.58544606,  1.01258343]],


       [[ 0.24973136,  0.77947498,  0.268103  ,  0.37375195,  1.023678  ],
        [-1.26045699, -0.51076475,  2.04473879,  2.06870932,  0.77844536],
        [-0.6732083 , -1.39300166, -0.78671342, -1.76692615, -1.31159859],
        [ 0.56496062, -0.148088  , -0.38211876,  0.41182366, -1.29733898]],


       [[-0.7738298 ,  1.22118752,  0.98363775, -0.86361563, -0.18191885],
        [-0.60909452, -1.23791258, -1.54172115,  0.26634691, -1.26016078],
        [ 0.89119805, -0.30730155,  1.05434599, -1.32388163,  0.5377566 ],
        [ 1.62214262,  0.42940401,  0.94222834, -0.34994294,  0.19546451]]])


In [162]: depth_means=arr.mean(2)


In [163]: depth_means
Out[163]:
array([[-0.03645934, -0.27871592,  0.17813599,  0.19142764],
       [ 0.53894786,  0.62413435, -1.18628962, -0.17015229],
       [ 0.0770922 , -0.87650842,  0.17042349,  0.56785931]])


In [164]: demeaned=arr-depth_means[:,:,np.newaxis]


通过广播设置数组的值
In [166]: col=np.array([2,1,3,4])


In [167]: arr[:]=col[:,np.newaxis]


In [168]: arr
Out[168]:
array([[[ 2.,  2.,  2.,  2.,  2.],
        [ 1.,  1.,  1.,  1.,  1.],
        [ 3.,  3.,  3.,  3.,  3.],
        [ 4.,  4.,  4.,  4.,  4.]],


       [[ 2.,  2.,  2.,  2.,  2.],
        [ 1.,  1.,  1.,  1.,  1.],
        [ 3.,  3.,  3.,  3.,  3.],
        [ 4.,  4.,  4.,  4.,  4.]],


       [[ 2.,  2.,  2.,  2.,  2.],
        [ 1.,  1.,  1.,  1.,  1.],
        [ 3.,  3.,  3.,  3.,  3.],
        [ 4.,  4.,  4.,  4.,  4.]]])


ufunc高级应用
In [169]: arr=np.arange(10)


In [170]: np.add.reduce(arr)
Out[170]: 45


In [171]: arr.sum()
Out[171]: 45


np.logical_and.reduce(arr[:,:-1]<arr[:,1:],axis=1)
logical_and_reduce跟all方法是等价
accumulate和reduce 就像cumsum跟sum的关系
outer用于计算两个数组的叉积
自定义ufunc
numpy.frompyfunc接受一个Python函数及两个分别表示输入参数数量的整数
In [174]: def add_element(x,y):
     ...:     return x+y
     ...:


In [175]: add_them=np.frompyfunc(add_element,2,1)


In [176]: add_them(np.arange(8),np.arange(8))
Out[176]: array([0, 2, 4, 6, 8, 10, 12, 14], dtype=object)


add_them1=np.vectorize(add_element,otypes=[np.float64])
In [179]: add_them1(np.arange(8),np.arange(8))
Out[179]: array([  0.,   2.,   4.,   6.,   8.,  10.,  12.,  14.])


结构化和记录式数组


In [180]: dtype=[('x',np.float64),('y',np.int32)]


In [181]: sarr=np.array([(1.5,6),(np.pi,-2)],dtype=dtype)


In [182]: sarr
Out[182]:
array([( 1.5       ,  6), ( 3.14159265, -2)],
      dtype=[('x', '<f8'), ('y', '<i4')])


嵌套的type和多维字段’
机构化数组的操作, numpy.lib.recfunctions
间接排序 argsort  lexsort
numpy.searchsorted 在有序数组中查找元素
Numpy的matrix类
np.dot(y.T,np.dot(X,y))
内存映像文件
性能

































  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张博208

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值