3.3 数组基本操作

既已加载数据,现在来看看对于这些数据我们能做些什么。总的来说,我们可以做三类事情:

  • 选择
  • 操作
  • 计算

3.3.1 选择

选择即访问数组中的若干元素,可通过NumPy或Pandas完成。

Pandas

继续上节中加载的cities数据集。DataFrame的列可通过名字访问。

data.AccentCity
0                       Aixas
1                  Aixirivali
...
3173956               Zuzumba
3173957            Zvishavane
Name: AccentCity, dtype: object

这一列的类型是Series,我们可使用索引访问其中的行,如data.AccentCity[3000]。问题是,如果想知道纽约市的人口和GPS信息,怎么做呢?最直接的当然是循环,但Pandas和NumPy中的boolean indexing要优雅和高效得多。

data[data.AccentCity=='New York']
data.ix[2990572]

第一行代码可分为两步来看,第一步是==判断返回了一个bool数组,第二步是根据bool数组过滤出符合条件的行。获得行索引后再通过ix属性获取该行的信息。

NumPy

Pandas的Series列可转换为NumPy的数组。

population = array(data.Population)
population.shape
# (3173958,)
population[2990572]
8107916.0

我们知道有些城市的人口信息缺失,那来检查下有多少城市是有值的:

isnan(population)
# array([ True,  True,  True, ...,  True,  True, False], dtype=bool)

x = population[~_]
len(x), len(x) / float(len(population))
# (47980, 0.015116772181610469)

更多索引法

NumPy的索引法可视作Python索引法的扩展。值得注意的一点是,索引返回的结果是一个“视图”,即它与原数据集共享一片内存。如果希望硬拷贝,可调用copy函数。

最后,还有另一种索引法:fancy indexing

3.3.2 操作

数组可以reshape

reshape

顾名思义,reshape就是改变数组的shape。

x = rand(6)
x.reshape((2, 3))
# array([[ 0.08883653,  0.66242125,  0.03360294],
#        [ 0.72060903,  0.69445323,  0.21245629]])

其它相关函数包括ravel、squeeze和expand_dims。

重复与连接(repeating and concatenating)

x = arange(3)

tile(x, (2, 1))
# array([[0, 1, 2],
#        [0, 1, 2]])

repeat(x, 2)
# array([0, 0, 1, 1, 2, 2])

其它相关函数包括hstack、vstack、dstack、concatenate,以及split、hsplit、vsplit、dsplit。

广播(broadcasting)

在两个数组shape不同时,NumPy仍允许它们执行某些运算,这个特性称为广播。广播可视作NumPy自动扩展了数组内容,以使得数组的shape相同。

def mul_table(n):
    M = arange(1, n+1).reshape((-1, 1))
    N = arange(1, n+1).reshape((1, -1))
    return M * N

这里M和Nshape并不符合向量相乘之条件,但仍可相乘,NumPy自行帮我们做了处理。

排列(permuting)

transpose、fliplr、flipud、roll、rot90。

3.3.3 计算

如果两个数组维度兼容,那么四则运算就可以进行,不过这些运算都是元素级的(element-wise)。特别地,对于两个矩阵来说,它们的乘积应该用dot()

常见的一元操作包括:

  • -A
  • A ** x
  • abs(A)
  • sign(A)
  • floor(A)
  • sqrt(A)
  • log(A)
  • exp(A)
  • 三角函数、双曲函数...

如四则运算一样,这些函数都是元素级的。

NumPy也支持sum和prod这样的函数,可用于求解数组的和和乘积,axis参数可指定这些操作应用的范围。max和min返回数组的最大值和最小值,argmax和argmin则返回相应的索引。

from numpy import array

def locate(data, x, y):
    locations = data[['Latitude', 'Longitude']].as_matrix()
    d = locations - array([x, y])

    distances = d[:, 0] ** 2 + d[:, 1] ** 2

    closest = distances.argmin()
    return data.AccentCity[closest]

locate(data, 48.861, 2.3358)
# 'Paris'

可以看到NumPy的数组操作使得实现简洁了很多,也更符合一般的“向量化”的思路。

统计函数

  • mean
  • median
  • std
  • var

describe()函数类似于R中的summary函数。

相关函数还有diff、cumsum、cumprod。