本章是本书中最重要的部分。 现在,我们将开始研究 Pandas 的肉和骨头。 我们首先浏览 NumPy ndarrays
,这是一种不在 Pandas 中而是 NumPy 的数据结构。 NumPy ndarrays
的知识很有用,因为它构成了 Pandas 数据结构的基础。 NumPy 数组的另一个主要优点是它们执行称为向量化的操作,这些操作需要在 Python 数组上遍历/循环的操作要快得多。
我们将在本章中介绍的主题包括:
- 浏览
numpy.ndarray
数据结构。 pandas.Series
:一维(1D)Pandas 数据结构pandas.DatcaFrame
:二维(2D)Pandas 表格数据结构pandas.Panel
:3 维(3D)Pandas 数据结构
在本章中,我将通过使用 IPython(一个基于浏览器的界面,使用户可以交互地向 Python 解释器键入命令)的众多示例来介绍这些资料。 上一章提供了安装 IPython 的说明。
NumPy 库是一个非常重要的包,用于使用 Python 进行数值计算。 其主要功能包括:
numpy.ndarray
类型,同构多维数组- 访问大量数学函数 – 线性代数,统计信息等
- 能够集成 C,C++ 和 Fortran 代码
有关 NumPy 的更多信息,请参见这里。
NumPy 中的主要数据结构是数组类ndarray
。 它是元素的齐次多维(n 维)表,它们像常规数组一样由整数索引。 但是,numpy.ndarray
(也称为numpy.array
)与标准 Python array.array
类不同,后者提供的功能要少得多。 这里提供了有关各种操作的更多信息。
可以通过调用各种 NumPy 方法以多种方式创建 NumPy 数组。
NumPy 数组可以直接通过numpy.array
构造器创建:
In [1]: import numpy as np
In [2]: ar1=np.array([0,1,2,3])# 1 dimensional array
In [3]: ar2=np.array ([[0,3,5],[2,8,7]]) # 2D array
In [4]: ar1
Out[4]: array([0, 1, 2, 3])
In [5]: ar2
Out[5]: array([[0, 3, 5],
[2, 8, 7]])
数组的形状通过ndarray.shape
给出:
In [5]: ar2.shape
Out[5]: (2, 3)
尺寸数量使用ndarray.ndim
获得:
In [7]: ar2.ndim
Out[7]: 2
ndarray.arange
是 Python 的range
函数的 NumPy 版本:In [10]:
产生从 0 到 11 的整数,不包括 12。
In [10]: ar3=np.arange(12); ar3
Out[10]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
In [11]: # start, end (exclusive), step size
ar4=np.arange(3,10,3); ar4
Out[11]: array([3, 6, 9])
ndarray.linspace
在起点和终点之间生成线性均匀间隔的元素:
In [13]:# args - start element,end element, number of elements
ar5=np.linspace(0,2.0/3,4); ar5
Out[13]:array([ 0., 0.22222222, 0.44444444, 0.66666667])
这些函数包括numpy.zeros
,numpy.ones
,numpy.eye
,nrandom.rand
,numpy.random.randn
和numpy.empty
。
在每种情况下,该参数都必须是一个元组。 对于一维数组,您只需指定元素数,而无需元组。
以下命令行说明了该函数:
In [14]:# Produces 2x3x2 array of 1's.
ar7=np.ones((2,3,2)); ar7
Out[14]: array([[[ 1., 1.],
[ 1., 1.],
[ 1., 1.]],
[[ 1., 1.],
[ 1., 1.],
[ 1., 1.]]])
以下命令行说明了该函数:
In [15]:# Produce 4x2 array of zeros.
ar8=np.zeros((4,2));ar8
Out[15]: array([[ 0., 0.],
[ 0., 0.],
[ 0., 0.],
[ 0., 0.]])
以下命令行说明了该函数:
In [17]:# Produces identity matrix
ar9 = np.eye(3);ar9
Out[17]: array([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])
以下命令行说明了该函数:
In [18]: # Create diagonal array
ar10=np.diag((2,1,4,6));ar10
Out[18]: array([[2, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 4, 0],
[0, 0, 0, 6]])
以下命令行说明了该函数:
In [19]: # Using the rand, randn functions
# rand(m) produces uniformly distributed random numbers with range 0 to m
np.random.seed(100) # Set seed
ar11=np.random.rand(3); ar11
Out[19]: array([ 0.54340494, 0.27836939, 0.42451759])
In [20]: # randn(m) produces m normally distributed (Gaussian) random numbers
ar12=np.random.rand(5); ar12
Out[20]: array([ 0.35467445, -0.78606433, -0.2318722 , 0.20797568, 0.93580797])
使用np.empty
创建未初始化的数组比分配np.ones
或np.zeros
(malloc
与cmalloc
)是一种更便宜,更快捷的分配数组的方法。 但是,只有在确定所有元素稍后都会初始化时,才应使用它:
In [21]: ar13=np.empty((3,2)); ar13
Out[21]: array([[ -2.68156159e+154, 1.28822983e-231],
[ 4.22764845e-307, 2.78310358e-309],
[ 2.68156175e+154, 4.17201483e-309]])
np.tile
函数允许通过根据参数重复几次来从较小的数组构造一个数组:
In [334]: np.array([[1,2],[6,7]])
Out[334]: array([[1, 2],
[6, 7]])
In [335]: np.tile(np.array([[1,2],[6,7]]),3)
Out[335]: array([[1, 2, 1, 2, 1, 2],
[6, 7, 6, 7, 6, 7]])
In [336]: np.tile(np.array([[1,2],[6,7]]),(2,2))
Out[336]: array([[1, 2, 1, 2],
[6, 7, 6, 7],
[1, 2, 1, 2],
[6, 7, 6, 7]])
我们可以使用dtype
参数指定数字数组的内容类型:
In [50]: ar=np.array([2,-1,6,3],dtype='float'); ar
Out[50]: array([ 2., -1., 6., 3.])
In [51]: ar.dtype
Out[51]: dtype('float64')
In [52]: ar=np.array([2,4,6,8]); ar.dtype
Out[52]: dtype('int64')
In [53]: ar=np.array([2.,4,6,8]); ar.dtype
Out[53]: dtype('float64')
NumPy 中的默认dtype
为float
。 对于字符串,dtype
是数组中最长字符串的长度:
In [56]: sar=np.array(['Goodbye','Welcome','Tata','Goodnight']); sar.dtype
Out[56]: dtype('S9')
您不能在 NumPy 中创建长度可变的字符串,因为 NumPy 需要知道为该字符串分配多少空间。 dtypes
也可以是布尔值,复数等等:
In [57]: bar=np.array([True, False, True]); bar.dtype
Out[57]: dtype('bool')
ndarray
的数据类型可以用与其他语言(例如 Java 或 C/C++)相同的方式进行更改。 例如,float
至int
等。 执行此操作的机制是使用numpy.ndarray.astype()
函数。 这是一个例子:
In [3]: f_ar = np.array([3,-2,8.18])
f_ar
Out[3]: array([ 3\. , -2\. , 8.18])
In [4]: f_ar.astype(int)
Out[4]: array([ 3, -2, 8])
有关转换的更多信息,请参见官方文档。
NumPy 中的数组索引以0
开头,例如 Python,Java 和 C++ 之类的语言,而 Fortran,Matlab 和 Octave 的数组索引以1
开头。 数组可以以标准方式建立索引,就像我们将索引到任何其他 Python 序列中一样:
# print entire array, element 0, element 1, last element.
In [36]: ar = np.arange(5); print ar; ar[0], ar[1], ar[-1]
[0 1 2 3 4]
Out[36]: (0, 1, 4)
# 2nd, last and 1st elements
In [65]: ar=np.arange(5); ar[1], ar[-1], ar[0]
Out[65]: (1, 4, 0)
可以使用::-1
惯用法反转数组,如下所示:
In [24]: ar=np.arange(5); ar[::-1]
Out[24]: array([4, 3, 2, 1, 0])
多维数组使用整数元组建立索引:
In [71]: ar = np.array([[2,3,4],[9,8,7],[11,12,13]]); ar
Out[71]: array([[ 2, 3, 4],
[ 9, 8, 7],
[11, 12, 13]])
In [72]: ar[1,1]
Out[72]: 8
在这里,我们将row1
和column1
的条目设置为5
:
In [75]: ar[1,1]=5; ar
Out[75]: array([[ 2, 3, 4],
[ 9, 5, 7],
[11, 12, 13]])
检索第 2 行:
In [76]: ar[2]
Out[76]: array([11, 12, 13])
In [77]: ar[2,:]
Out[77]: array([11, 12, 13])
检索列 1:
In [78]: ar[:,1]
Out[78]: array([ 3, 5, 12])
如果指定的索引超出数组范围,则将引发IndexError
:
In [6]: ar = np.array([0,1,2])
In [7]: ar[5]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-7-8ef7e0800b7a> in <module>()
----> 1 ar[5]
IndexError: index 5 is out of bounds for axis 0 with size 3
因此,对于 2D 数组,第一维表示行,第二维表示列。 冒号(:
)表示对维度所有元素的选择。
可以使用以下语法对数组进行切片:ar[startIndex: endIndex: stepValue]
。
In [82]: ar=2*np.arange(6); ar
Out[82]: array([ 0, 2, 4, 6, 8, 10])
In [85]: ar[1:5:2]
Out[85]: array([2, 6])
请注意,如果我们希望包含endIndex
值,则需要超过它,如下所示:
In [86]: ar[1:6:2]
Out[86]: array([ 2, 6, 10])
使用ar[:n]
获得前 n 个元素:
In [91]: ar[:4]
Out[91]: array([0, 2, 4, 6])
这里的隐含假设是startIndex=0, step=1
。
从元素 4 开始直到结束:
In [92]: ar[4:]
Out[92]: array([ 8, 10])
带stepValue=3
的切片数组:
In [94]: ar[::3]
Out[94]: array([0, 6])
为了说明 NumPy 中索引的范围,让我们参考此图,该图取自 SciPy 2013 上的 NumPy 演讲,可在这个链接中找到:
现在让我们检查上图中的表达式的含义:
- 表达式
a[0,3:5]
表示从第 0 行和第 3-5 列开始,其中不包括第 5 列。 - 在表达式
a[4:,4:]
中,前 4 个表示第 4 行的起点,并将给出所有列,即数组[[40, 41, 42, 43, 44, 45], [50, 51, 52, 53, 54, 55]]
。 第二个 4 显示了在第 4 列开始处的截止,以产生数组[[44, 45], [54, 55]]
。 - 表达式
a[:,2]
给出了列 2 中的所有行。 - 现在,在最后一个表达式
a[2::2,::2]
中,2::2
指示起点在第 2 行,此处的步长值也为 2。这将为我们提供数组[[20, 21, 22, 23, 24, 25], [40, 41, 42, 43, 44, 45]
。 此外,::2
指定我们以 2 的步骤检索列,从而产生最终结果数组([[20, 22, 24], [40, 42, 44]]
)。
可以将分配和切片结合在一起,如以下代码片段所示:
In [96]: ar
Out[96]: array([ 0, 2, 4, 6, 8, 10])
In [100]: ar[:3]=1; ar
Out[100]: array([ 1, 1, 1, 6, 8, 10])
In [110]: ar[2:]=np.ones(4);ar
Out[110]: array([1, 1, 1, 1, 1, 1])
在这里,NumPy 数组可用作遮罩,以选择或滤除原始数组的元素。 例如,请参见以下代码段:
In [146]: np.random.seed(10)
ar=np.random.random_integers(0,25,10); ar
Out[146]: array([ 9, 4, 15, 0, 17, 25, 16, 17, 8, 9])
In [147]: evenMask=(ar % 2==0); evenMask
Out[147]: array([False, True, False, True, False, False, True, False, True, False], dtype=bool)
In [148]: evenNums=ar[evenMask]; evenNums
Out[148]: array([ 4, 0, 16, 8])
在下面的示例中,我们随机生成一个 0 到 25 之间的 10 个整数的数组。然后,我们创建一个布尔掩码数组,该数组用于仅滤除偶数。 例如,如果我们希望通过将默认值替换为缺失值来消除缺失值,则此掩码功能可能非常有用。 在这里,缺失值''
被替换为'USA'
作为默认国家/地区。 请注意,''
也是一个空字符串:
In [149]: ar=np.array(['Hungary','Nigeria',
'Guatemala','','Poland',
'','Japan']); ar
Out[149]: array(['Hungary', 'Nigeria', 'Guatemala',
'', 'Poland', '', 'Japan'],
dtype='|S9')
In [150]: ar[ar=='']='USA'; ar
Out[150]: array(['Hungary', 'Nigeria', 'Guatemala',
'USA', 'Poland', 'USA', 'Japan'], dtype='|S9')
整数数组也可以用于索引一个数组以生成另一个数组。 请注意,这会产生多个值。 因此,输出必须是ndarray
类型的数组。 以下代码段对此进行了说明:
In [173]: ar=11*np.arange(0,10); ar
Out[173]: array([ 0, 11, 22, 33, 44, 55, 66, 77, 88, 99])
In [174]: ar[[1,3,4,2,7]]
Out[174]: array([11, 33, 44, 22, 77])
在前面的代码中,选择对象是一个列表,并且选择了索引 1、3、4、2 和 7 的元素。 现在,假设我们将其更改为以下内容:
In [175]: ar[1,3,4,2,7]
由于数组是一维的,因此我们收到IndexError
错误,并且指定的索引太多,无法访问它。
IndexError Traceback (most recent call last)
<ipython-input-175-adbcbe3b3cdc> in <module>()
----> 1 ar[1,3,4,2,7]
IndexError: too many indices
数组索引也可以进行此分配,如下所示:
In [176]: ar[[1,3]]=50; ar
Out[176]: array([ 0, 50, 22, 50, 44, 55, 66, 77, 88, 99])
通过使用数组索引列表从另一个数组创建新数组时,新数组具有相同的形状。
在这里,我们说明了如何使用复杂的索引将值从较小的数组分配到较大的数组:
In [188]: ar=np.arange(15); ar
Out[188]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
In [193]: ar2=np.arange(0,-10,-1)[::-1]; ar2
Out[193]: array([-9, -8, -7, -6, -5, -4, -3, -2, -1, 0])
切出ar
的前 10 个元素,并用ar2
中的元素替换它们,如下所示:
In [194]: ar[:10]=ar2; ar
Out[194]: array([-9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 10, 11, 12, 13, 14])
NumPy 数组上的视图只是描绘其包含的数据的一种特殊方式。 创建视图不会导致数组的新副本,而是可以按特定顺序排列其中包含的数据,或者仅显示某些数据行。 因此,如果将数据替换为基础数组的数据,则无论何时通过索引访问数据,这都会反映在视图中。
切片时不会将初始数组复制到内存中,因此效率更高。 np.may_share_memory
方法可用于查看两个数组是否共享同一存储块。 但是,应谨慎使用,因为它可能会产生误报。 修改视图会修改原始数组:
In [118]:ar1=np.arange(12); ar1
Out[118]:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
In [119]:ar2=ar1[::2]; ar2
Out[119]: array([ 0, 2, 4, 6, 8, 10])
In [120]: ar2[1]=-1; ar1
Out[120]: array([ 0, 1, -1, 3, 4, 5, 6, 7, 8, 9, 10, 11])
为了强制 NumPy 复制数组,我们使用np.copy
函数。 正如我们在以下数组中看到的,修改复制的数组时,原始数组不受影响:
In [124]: ar=np.arange(8);ar
Out[124]: array([0, 1, 2, 3, 4, 5, 6, 7])
In [126]: arc=ar[:3].copy(); arc
Out[126]: array([0, 1, 2])
In [127]: arc[0]=-1; arc
Out[127]: array([-1, 1, 2])
In [128]: ar
Out[128]: array([0, 1, 2, 3, 4, 5, 6, 7])
在这里,我们介绍 NumPy 中的各种操作。
基本算术运算使用标量操作数逐个元素地工作。 它们是- +
,-
,*
,/
和**
。
In [196]: ar=np.arange(0,7)*5; ar
Out[196]: array([ 0, 5, 10, 15, 20, 25, 30])
In [198]: ar=np.arange(5) ** 4 ; ar
Out[198]: array([ 0, 1, 16, 81, 256])
In [199]: ar ** 0.5
Out[199]: array([ 0., 1., 4., 9., 16.])
当另一个数组是第二个操作数时,操作也按元素方式工作,如下所示:
In [209]: ar=3+np.arange(0, 30,3); ar
Out[209]: array([ 3, 6, 9, 12, 15, 18, 21, 24, 27, 30])
In [210]: ar2=np.arange(1,11); ar2
Out[210]: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
在下面的代码段中,我们看到了逐元素的减法,除法和乘法:
In [211]: ar-ar2
Out[211]: array([ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20])
In [212]: ar/ar2
Out[212]: array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3])
In [213]: ar*ar2
Out[213]: array([ 3, 12, 27, 48, 75, 108, 147, 192, 243, 300])
使用 NumPy 进行此操作比使用纯 Python 更快。 IPython 中的%timeit
函数被称为魔术函数,它使用 Python timeit
模块来定时执行 Python 语句或表达式,其解释如下:
In [214]: ar=np.arange(1000)
%timeit ar**3
100000 loops, best of 3: 5.4 µs per loop
In [215]:ar=range(1000)
%timeit [ar[i]**3 for i in ar]
1000 loops, best of 3: 199 µs per loop
数组乘法与矩阵乘法不同; 它是元素方式的,意味着相应的元素被相乘在一起。 对于矩阵乘法,请使用点运算符。 有关更多信息,请参考这里。
In [228]: ar=np.array([[1,1],[1,1]]); ar
Out[228]: array([[1, 1],
[1, 1]])
In [230]: ar2=np.array([[2,2],[2,2]]); ar2
Out[230]: array([[2, 2],
[2, 2]])
In [232]: ar.dot(ar2)
Out[232]: array([[4, 4],
[4, 4]])
比较和逻辑运算也是基于元素的:
In [235]: ar=np.arange(1,5); ar
Out[235]: array([1, 2, 3, 4])
In [238]: ar2=np.arange(5,1,-1);ar2
Out[238]: array([5, 4, 3, 2])
In [241]: ar < ar2
Out[241]: array([ True, True, False, False], dtype=bool)
In [242]: l1 = np.array([True,False,True,False])
l2 = np.array([False,False,True, False])
np.logical_and(l1,l2)
Out[242]: array([False, False, True, False], dtype=bool)
其他 NumPy 运算(例如log
,sin
,cos
和exp
)也是按元素排列的:
In [244]: ar=np.array([np.pi, np.pi/2]); np.sin(ar)
Out[244]: array([ 1.22464680e-16, 1.00000000e+00])
请注意,对于在两个 NumPy 数组上的按元素进行操作,两个数组必须为具有相同的形状,否则将导致错误,因为该操作的参数必须是两个数组中的对应元素:
In [245]: ar=np.arange(0,6); ar
Out[245]: array([0, 1, 2, 3, 4, 5])
In [246]: ar2=np.arange(0,8); ar2
Out[246]: array([0, 1, 2, 3, 4, 5, 6, 7])
In [247]: ar*ar2
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-247-2c3240f67b63> in <module>()
----> 1 ar*ar2
ValueError: operands could not be broadcast together with shapes (6) (8)
此外,NumPy 数组可以如下进行转置:
In [249]: ar=np.array([[1,2,3],[4,5,6]]); ar
Out[249]: array([[1, 2, 3],
[4, 5, 6]])
In [250]:ar.T
Out[250]:array([[1, 4],
[2, 5],
[3, 6]])
In [251]: np.transpose(ar)
Out[251]: array([[1, 4],
[2, 5],
[3, 6]])
假设我们希望不按元素比较而是按数组比较数组。 我们可以通过使用np.array_equal
运算符实现以下目标:
In [254]: ar=np.arange(0,6)
ar2=np.array([0,1,2,3,4,5])
np.array_equal(ar, ar2)
Out[254]: True
在这里,我们看到返回的是布尔值而不是布尔数组。 仅当两个数组中的全部对应元素匹配时,该值才为True
。 前面的表达式等效于以下内容:
In [24]: np.all(ar==ar2)
Out[24]: True
诸如np.sum
和np.prod
之类的运算符对数组执行归约运算。 也就是说,它们将多个元素组合为一个值:
In [257]: ar=np.arange(1,5)
ar.prod()
Out[257]: 24
在多维数组的情况下,我们可以使用axis
参数指定是要按行还是按列应用约简运算符:
In [259]: ar=np.array([np.arange(1,6),np.arange(1,6)]);ar
Out[259]: array([[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]])
# Columns
In [261]: np.prod(ar,axis=0)
Out[261]: array([ 1, 4, 9, 16, 25])
# Rows
In [262]: np.prod(ar,axis=1)
Out[262]: array([120, 120])
对于多维数组,不指定轴会导致将操作应用于数组的所有元素,如以下示例中所述:
In [268]: ar=np.array([[2,3,4],[5,6,7],[8,9,10]]); ar.sum()
Out[268]: 54
In [269]: ar.mean()
Out[269]: 6.0
In [271]: np.median(ar)
Out[271]: 6.0
这些运算符用于将标准统计运算应用于 NumPy 数组。 名称是不言自明的:np.std()
,np.mean()
,np.median()
和np.cumsum()
。
In [309]: np.random.seed(10)
ar=np.random.randint(0,10, size=(4,5));ar
Out[309]: array([[9, 4, 0, 1, 9],
[0, 1, 8, 9, 0],
[8, 6, 4, 3, 0],
[4, 6, 8, 1, 8]])
In [310]: ar.mean()
Out[310]: 4.4500000000000002
In [311]: ar.std()
Out[311]: 3.4274626183227732
In [312]: ar.var(axis=0) # across rows
Out[312]: array([ 12.6875, 4.1875, 11\. , 10.75 , 18.1875])
In [313]: ar.cumsum()
Out[313]: array([ 9, 13, 13, 14, 23, 23, 24, 32, 41, 41, 49, 55,
59, 62, 62, 66, 72, 80, 81, 89])
逻辑运算符可用于数组比较/检查。 它们如下:
np.all()
:用于计算所有元素的逐元素 ANDnp.any()
:用于计算所有元素的逐元素 OR
生成ints
的4×4
随机数组,并检查是否有任何元素可以被 7 整除,并且所有元素都小于 11:
In [320]: np.random.seed(100)
ar=np.random.randint(1,10, size=(4,4));ar
Out[320]: array([[9, 9, 4, 8],
[8, 1, 5, 3],
[6, 3, 3, 3],
[2, 1, 9, 5]])
In [318]: np.any((ar%7)==0)
Out[318]: False
In [319]: np.all(ar<11)
Out[319]: True
在广播中,我们利用 NumPy 组合形状不完全相同的数组的功能。 这是一个例子:
In [357]: ar=np.ones([3,2]); ar
Out[357]: array([[ 1., 1.],
[ 1., 1.],
[ 1., 1.]])
In [358]: ar2=np.array([2,3]); ar2
Out[358]: array([2, 3])
In [359]: ar+ar2
Out[359]: array([[ 3., 4.],
[ 3., 4.],
[ 3., 4.]])
因此,我们可以看到,通过将ar2
添加到ar
的每一行中,从而产生广播。 这是另一个示例,显示广播在各个维度上均有效:
In [369]: ar=np.array([[23,24,25]]); ar
Out[369]: array([[23, 24, 25]])
In [368]: ar.T
Out[368]: array([[23],
[24],
[25]])
In [370]: ar.T+ar
Out[370]: array([[46, 47, 48],
[47, 48, 49],
[48, 49, 50]])
在这里,广播了行和列数组,最后得到了3×3
数组。
数组的形状处理有许多步骤。
np.ravel()
函数允许您按以下方式展平多维数组:
In [385]: ar=np.array([np.arange(1,6), np.arange(10,15)]); ar
Out[385]: array([[ 1, 2, 3, 4, 5],
[10, 11, 12, 13, 14]])
In [386]: ar.ravel()
Out[386]: array([ 1, 2, 3, 4, 5, 10, 11, 12, 13, 14])
In [387]: ar.T.ravel()
Out[387]: array([ 1, 10, 2, 11, 3, 12, 4, 13, 5, 14])
您还可以使用np.flatten
进行相同的操作,除了它在np.ravel
返回视图的同时返回副本。
整形函数可用于更改数组的形状或使其不展平:
In [389]: ar=np.arange(1,16);ar
Out[389]: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
In [390]: ar.reshape(3,5)
Out[390]: array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])
np.reshape
函数返回数据视图,表示基础数组保持不变。 但是,在特殊情况下,如果不复制数据,则无法更改形状。 有关此的更多详细信息,请参见文档。
有两个大小调整操作符,numpy.ndarray.resize
是用于调整大小的ndarray
操作符,numpy.resize
是用于返回具有指定形状的新数组的numpy.resize
。 在这里,我们说明numpy.ndarray.resize
函数:
In [408]: ar=np.arange(5); ar.resize((8,));ar
Out[408]: array([0, 1, 2, 3, 4, 0, 0, 0])
请注意,只有在没有其他引用此数组的情况下,此函数才起作用。 否则,ValueError
结果:
In [34]: ar=np.arange(5);
ar
Out[34]: array([0, 1, 2, 3, 4])
In [35]: ar2=ar
In [36]: ar.resize((8,));
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-36-394f7795e2d1> in <module>()
----> 1 ar.resize((8,));
ValueError: cannot resize an array that references or is referenced by another array in this way. Use the resize function
解决此问题的方法是改用numpy.resize
函数:
In [38]: np.resize(ar,(8,))
Out[38]: array([0, 1, 2, 3, 4, 0, 1, 2])
np.newaxis
函数为数组添加了额外的维度:
In [377]: ar=np.array([14,15,16]); ar.shape
Out[377]: (3,)
In [378]: ar
Out[378]: array([14, 15, 16])
In [379]: ar=ar[:, np.newaxis]; ar.shape
Out[379]: (3, 1)
In [380]: ar
Out[380]: array([[14],
[15],
[16]])
数组可以以多种方式排序。
-
沿轴对数组排序; 首先,让我们沿 y 轴进行讨论:
In [43]: ar=np.array([[3,2],[10,-1]]) ar Out[43]: array([[ 3, 2], [10, -1]]) In [44]: ar.sort(axis=1) ar Out[44]: array([[ 2, 3], [-1, 10]])
-
在这里,我们将解释沿 x 轴的排序:
In [45]: ar=np.array([[3,2],[10,-1]]) ar Out[45]: array([[ 3, 2], [10, -1]]) In [46]: ar.sort(axis=0) ar Out[46]: array([[ 3, -1], [10, 2]])
-
按就地(
np.array.sort
)和就地(np.sort
)函数排序。 -
可用于数组排序的其他操作包括:
np.min()
:返回数组中的最小元素np.max()
:返回数组中的最大元素np.std()
:返回数组中元素的标准差np.var()
:它返回数组中元素的方差np.argmin()
:最小索引np.argmax()
:最大索引np.all()
:返回所有元素的按元素 ANDnp.any()
:返回所有元素的按元素 OR
Pandas 由 Wed McKinney 于 2008 年创建,原因是他在 R 中处理时间序列数据时遇到挫折。它是在 NumPy 之上构建的,并提供了其中不可用的功能。 它提供了快速,易于理解的数据结构,并有助于填补 Python 与 R 之类的语言之间的空白。
我在此处演示的各种操作的关键参考是官方的 Pandas 数据结构文档。
Pandas 有三种主要的数据结构:
- 序列
- 数据帧
- 面板
序列实际上是引擎盖下的一维 NumPy 数组。 它由一个 NumPy 数组和一个标签数组组成。
创建序列数据结构的一般构造如下:
import pandas as pd
ser=pd.Series(data, index=idx)
数据可以是以下之一:
ndarray
- Python 字典
- 标量值
在这种情况下,索引必须与数据长度相同。 如果未指定索引,则将创建以下默认索引[0,... n-1]
,其中n
是数据的长度。 下面的示例创建一个由 0 至 1 之间的七个随机数组成的序列结构; 未指定索引:
In [466]: import numpy as np
np.random.seed(100)
ser=pd.Series(np.random.rand(7)); ser
Out[466]:0 0.543405
1 0.278369
2 0.424518
3 0.844776
4 0.004719
5 0.121569
6 0.670749
dtype: float64
以下示例使用指定的月份名称索引创建一年中前 5 个月的序列结构:
In [481]: import calendar as cal
monthNames=[cal.month_name[i] for i in np.arange(1,6)]
months=pd.Series(np.arrange(1,6),index=monthNames);months
Out[481]: January 1
February 2
March 3
April 4
May 5
dtype: int64
In [482]: months.index
Out[482]: Index([u'January', u'February', u'March', u'April', u'May'], dtype=object)
如果数据是字典并提供了索引,则将从中构造标签; 否则,字典的键将用作标签。 字典的值用于填充序列结构。
In [486]: currDict={'US' : 'dollar', 'UK' : 'pound',
'Germany': 'euro', 'Mexico':'peso',
'Nigeria':'naira',
'China':'yuan', 'Japan':'yen'}
currSeries=pd.Series(currDict); currSeries
Out[486]: China yuan
Germany euro
Japan yen
Mexico peso
Nigeria naira
UK pound
US dollar
dtype: object
Pandas 序列结构的索引类型为pandas.core.index.Index
,可以将其视为有序多集。
在以下情况下,我们指定一个索引,但是该索引包含一个条目,该条目不是相应的dict
中的键。 结果是将将的值分配为NaN
,表明它丢失了。 我们将在后面的部分中处理缺失值。
In [488]: stockPrices = {'GOOG':1180.97,'FB':62.57,
'TWTR': 64.50, 'AMZN':358.69,
'AAPL':500.6}
stockPriceSeries=pd.Series(stockPrices,
index=['GOOG','FB','YHOO',
'TWTR','AMZN','AAPL'],
name='stockPrices')
stockPriceSeries
Out[488]: GOOG 1180.97
FB 62.57
YHOO NaN
TWTR 64.50
AMZN 358.69
AAPL 500.60
Name: stockPrices, dtype: float64
请注意,序列还具有可以如前面的片段中所示设置的name
属性。 name
属性在将序列对象组合到数据帧结构等任务中很有用。
对于标量数据,必须提供索引。 将为尽可能多的索引值重复该值。 此方法的一种可能用途是提供一种快速而肮脏的初始化方法,并在以后填充序列结构。 让我们看看如何使用标量值创建序列:
In [491]: dogSeries=pd.Series('chihuahua',
index=['breed','countryOfOrigin',
'name', 'gender'])
dogSeries
Out[491]: breed chihuahua
countryOfOrigin chihuahua
name chihuahua
gender chihuahua
dtype: object
无法提供索引只会导致返回标量值,如下所示:
In [494]: dogSeries=pd.Series('pekingese'); dogSeries
Out[494]: 'pekingese'
In [495]: type(dogSeries)
Out[495]: str
序列的行为与上一节中讨论的numpy
数组的行为非常相似,其中一个警告是切片等操作也会对索引进行切片。
可以使用类似于字典的方式使用索引标签设置和访问值:
In [503]: currDict['China']
Out[503]: 'yuan'
In [505]: stockPriceSeries['GOOG']=1200.0
stockPriceSeries
Out[505]: GOOG 1200.00
FB 62.57
YHOO NaN
TWTR 64.50
AMZN 358.69
AAPL 500.60
dtype: float64
与dict
一样,如果尝试检索丢失的标签,则会引发KeyError
:
In [506]: stockPriceSeries['MSFT']
KeyError: 'MSFT'
通过显式使用get
可以避免此错误,如下所示:
In [507]: stockPriceSeries.get('MSFT',np.NaN)
Out[507]: nan
在这种情况下,将默认值np.NaN
指定为序列结构中不存在该键时要返回的值。
切片操作的行为与 NumPy 数组相同:
In [498]: stockPriceSeries[:4]
Out[498]: GOOG 1180.97
FB 62.57
YHOO NaN
TWTR 64.50
dtype: float64
逻辑切片也如下工作:
In [500]: stockPriceSeries[stockPriceSeries > 100]
Out[500]: GOOG 1180.97
AMZN 358.69
AAPL 500.60
dtype: float64
可以应用算术和统计运算,就像使用 NumPy 数组一样:
In [501]: np.mean(stockPriceSeries)
Out[501]: 433.46600000000001
In [502]: np.std(stockPriceSeries)
Out[502]: 410.50223047384287
按元素操作也可以按顺序执行:
In [506]: ser
Out[506]: 0 0.543405
1 0.278369
2 0.424518
3 0.844776
4 0.004719
5 0.121569
6 0.670749
dtype: float64
In [508]: ser*ser
Out[508]: 0 0.295289
1 0.077490
2 0.180215
3 0.713647
4 0.000022
5 0.014779
6 0.449904
dtype: float64
In [510]: np.sqrt(ser)
Out[510]: 0 0.737160
1 0.527607
2 0.651550
3 0.919117
4 0.068694
5 0.348668
6 0.818993
dtype: float64
序列的一个重要功能是根据标签自动对齐数据:
In [514]: ser[1:]
Out[514]: 1 0.278369
2 0.424518
3 0.844776
4 0.004719
5 0.121569
6 0.670749
dtype: float64
In [516]:ser[1:] + ser[:-2]
Out[516]: 0 NaN
1 0.556739
2 0.849035
3 1.689552
4 0.009438
5 NaN
6 NaN
dtype: float64
因此,我们可以看到,对于不匹配的标签,插入了NaN
。 默认行为是为未对齐的序列结构生成索引的并集。 这是可取的,因为信息可以保留而不是丢失。 在本书的下一章中,我们将处理 Pandas 中缺失的值。
数据帧是一个二维标签数组。 它的列类型可以是异构的:即具有不同的类型。 它类似于 NumPy 中的结构化数组,并添加了可变性。 它具有以下属性:
- 从概念上讲类似于数据表或电子表格。
- 类似于 NumPy
ndarray
,但不是np.ndarray
的子类。 - 列可以是异构类型:
float64
,int
,bool
等。 - 数据帧的列是序列结构。
- 可以将其视为序列结构的字典,在该结构中,对列和行均进行索引,对于行,则表示为“索引”,对于列,则表示为“列”。
- 它的大小可变:可以插入和删除列。
序列/数据帧中的每个轴都有索引,无论是否默认。 需要索引才能快速查找以及正确对齐和连接 Pandas 中的数据。 轴也可以命名,例如以月的形式表示列的数组 Jan Feb Mar ...Dec。这是索引数据帧的表示形式,其命名列的两端以及字符 V,W, X,Y,Z:
columns nums strs bools decs
index
V 11 cat True 1.4
W -6 hat False 6.9
X 25 bat False -0.6
Y 8 mat True 3.7
Z -17 sat False 18.
数据帧是 Pandas 中最常用的数据结构。 构造器接受许多不同类型的参数:
- 一维
ndarray
,列表,字典或序列结构的字典 - 2D NumPy 数组
- 结构化或记录
ndarray
- 序列结构
- 另一个数据帧结构
行标签索引和列标签可以与数据一起指定。 如果未指定,则将以直观的方式从输入数据生成它们,例如,从dict.
的键(对于列标签)或通过在行标签的情况下使用np.range(n)
生成, 其中n
对应于行数。
在这里,我们通过使用序列对象的字典来创建数据帧结构。
In [97]:stockSummaries={
'AMZN': pd.Series([346.15,0.59,459,0.52,589.8,158.88],
index=['Closing price','EPS',
'Shares Outstanding(M)',
'Beta', 'P/E','Market Cap(B)']),
'GOOG': pd.Series([1133.43,36.05,335.83,0.87,31.44,380.64],
index=['Closing price','EPS','Shares Outstanding(M)',
'Beta','P/E','Market Cap(B)']),
'FB': pd.Series([61.48,0.59,2450,104.93,150.92],
index=['Closing price','EPS','Shares Outstanding(M)',
'P/E', 'Market Cap(B)']),
'YHOO': pd.Series([34.90,1.27,1010,27.48,0.66,35.36],
index=['Closing price','EPS','Shares Outstanding(M)',
'P/E','Beta', 'Market Cap(B)']),
'TWTR':pd.Series([65.25,-0.3,555.2,36.23],
index=['Closing price','EPS','Shares Outstanding(M)',
'Market Cap(B)']),
'AAPL':pd.Series([501.53,40.32,892.45,12.44,447.59,0.84],
index=['Closing price','EPS','Shares Outstanding(M)','P/E',
'Market Cap(B)','Beta'])}
In [99]: stockDF=pd.DataFrame(stockSummaries); stockDF
Out[99]:
AAPL | AMZN | FB | GOOG | TWTR | YHOO | |
---|---|---|---|---|---|---|
Beta | 0.84 | 0.52 | NaN | 0.87 | NaN | 0.66 |
Closing Price | 501.53 | 346.15 | 61.48 | 1133.43 | 65.25 | 34.9 |
EPS | 40.32 | 0.59 | 0.59 | 36.05 | -0.3 | 1.27 |
Market Cap(B) | 447.59 | 158.88 | 150.92 | 380.64 | 36.23 | 35.36 |
P/E | 12.44 | 589.8 | 104.93 | 31.44 | NaN | 27.48 |
Shares Outstanding(M) | 892.45 | 459 | 2450 | 335.83 | 555.2 | 1010 |
In [100]:stockDF=pd.DataFrame(stockSummaries,
index=['Closing price','EPS',
'Shares Outstanding(M)',
'P/E', 'Market Cap(B)','Beta']);stockDF
Out [100]:
AAPL | AMZN | FB | GOOG | TWTR | YHOO | |
---|---|---|---|---|---|---|
Closing price | 501.53 | 346.15 | 61.48 | 1133.43 | 65.25 | 34.9 |
EPS | 40.32 | 0.59 | 0.59 | 36.05 | -0.3 | 1.27 |
Shares Outstanding(M) | 892.45 | 459 | 2450 | NaN | 555.2 | 1010 |
P/E | 12.44 | 589.8 | 104.93 | 31.44 | NaN | 27.48 |
Market Cap(B) | 447.59 | 158.88 | 150.92 | 380.64 | 36.23 | 35.36 |
Beta | 0.84 | 0.52 | NaN | 0.87 | NaN | 0.66 |
In [102]:stockDF=pd.DataFrame(stockSummaries,
index=['Closing price','EPS','Shares Outstanding(M)',
'P/E', 'Market Cap(B)','Beta'],
columns=['FB','TWTR','SCNW'])
stockDF
Out [102]:
FB | TWTR | SCNW | |
---|---|---|---|
Closing price | 61.48 | 65.25 | NaN |
EPS | 0.59 | -0.3 | NaN |
Shares Outstanding(M) | 2450 | 555.2 | NaN |
P/E | 104.93 | NaN | NaN |
Market Cap(B) | 150.92 | 36.23 | NaN |
Beta | NaN | NaN | NaN |
可以通过index
和columns
属性访问行索引标签和列标签:
In [527]: stockDF.index
Out[527]: Index([u'Closing price', u'EPS',
u'Shares Outstanding(M)',
u'P/E', u'Market Cap(B)', u'Beta'], dtype=object)
In [528]: stockDF.columns
Out[528]: Index([u'AAPL', u'AMZN', u'FB', u'GOOG', u'TWTR',
u'YHOO'], dtype=object)
上述数据的来源是 Google 财经,2014 年 2 月 3 日访问。
在这里,我们从列表的字典中创建一个数据帧结构。 键将成为数据帧结构中的列标签,列表中的数据将成为列值。 注意如何使用np.range(n)
生成行标签索引。
In [529]:algos={'search':['DFS','BFS','Binary Search',
'Linear','ShortestPath (Djikstra)'],
'sorting': ['Quicksort','Mergesort', 'Heapsort',
'Bubble Sort', 'Insertion Sort'],
'machine learning':['RandomForest',
'K Nearest Neighbor',
'Logistic Regression',
'K-Means Clustering',
'Linear Regression']}
algoDF=pd.DataFrame(algos); algoDF
Out[529]:
machine learning search sorting
0 RandomForest DFS Quicksort
1 K Nearest Neighbor BFS Mergesort
2 Logistic Regression Binary Search Heapsort
3 K-Means Clustering Linear Bubble Sort
4 Linear Regression ShortestPath (Djikstra) Insertion Sort
In [530]: pd.DataFrame(algos,index=['algo_1','algo_2','algo_3','algo_4',
'algo_5'])
Out[530]:
machine learning search sorting
algo_1 RandomForest DFS Quicksort
algo_2 K Nearest Neighbor BFS Mergesort
algo_3 Logistic Regression Binary Search Heapsort
algo_4 K-Means Clustering Linear Bubble Sort
algo_5 Linear Regression ShortestPath (Djikstra) Insertion Sort
在这种情况下,我们使用结构化数组,即记录或structs
的数组。 有关结构化数组的更多信息,请参考这个内容。
In [533]: memberData = np.zeros((4,),
dtype=[('Name','a15'),
('Age','i4'),
('Weight','f4')])
memberData[:] = [('Sanjeev',37,162.4),
('Yingluck',45,137.8),
('Emeka',28,153.2),
('Amy',67,101.3)]
memberDF=pd.DataFrame(memberData);memberDF
Out[533]: Name Age Weight
0 Sanjeev 37 162.4
1 Yingluck 45 137.8
2 Emeka 28 153.2
3 Amy 67 101.3
In [534]: pd.DataFrame(memberData, index=['a','b','c','d'])
Out[534]: Name Age Weight
a Sanjeev 37 162.4
b Yingluck 45 137.8
c Emeka 28 153.2
d Amy 67 101.3
在这里,我们展示如何从序列结构构造一个数据帧结构:
In [ 540]: currSeries.name='currency'
pd.DataFrame(currSeries)
Out[540]: currency
China yuan
Germany euro
Japan yen
Mexico peso
Nigeria naira
UK pound
US dollar
还有一些数据帧的替代构造器。 它们可以总结如下:
DataFrame.from_dict
:它使用字典或序列的字典并返回数据帧。DataFrame.from_records
:需要一个元组或结构化ndarray
的列表。DataFrame.from_items
:需要一些(键,值)对。 键是列或索引名,值是列或行值。 如果希望键为行索引名,则必须指定orient ='index'
作为参数并指定列名。pandas.io.parsers.read_csv
:这是一个辅助函数,可将 CSV 文件读取到 Pandas 数据帧结构中。pandas.io.parsers.read_table
:这是一个辅助函数,它将定界文件读入 Pandas 数据帧结构。pandas.io.parsers.read_fwf
:这是一个辅助函数,它将固定宽度的线表读入 Pandas 数据帧结构。
在这里,我将简要描述各种数据帧操作。
特定的列可以作为序列结构获得:
In [543]: memberDF['Name']
Out[543]: 0 Sanjeev
1 Yingluck
2 Emeka
3 Amy
Name: Name, dtype: object
可以通过分配添加新列,如下所示:
In [545]: memberDF['Height']=60;memberDF
Out[545]: Name Age Weight Height
0 Sanjeev 37 162.4 60
1 Yingluck 45 137.8 60
2 Emeka 28 153.2 60
3 Amy 67 101.3 60
可以删除列,就像使用dict
一样:
In [546]: del memberDF['Height']; memberDF
Out[546]: Name Age Weight
0 Sanjeev 37 162.4
1 Yingluck 45 137.8
2 Emeka 28 153.2
3
Amy 67 101.3
也可以像字典一样弹出它:
In [547]: memberDF['BloodType']='O'
bloodType=memberDF.pop('BloodType'); bloodType
Out[547]: 0 O
1 O
2 O
3 O
Name: BloodType, dtype: object
基本上,可以将数据帧结构看作是序列对象的字典。 列在末尾插入; 要在特定位置插入列,可以使用insert
函数:
In [552]: memberDF.insert(2,'isSenior',memberDF['Age']>60);
memberDF
Out[552]: Name Age isSenior Weight
0 Sanjeev 37 False 162.4
1 Yingluck 45 False 137.8
2 Emeka 28 False 153.2
3 Amy 67 True 101.3
数据帧对象以与序列对象相似的方式对齐,只不过它们在列和索引标签上都对齐。 结果对象是列标签和行标签的并集:
In [559]: ore1DF=pd.DataFrame(np.array([[20,35,25,20],
[11,28,32,29]]),
columns=['iron','magnesium',
'copper','silver'])
ore2DF=pd.DataFrame(np.array([[14,34,26,26],
[33,19,25,23]]),
columns=['iron','magnesium',
'gold','silver'])
ore1DF+ore2DF
Out[559]: copper gold iron magnesium silver
0 NaN NaN 34 69 46
1 NaN NaN 44 47 52
在没有共同的行标签或列标签的情况下,该值用NaN
填充,例如,铜和金。 如果将数据帧对象和序列对象组合在一起,则默认行为是在各行之间广播序列对象:
In [562]: ore1DF + pd.Series([25,25,25,25],
index=['iron','magnesium',
'copper','silver'])
Out[562]: iron magnesium copper silver
0 45 60 50 45
1 36 53 57 54
可以将数学运算符明智地应用于数据帧结构:
In [565]: np.sqrt(ore1DF)
Out[565]: iron magnesium copper silver
0 4.472136 5.916080 5.000000 4.472136
1 3.316625 5.291503 5.656854 5.385165
面板是 3D 数组。 它不如序列或数据帧广泛使用。 由于其 3D 性质,它不像其他两个屏幕那样容易在屏幕上显示或可视化。面板数据结构是 Pandas 中数据结构拼图的最后一部分。 它使用较少,用于 3D 数据。 三个轴名称如下:
item
:这是轴 0。每个项目均对应一个数据帧结构。major_axis
:这是轴 1。每个项目对应于数据帧结构的行。minor_axis
:这是轴 2。每个项目对应于每个数据帧结构的列。
至于序列和数据帧,有创建面板对象的不同方法。 它们将在后面的章节中进行解释。
在这里,我们展示了如何从 3D NumPy 数组构造面板对象。
In 586[]: stockData=np.array([[[63.03,61.48,75],
[62.05,62.75,46],
[62.74,62.19,53]],
[[411.90, 404.38, 2.9],
[405.45, 405.91, 2.6],
[403.15, 404.42, 2.4]]])
stockData
Out[586]: array([[[ 63.03, 61.48, 75\. ],
[ 62.05, 62.75, 46\. ],
[ 62.74, 62.19, 53\. ]],
[[ 411.9 , 404.38, 2.9 ],
[ 405.45, 405.91, 2.6 ],
[ 403.15, 404.42, 2.4 ]]])
In [587]: stockHistoricalPrices = pd.Panel(stockData,
items=['FB', 'NFLX'],
major_axis=pd.date_range('2/3/2014', periods=3),
minor_axis=['open price', 'closing price', 'volume'])
stockHistoricalPrices
Out[587]: <class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 3 (major_axis) x 3 (minor_axis)
Items axis: FB to NFLX
Major_axis axis: 2014-02-03 00:00:00 to 2014-02-05 00:00:00
Minor_axis axis: open price to volume
我们通过使用数据帧结构的 Python 字典来构造面板结构。
In [591]: USData=pd.DataFrame(np.array([[249.62 , 8900],
[ 282.16,12680],
[309.35,14940]]),
columns=['Population(M)','GDP($B)'],
index=[1990,2000,2010])
USData
Out[591]: Population(M) GDP($B)
1990 249.62 8900
2000 282.16 12680
2010 309.35 14940
In [590]: ChinaData=pd.DataFrame(np.array([[1133.68, 390.28],
[ 1266.83,1198.48],
[1339.72, 6988.47]]),
columns=['Population(M)','GDP($B)'],
index=[1990,2000,2010])
ChinaData
Out[590]: Population(M) GDP($B)
1990 1133.68 390.28
2000 1266.83 1198.48
2010 1339.72 6988.47
In [592]:US_ChinaData={'US' : USData,
'China': ChinaData}
pd.Panel(US_ChinaData)
Out[592]: <class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 3 (major_axis) x 2 (minor_axis)
Items axis: China to US
Major_axis axis: 1990 to 2010
此方法将具有多重索引的数据帧结构转换为面板结构:
In [617]: mIdx = pd.MultiIndex(levels=[['US', 'China'],
[1990,2000, 2010]],
labels=[[1,1,1,0,0,0],[0,1,2,0,1,2]])
mIdx
Out[617]: MultiIndex
[(u'China', 1990), (u'China', 2000), (u'China', 2010),
(u'US', 1990), (u'US', 2000), (u'US', 2010)]
ChinaUSDF = pd.DataFrame({'Population(M)' : [1133.68, 1266.83,
1339.72, 249.62,
282.16,309.35],
'GDB($B)': [390.28, 1198.48, 6988.47,
8900,12680, 14940]}, index=mIdx)
ChinaUSDF
In [618]: ChinaUSDF = pd.DataFrame({'Population(M)' : [1133.68,
1266.83,
1339.72,
249.62,
282.16,
309.35],
'GDB($B)': [390.28, 1198.48,
6988.47, 8900,
12680,14940]},
index=mIdx)
ChinaUSDF
Out[618]: GDB($B) Population(M)
China 1990 390.28 1133.68
2000 1198.48 1266.83
2010 6988.47 1339.72
US 1990 8900.00 249.62
2000 12680.00 282.16
2010 14940.00 309.35
In [622]: ChinaUSDF.to_panel()
Out[622]: <class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 2 (major_axis) x 3 (minor_axis)
Items axis: GDB($B) to Population(M)
Major_axis axis: US to China
Minor_axis axis: 1990 to 2010
美国/中国经济数据的来源是以下站点:
- http://www.multpl.com/us-gdp-inflation-adjusted/table
- http://www.multpl.com/united-states-population/table
- http://en.wikipedia.org/wiki/Demographics_of_China
- http://www.theguardian.com/news/datablog/2012/mar/23/china-gdp-since-1980
插入,删除和逐项操作的行为与数据帧相同。 面板结构可以通过转置重新排列。面板的操作功能集相对欠发达,不如序列和数据帧丰富。
总结本章,numpy.ndarray
是 Pandas 数据结构所基于的基岩数据结构。 Pandas 的数据结构由 NumPy ndarray
数据和一个或多个标签数组组成。
Pandas 中有三种主要的数据结构:序列,数据帧架和面板。 与 Numpy ndarrays
相比,pandas 数据结构更易于使用且更加用户友好,因为在数据帧和面板的情况下,它们提供行索引和列索引。数据帧对象是 Pandas 中最流行和使用最广泛的对象。 在下一章中,我们将讨论 Pandas 索引的主题。