NumPy 基础:数组和矢量计算
pandas 入门
数据加载、存储与文件格式
第4章 NumPy 基础:数组和矢量计算
4.1 NumPy的ndarray:一种多维数组对象
ndarray
是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的。每个数组都有一个shape
(一个表示各维度大小的元组)和一个dtype
(一个用于说明数组数据类型的对象)
array
函数接受一切序列型的对象(包括其他数组),然后产生一个新的含有传入数据的NumPy数组。
1 2 data1 = [6 , 7.5 , 8 , 0 , 1 ] arr1 = np.array(data1)
嵌套序列(比如由一组等长列表组成的列表)将会被转换为一个多维数组。
由于NumPy关注的是数值计算,因此,如果没有特别指定,数据类型基本都是float64(浮点数)。
dtype
(数据类型)对象将含有的ndarray一块内存解释为特定数据类型。
使用astype
方法进行类型转换:
1 float_arr = arr.astype(np.float64)
可以用astype
方法把数字字符串转换成数字。
1 2 3 4 In [64 ]: arr[5 :8 ] = 12 In [65 ]: arr Out[65 ]: array([ 0 , 1 , 2 , 3 , 4 , 12 , 12 , 12 , 8 , 9 ])
当你将一个标量值赋值给一个切片时,该值会自动传播到整个选区。跟列表最重要的区别在于,数组切片是原始数组的引用 。这意味着数据不会被复制,引用上的任何修改都会直接反映到源数组上。
高维数组的访问:
1 2 3 4 5 In [74 ]: arr2d[0 ][2 ] Out[74 ]: 3 In [75 ]: arr2d[0 , 2 ] Out[75 ]: 3
高维数组切片的例子:arr2d[3][3]
是二维数组,arr2d[:2, 1:]
选取前两行、后两列,arr2d[:, :1]
选取第一列,arr2d[:2, 2]
选取第三列的前两行。
可以通过布尔数组选取某个轴,但是数组长度必须和轴的长度相等。
通过布尔型索引选取数组中的数据,将总是创建数据的副本。
传入一个用于指定顺序的整数列表或ndarray
来以特定顺序选取某个轴。一次传入多个索引数组时返回的是一个一维数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 In [123 ]: arr Out[123 ]: 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 [124 ]: arr[[1 , 5 , 7 , 2 ], [0 , 3 , 1 , 2 ]] Out[124 ]: array([ 4 , 23 , 29 , 10 ]) In [125 ]: arr[[1 , 5 , 7 , 2 ]][:, [0 , 3 , 1 , 2 ]] Out[125 ]: array([[ 4 , 7 , 5 , 6 ], [20 , 23 , 21 , 22 ], [28 , 31 , 29 , 30 ], [ 8 , 11 , 9 , 10 ]])
T
属性返回数组的转置,高维数组采用transpose
方法,传入由轴编号组成的元组对这些轴进行转置。swapaxes
传入一对轴的编号。
4.2 通用函数:快速的元素级数组函数
Ufuncs可以接受一个out可选参数,这样就能在数组原地进行操作:np.sqrt(arr, arr)
4.3 利用数组进行数据处理
numpy.where
函数是三元表达式x if condition else y
的矢量化版本。
根据cond中的值选取xarr和yarr的值:
1 np.where(cond, xarr, yarr)
np.where
的第二个和第三个参数数组大小可以不相等,甚至可以是标量值。
mean
和sum
这类的函数可以接受一个axis
选项参数,用于计算该轴向上的统计值, 最终结果是一个少一维的数组。
在多维数组中,累加函数(如cumsum
)返回的是同样大小的数组,但是会根据每个低维的切片沿着标记轴计算部分聚类。
sum
方法用于对布尔数组中的True
计数,any
方法检测是否存在True
,all
方法判断是否全为True
。
sort
方法可以排序,传入参数以按照某一个轴排序。
unqiue
方法找出数组中的唯一值并返回已排序的结果。函数np.in1d
用于测试一个数组中的值在另一个数组中的是否出现,返回一个布尔数组。
np.save
和np.load
用于读写磁盘数组数据。默认情况下,数组是以未压缩的原始二进制格式保存在扩展名为.npy的文件中的。如果文件路径末尾没有扩展名.npy,则该扩展名会被自动加上。
1 2 np.save('some_array' , arr) np.load('some_array.npy' )
通过np.savez
可以将多个数组保存到一个未压缩文件中,将数组以关键字参数的形式传入即可:
1 In [216 ]: np.savez('array_archive.npz' , a=arr, b=arr)
加载.npz文件时,你会得到一个类似字典的对象,该对象会对各个数组进行延迟加载:
1 2 3 4 In [217 ]: arch = np.load('array_archive.npz' ) In [218 ]: arch['b' ] Out[218 ]: array([0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ])
如果要将数据压缩,可以使用np.savez_compressed
。
4.5 线性代数
通过*对两个二维数组相乘得到的是 一个元素级的积,而不是一个矩阵点积。
通过x.dot(y)
或np.dot(x, y)
或x @ y
实现矩阵乘法。
4.6 伪随机数生成
np.random.seed
会更改全局种子,np.random.RandomState
函数用给定种子创建一个新的随机数生成器:
1 2 3 In [245 ]: rng = np.random.RandomState(1234 ) In [246 ]: rng.randn(10 )
第5章 pandas 入门
5.1 pandas的数据结构介绍
Series
是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。
1 2 3 4 5 6 7 8 9 In [11 ]: obj = pd.Series([4 , 7 , -5 , 3 ]) In [12 ]: obj Out[12 ]: 0 4 1 7 2 -5 3 3 dtype: int64
Series
的字符串表现形式为:索引在左边,值在右边。通过Series
的values
和index
属性获取其数组表示形式和索引对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 In [15 ]: obj2 = pd.Series([4 , 7 , -5 , 3 ], index=['d' , 'b' , 'a' , 'c' ]) In [16 ]: obj2 Out[16 ]: d 4 b 7 a -5 c 3 dtype: int64 In [17 ]: obj2.index Out[17 ]: Index(['d' , 'b' , 'a' , 'c' ], dtype='object' ) In [18 ]: obj2['a' ] Out[18 ]: -5 In [19 ]: obj2['d' ] = 6 In [20 ]: obj2[['c' , 'a' , 'd' ]] Out[20 ]: c 3 a -5 d 6 dtype: int64
使用NumPy函数或类似NumPy的运算(如根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引值的链接。还可以将Series
看成是一个定长的有序字典,因为它是索引值到数据值的一个映射。如果数据被存放在一个Python字典中,也可以直接通过这个字典来创建Series
。
通过传入排好序的键的序列以改变顺序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 In [26 ]: sdata = {'Ohio' : 35000 , 'Texas' : 71000 , 'Oregon' : 16000 , 'Utah' : 5000 } In [27 ]: obj3 = pd.Series(sdata) In [28 ]: obj3 Out[28 ]: Ohio 35000 Texas 71000 Oregon 16000 Utah 5000 dtype: int64 In [29 ]: states = ['California' , 'Ohio' , 'Oregon' , 'Texas' ] In [30 ]: obj4 = pd.Series(sdata, index=states) In [31 ]: obj4 Out[31 ]: California NaN Ohio 35000.0 Oregon 16000.0 Texas 71000.0 dtype: float64
'California'没有对应的值,用NaN
表示缺失值;'Utah'没有出现。
用isnull
或notnull
函数或者Series
的isnull
方法判断是否缺失:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 In [32 ]: pd.isnull(obj4) Out[32 ]: California True Ohio False Oregon False Texas False dtype: bool In [34 ]: obj4.notnull() Out[34 ]: California False Ohio True Oregon True Texas True dtype: bool
根据运算的索引标签自动对齐数据:
1 2 3 4 5 6 7 8 In [37 ]: obj3 + obj4 Out[37 ]: California NaN Ohio 70000.0 Oregon 32000.0 Texas 142000.0 Utah NaN dtype: float64
Series
对象本身及其索引都有一个name
属性。
Series
的索引可以通过赋值的方式就地修改:
1 obj.index = ['Bob' , 'Steve' , 'Jeff' , 'Ryan' ]
DataFrame
是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame
既有行索引也有列索引,它可以被看做由Series
组成的字典(共用同一个索引)。
直接传入一个由等长列表或NumPy数组组成的字典来创建DataFrame
:
1 2 3 4 data = {'state' : ['Ohio' , 'Ohio' , 'Ohio' , 'Nevada' , 'Nevada' , 'Nevada' ], 'year' : [2000 , 2001 , 2002 , 2001 , 2002 , 2003 ], 'pop' : [1.5 , 1.7 , 3.6 , 2.4 , 2.9 , 3.2 ]} frame = pd.DataFrame(data)
1 2 3 4 5 6 7 8 9 In [45 ]: frame Out[45 ]: state year pop 0 Ohio 2000 1.5 1 Ohio 2001 1.7 2 Ohio 2002 3.6 3 Nevada 2001 2.4 4 Nevada 2002 2.9 5 Nevada 2003 3.2
对于特别大的DataFrame
,head
方法会选取前五行。如果指定了列序列,则DataFrame
的列就会按照指定顺序进行排列:
1 pd.DataFrame(data, columns=['year' , 'state' , 'pop' ])
如果传入的列在数据中找不到,就会在结果中产生缺失值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 In [48 ]: frame2 = pd.DataFrame(data, columns=['year' , 'state' , 'pop' , 'debt' ], ...: index=['one' , 'two' , 'three' , 'four' , ...: 'five' , 'six' ]) ...: In [49 ]: frame2 Out[49 ]: 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 six 2003 Nevada 3.2 NaN In [50 ]: frame2.columns Out[50 ]: Index(['year' , 'state' , 'pop' , 'debt' ], dtype='object' )
通过类似字典标记的方式或属性的方式,可以将DataFrame
的列获取为一个Series
:
1 2 frame2['state' ] frame2.year
返回的Series
拥有原DataFrame
相同的索引,且其name
属性也已经被相应地设置好了。
通过loc
属性获取行:
1 2 3 4 5 6 7 In [53 ]: frame2.loc['three' ] Out[53 ]: year 2002 state Ohio pop 3.6 debt NaN Name: three, dtype: object
通过赋值修改列:
1 2 3 frame2['debt' ] = 16.5 frame2['debt' ] = np.arange(6. ) frame2['debt' ] = pd.Series([-1.2 , -1.5 , -1.7 ], index=['two' , 'four' , 'five' ])
将列表或数组赋值给某个列时,其长度必须跟DataFrame
的长度相匹配。如果赋值的是一个Series
,就会精确匹配DataFrame
的索引,所有的空位都将被填上缺失值。
关键字del
用于删除列。
如果嵌套字典传给DataFrame
,pandas就会被解释为:外层字典的键作为列,内层键则作为行索引:
1 2 3 4 5 6 7 8 9 10 11 In [65 ]: pop = {'Nevada' : {2001 : 2.4 , 2002 : 2.9 }, ...: 'Ohio' : {2000 : 1.5 , 2001 : 1.7 , 2002 : 3.6 }} In [66 ]: frame3 = pd.DataFrame(pop) In [67 ]: frame3 Out[67 ]: Nevada Ohio 2001 2.4 1.7 2002 2.9 3.6 2000 NaN 1.5
内层字典的键会被合并、排序以形成最终的索引。如果明确指定了索引,则不会这样:
1 pd.DataFrame(pop, index=[2001 , 2002 , 2003 ])
DataFrame
的index
和columns
也有name
属性。
values
属性会以二维ndarray
的形式返回DataFrame
中的数据。如果DataFrame
各列的数据类型不同,则值数组的dtype
就会选用能兼容所有列的数据类型。
构建Series
或DataFrame
时,所用到的任何数组或其他序列的标签都会被转换成一个Index
对象。Index
对象是不可变的。Index
的功能也类似一个固定大小的集合,但是可以包含重复的标签,选择重复的标签,会显示所有的结果。
5.2 基本功能
Series
的reindex
方法将会根据新索引进行重排。如果某个索引值当前不存在,就引入缺失值。method
选项实现插值,例如,使用ffill
可以实现前向值填充。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 In [95 ]: obj3 = pd.Series(['blue' , 'purple' , 'yellow' ], index=[0 , 2 , 4 ]) In [96 ]: obj3 Out[96 ]: 0 blue2 purple4 yellowdtype: object In [97 ]: obj3.reindex(range (6 ), method='ffill' ) Out[97 ]: 0 blue1 blue2 purple3 purple4 yellow5 yellowdtype: object
重新索引列:
1 frame.reindex(columns=states)
drop
方法返回的是一个在指定轴上删除了指定值的新对象。
默认删除行,通过制定axis
删除列:
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 32 33 In [110 ]: data = pd.DataFrame(np.arange(16 ).reshape((4 , 4 )), ...: index=['Ohio' , 'Colorado' , 'Utah' , 'New York' ], ...: columns=['one' , 'two' , 'three' , 'four' ]) In [111 ]: data Out[111 ]: one two three four Ohio 0 1 2 3 Colorado 4 5 6 7 Utah 8 9 10 11 New York 12 13 14 15 In [112 ]: data.drop(['Colorado' , 'Ohio' ]) Out[112 ]: one two three four Utah 8 9 10 11 New York 12 13 14 15 In [113 ]: data.drop('two' , axis=1 ) Out[113 ]: one three four Ohio 0 2 3 Colorado 4 6 7 Utah 8 10 11 New York 12 14 15 In [114 ]: data.drop(['two' , 'four' ], axis='columns' ) Out[114 ]: one three Ohio 0 2 Colorado 4 6 Utah 8 10 New York 12 14
选项inplace=True
使得就地删除。
既可以使用数字索引,也可以使用index
:
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 [117 ]: obj = pd.Series(np.arange(4. ), index=['a' , 'b' , 'c' , 'd' ]) In [118 ]: obj Out[118 ]: a 0.0 b 1.0 c 2.0 d 3.0 dtype: float64 In [119 ]: obj['b' ] Out[119 ]: 1.0 In [120 ]: obj[1 ] Out[120 ]: 1.0 In [124 ]: obj[obj < 2 ] Out[124 ]: a 0.0 b 1.0 dtype: float64 In [126 ]: obj['b' :'c' ] = 5 In [127 ]: obj Out[127 ]: a 0.0 b 5.0 c 5.0 d 3.0 dtype: float64
利用标签的切片运算是一个闭区间。
用一个值或序列对DataFrame
进行索引选取一个或多个列 ;通过切片或布尔型数组选取行 ;通过布尔型DataFrame
索引:
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 32 33 34 35 36 37 38 39 40 41 42 In [128 ]: data = pd.DataFrame(np.arange(16 ).reshape((4 , 4 )), ...: index=['Ohio' , 'Colorado' , 'Utah' , 'New York' ], ...: columns=['one' , 'two' , 'three' , 'four' ]) In [131 ]: data[['three' , 'one' ]] Out[131 ]: three one Ohio 2 0 Colorado 6 4 Utah 10 8 New York 14 12 In [132 ]: data[:2 ] Out[132 ]: one two three four Ohio 0 1 2 3 Colorado 4 5 6 7 In [133 ]: data[data['three' ] > 5 ] Out[133 ]: one two three four Colorado 4 5 6 7 Utah 8 9 10 11 New York 12 13 14 15 In [134 ]: data < 5 Out[134 ]: one two three four Ohio True True True True Colorado True False False False Utah False False False False New York False False False False In [135 ]: data[data < 5 ] = 0 In [136 ]: data Out[136 ]: one two three four Ohio 0 0 0 0 Colorado 0 5 6 7 Utah 8 9 10 11 New York 12 13 14 15
如果轴索引含有整数,数据选取总会使用标签。为了更准确,请使用loc
(标签)或iloc
(整数)
将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。自动的数据对齐操作在不重叠的索引处引入了NaN
值。缺失值会在算术运算过程中传播。
当一个对象中某个轴标签在另一 个对象中找不到时填充一个特殊值:
1 df1.add(df2, fill_value=0 )
reindex
也可以指定填充值。
DataFrame
和Series
之间的算术运算会将Series
的索引匹配到DataFrame
的列,然后沿着行一直向下广播:
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 In [179 ]: frame = pd.DataFrame(np.arange(12. ).reshape((4 , 3 )), ...: columns=list ('bde' ), ...: index=['Utah' , 'Ohio' , 'Texas' , 'Oregon' ]) In [180 ]: series = frame.iloc[0 ] In [181 ]: frame Out[181 ]: b d e Utah 0.0 1.0 2.0 Ohio 3.0 4.0 5.0 Texas 6.0 7.0 8.0 Oregon 9.0 10.0 11.0 In [182 ]: series Out[182 ]: b 0.0 d 1.0 e 2.0 Name: Utah, dtype: float64 In [183 ]: frame - series Out[183 ]: b d e Utah 0.0 0.0 0.0 Ohio 3.0 3.0 3.0 Texas 6.0 6.0 6.0 Oregon 9.0 9.0 9.0
如果某个索引值在DataFrame
的列或Series
的索引中找不到,则参与运算的两个对象就会被重新索引以形成并集
如果你希望匹配行且在列上广播,则必须使用算术运算方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 In [186 ]: series3 = frame['d' ] In [188 ]: series3 Out[188 ]: Utah 1.0 Ohio 4.0 Texas 7.0 Oregon 10.0 Name: d, dtype: float64 In [189 ]: frame.sub(series3, axis='index' ) Out[189 ]: b d e Utah -1.0 0.0 1.0 Ohio -1.0 0.0 1.0 Texas -1.0 0.0 1.0 Oregon -1.0 0.0 1.0
NumPy的ufuncs
也可用于操作pandas对象。
DataFrame
的apply
方法实现将函数应用到由各列或行所形成的一维数组上:
1 2 3 4 5 6 7 8 9 10 11 In [190 ]: frame = pd.DataFrame(np.random.randn(4 , 3 ), columns=list ('bde' ), ...: index=['Utah' , 'Ohio' , 'Texas' , 'Oregon' ]) In [193 ]: f = lambda x: x.max () - x.min () In [194 ]: frame.apply(f) Out[194 ]: b 1.379224 d 2.469903 e 2.369424 dtype: float64
传递axis='columns'
使得函数在每行执行。
应用元素级的函数,使用DataFrame
的applymap
方法、Series
的map
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 In [198 ]: format = lambda x: '%.2f' % x In [199 ]: frame.applymap(format ) Out[199 ]: b d e Utah -1.06 -0.73 -0.42 Ohio -0.24 1.74 -1.11 Texas -0.80 0.51 1.10 Oregon -1.61 1.10 1.26 In [200 ]: frame['e' ].map (format ) Out[200 ]: Utah -0.42 Ohio -1.11 Texas 1.10 Oregon 1.26 Name: e, dtype: object
对行或列索引进行排序(按字典顺序),可使用sort_index
方法,它将返回一个已排序的新对象。默认对行排序,axis=1
选项使得对列排序;默认按升序排序,ascending=False
选项使得按降序排序。
1 2 3 4 5 6 7 8 9 In [201 ]: obj = pd.Series(range (4 ), index=['d' , 'a' , 'b' , 'c' ]) In [202 ]: obj.sort_index() Out[202 ]: a 1 b 2 c 3 d 0 dtype: int64
按值对Series
进行排序,使用sort_values
方法。缺失值放到末尾。对DataFrame
排序,传入列的名字,或者传入列的名字的列表(在前的优先级高)。
1 2 3 4 5 6 7 8 9 In [207 ]: obj = pd.Series([4 , 7 , -3 , 2 ]) In [208 ]: obj.sort_values() Out[208 ]: 2 -3 3 2 0 4 1 7 dtype: int64
rank
方法给出排名,对于相同元素来说,默认取所有排名的平均值。ascending=False
选项使得按降序排名。对于DataFrame
,可以使用axis
选项。
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 [215 ]: obj = pd.Series([7 , -5 , 7 , 4 , 2 , 0 , 4 ]) In [216 ]: obj.rank() Out[216 ]: 0 6.5 1 1.0 2 6.5 3 4.5 4 3.0 5 2.0 6 4.5 dtype: float64 In [219 ]: frame = pd.DataFrame({'b' : [4.3 , 7 , -3 , 2 ], 'a' : [0 , 1 , 0 , 1 ], ...: 'c' : [-2 , 5 , 8 , -2.5 ]}) In [220 ]: frame Out[220 ]: b a c 0 4.3 0 -2.0 1 7.0 1 5.0 2 -3.0 0 8.0 3 2.0 1 -2.5 In [221 ]: frame.rank(axis='columns' ) Out[221 ]: b a c 0 3.0 2.0 1.0 1 3.0 1.0 2.0 2 1.0 2.0 3.0 3 3.0 2.0 1.0
以下是可用的method
选项:
索引的is_unique
属性可以告诉你它的值是否是唯一的。
如果选取Series
的某个索引对应多个值,则返回一个Series
;而对应单个值的,则返回一个标量值。对于DataFrame
,如果选取某个索引对应多个值,则返回一个DataFrame
。
5.3 汇总和计算描述统计
Series
的corr
方法用于计算两个Series
中重叠的、非NA
的、按索引对齐的值的相关系数。与此类似,cov
用于计算协方差。DataFrame
的corr
和cov
方法将以DataFrame
的形式分别返回完整的相关系数或协方差矩阵。
利用DataFrame
的corrwith
方法,你可以计算其列或行跟另一个Series
或DataFrame
之间的相关系数。传入一个Series
将会返回一个相关系数值Series
(针对各列进行计算)。传入一个DataFrame
则会计算按列名配对的相关系数。传入axis='columns'
即可按行进行计算。
unique
方法得到Series
中的唯一值数组。value_counts
方法用于计算一个Series
中各值出现的频率。结果Series
是按值频率降序排列的。value_counts
还是一个顶级pandas
方法,可用于任何数组或序列:
1 2 3 4 5 6 7 8 9 In [251 ]: obj = pd.Series(['c' , 'a' , 'd' , 'a' , 'a' , 'b' , 'b' , 'c' , 'c' ]) In [255 ]: pd.value_counts(obj.values, sort=False ) Out[255 ]: a 3 d 1 b 2 c 3 dtype: int64
isin
方法返回一个布尔型Series
,用于判断矢量化集合的成员资格:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 In [257 ]: mask = obj.isin(['b' , 'c' ]) In [258 ]: mask Out[258 ]: 0 True 1 False 2 False 3 False 4 False 5 True 6 True 7 True 8 True dtype: bool In [259 ]: obj[mask] Out[259 ]: 0 c5 b6 b7 c8 cdtype: object
Index.get_indexer
方法给你一个索引数组,从可能包含重复值的数组到另一个不包含重复值的数组。
1 2 3 4 5 6 In [260 ]: to_match = pd.Series(['c' , 'a' , 'b' , 'b' , 'c' , 'a' ]) In [261 ]: unique_vals = pd.Series(['c' , 'b' , 'a' ]) In [262 ]: pd.Index(unique_vals).get_indexer(to_match) Out[262 ]: array([0 , 2 , 1 , 1 , 0 , 2 ])
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 In [263 ]: data = pd.DataFrame({'Qu1' : [1 , 3 , 4 , 3 , 4 ], ...: 'Qu2' : [2 , 3 , 1 , 2 , 3 ], ...: 'Qu3' : [1 , 5 , 2 , 4 , 4 ]}) In [264 ]: data Out[264 ]: Qu1 Qu2 Qu3 0 1 2 1 1 3 3 5 2 4 1 2 3 3 2 4 4 4 3 4 In [265 ]: result = data.apply(pd.value_counts).fillna(0 ) In [266 ]: result Out[266 ]: Qu1 Qu2 Qu3 1 1.0 1.0 1.0 2 0.0 2.0 1.0 3 2.0 2.0 0.0 4 2.0 0.0 2.0 5 0.0 0.0 1.0
第6章 数据加载、存储与文件格式
6.1 读写文本格式的数据
读入.csv:
1 2 df = pd.read_csv('examples/ex1.csv' ) pd.read_table('examples/ex1.csv' , sep=',' )
没有标题行:
1 2 pd.read_csv('examples/ex2.csv' , header=None ) pd.read_csv('examples/ex2.csv' , names=['a' , 'b' , 'c' , 'd' , 'message' ])
指定索引:
1 2 names = ['a' , 'b' , 'c' , 'd' , 'message' ] pd.read_csv('examples/ex2.csv' , names=names, index_col='message' )
层次化索引:
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 In [17 ]: !cat examples/csv_mindex.csv key1,key2,value1,value2 one,a,1 ,2 one,b,3 ,4 one,c,5 ,6 one,d,7 ,8 two,a,9 ,10 two,b,11 ,12 two,c,13 ,14 two,d,15 ,16 In [18 ]: parsed = pd.read_csv('examples/csv_mindex.csv' , ....: index_col=['key1' , 'key2' ]) In [19 ]: parsed Out[19 ]: 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
对于不规整的表格,使用正则表达式:
1 2 3 4 5 6 7 8 9 In [20 ]: list (open ('examples/ex3.txt' )) Out[20 ]: [' A B C\n' , 'aaa -0.264438 -1.026059 -0.619500\n' , 'bbb 0.927272 0.302904 -0.032399\n' , 'ccc -0.264273 -0.386314 -0.217601\n' , 'ddd -0.871858 -0.348382 1.100491\n' ] In [21 ]: result = pd.read_table('examples/ex3.txt' , sep='\s+' )
跳过第一行、第三行和第四行:
1 pd.read_csv('examples/ex4.csv' , skiprows=[0 , 2 , 3 ])
pandas能够自动识别缺失数据(空字符串或者标记值比如NA
或NULL
)
用一个列表或者集合的字符串表示标记值,各个列可以使用不同的标记值:
1 2 3 4 5 6 7 8 9 10 In [29 ]: result = pd.read_csv('examples/ex5.csv' , na_values=['NULL' ]) In [31 ]: sentinels = {'message' : ['foo' , 'NA' ], 'something' : ['two' ]} In [32 ]: pd.read_csv('examples/ex5.csv' , na_values=sentinels) Out[32 ]: something a b c d message 0 one 1 2 3.0 4 NaN1 NaN 5 6 NaN 8 world2 three 9 10 11.0 12 NaN
设置最大显示行数:
1 pd.options.display.max_rows = 10
nrows
选项指定读取多少行。
逐块读取:
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 In [37 ]: chunker = pd.read_csv('examples/ex6.csv' , chunksize=1000 ) In [38 ]: chunker Out[38 ]: <pandas.io.parsers.TextFileReader at 0x7f87a2627d90 > In [39 ]: chunker = pd.read_csv('examples/ex6.csv' , chunksize=1000 ) ...: ...: tot = pd.Series([]) ...: for piece in chunker: ...: tot = tot.add(piece['key' ].value_counts(), fill_value=0 ) ...: ...: tot = tot.sort_values(ascending=False ) In [40 ]: tot[:10 ] Out[40 ]: E 368.0 X 364.0 L 346.0 O 343.0 Q 340.0 M 338.0 J 337.0 F 335.0 K 334.0 H 330.0 dtype: float64
使用to_csv
方法输出到.csv;指定分隔符;指定缺失值的标记;禁用行列的标签;写出部分列:
1 2 3 4 5 data.to_csv('examples/out.csv' ) data.to_csv(sys.stdout, sep='|' ) data.to_csv(sys.stdout, na_rep='NULL' ) data.to_csv(sys.stdout, index=False , header=False ) data.to_csv(sys.stdout, index=False , columns=['a' , 'b' , 'c' ])
Python内置的csv
模块:
1 2 3 import csvf = open ('examples/ex7.csv' ) reader = csv.reader(f)
对这个reader
进行迭代将会为每行产生一个元组(并移除了所有的引号)。
1 2 3 4 5 6 7 8 9 10 In [57 ]: with open ('examples/ex7.csv' ) as f: ...: lines = list (csv.reader(f)) ...: In [58 ]: header, values = lines[0 ], lines[1 :] In [59 ]: data_dict = {h: v for h, v in zip (header, zip (*values))} In [60 ]: data_dict Out[60 ]: {'a' : ('1' , '1' ), 'b' : ('2' , '2' ), 'c' : ('3' , '3' )}
定义csv.Dialect
的一个子类即可定义出新格式(如专门的分隔符、字符串引用约定、行结束符等):
1 2 3 4 5 6 class my_dialect (csv.Dialect ): lineterminator = '\n' delimiter = ';' quotechar = '"' quoting = csv.QUOTE_MINIMAL reader = csv.reader(f, dialect=my_dialect)
或者通过参数传递:
1 reader = csv.reader(f, delimiter='|' )
要手工输出分隔符文件,使用csv.writer
:
1 2 3 4 5 6 with open ('mydata.csv' , 'w' ) as f: writer = csv.writer(f, dialect=my_dialect) writer.writerow(('one' , 'two' , 'three' )) writer.writerow(('1' , '2' , '3' )) writer.writerow(('4' , '5' , '6' )) writer.writerow(('7' , '8' , '9' ))
通过json.loads
即可将JSON字符串转换成Python形式;json.dumps
则将Python对象转换成JSON格式:
1 2 3 import jsonresult = json.loads(obj) asjson = json.dumps(result)
通过传入字典的列表把JSON对象转化成DataFrame
。
pandas.read_json
的默认选项假设JSON数组中的每个对象是表格中的一行:
1 2 3 4 5 6 7 8 9 10 11 12 13 In [68 ]: !cat examples/example.json [{"a" : 1 , "b" : 2 , "c" : 3 }, {"a" : 4 , "b" : 5 , "c" : 6 }, {"a" : 7 , "b" : 8 , "c" : 9 }] In [69 ]: data = pd.read_json('examples/example.json' ) In [70 ]: data Out[70 ]: a b c 0 1 2 3 1 4 5 6 2 7 8 9
将数据从pandas输出到JSON,可以使用to_json
方法。
pandas.read_html
将HTML文件中的表格解析为DataFrame
对象。
6.2 二进制数据格式
pandas对象都有一个用于将数据以pickle
格式保存到磁盘上的to_pickle
方法;使用pandas.read_pickle
读取被pickle化的数据:
1 2 frame.to_pickle('examples/frame_pickle' ) pd.read_pickle('examples/frame_pickle' )
HDF5是一种存储大规模科学数组数据的非常好的文件格式。它可以被作为C标准库,带有许多语言的接口,如Java、Python和MATLAB等。
1 2 3 4 5 6 7 In [92 ]: frame = pd.DataFrame({'a' : np.random.randn(100 )}) In [93 ]: store = pd.HDFStore('mydata.h5' ) In [94 ]: store['obj1' ] = frame In [95 ]: store['obj1_col' ] = frame['a' ]
pandas的ExcelFile
类或pandas.read_excel
函数支持读取存储在Excel 2003(或更高版本)中的表格型数据。
6.3 Web APIs交互
requests
扩展库
6.4 数据库交互