python数据探索(1)—numpy

本篇文章是python数据探索系列扫盲文章的第一篇,主要和各位朋友探讨一下numpy,后续文章会陆续介绍pandas以及Matplotlib。如有疏漏不当的地方,请留言或私信我。共同进步!
在处理一些数据时,我们常常会需要处理数组,而使用原生的array显然会比较慢。numpy有许多用 C 语言实现的底层函数,所以我们选择使用numpy进行数据探索。

一、数组基础

首先,我们明确一下研究对象——数组。在numpy里我们操作的对象就是ndarrays多维数组。我们假想一个使用环境,比如读取一个股票数据。为了
更快的使用体验,我们决定使用numpy。那么我们怎么读取这份数据呢?这涉及到numpy创建数组吧!我们来讲一下:

# 1D Array
a = np.array([0, 1, 2, 3, 4])
b = np.array((0, 1, 2, 3, 4))
c = np.arange(5)
d = np.linspace(0, 2*np.pi, 5)

print(a) # >>>[0 1 2 3 4]
print(b) # >>>[0 1 2 3 4]
print(c) # >>>[0 1 2 3 4]
print(d) # >>>[ 0.          1.57079633  3.14159265  4.71238898  6.28318531]
print(a[3]) # >>>3

我们还可以使用dtype为数据指定类型。比如:

a = np.array([2,23,4],dtype=np.int)
print(a.dtype)
# int 64

可以指定如float(64位)int32、int32等等数据类型。
还有一些特殊的数组,比如全零

a = np.zeros((3,4)) # 数据全为0,3行4列
"""
array([[ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.]])
"""

创建全一数组, 同时也能指定这些特定数据的 dtype:

a = np.ones((3,4),dtype = np.int)   # 数据为1,3行4列
"""
array([[1, 1, 1, 1],
       [1, 1, 1, 1],
       [1, 1, 1, 1]])
"""

怎么读取文件呢?一句代码可以搞定,a就是numpy数组:

    a = numpy.loadtxt('haha.txt')  

举个例子。
以载入苹果公司的历史股价数据为例。股价数据存储在CSV文件中,第一列为股票代码以标识股票(苹果公司股票代码为AAPL),第二列为dd-mm-yyyy格式的日期,第三列为空,随后各列依次是开盘价、最高价、最低价和收盘价,最后一列为当日的成交量。下面为一行数据:

AAPL,28-01-2011, ,344.17,344.4,333.53,336.1,21144800

将收盘价和成交量分别载入到两个数组中,代码如下所示:

>>> a,b=np.loadtxt("./data.csv",
...                delimiter=',',usecols=(6,7),unpack=True)
>>> print a
[ 336.1   339.32  345.03  344.32  343.44  346.5   351.88  355.2   358.16
  354.54  356.85  359.18  359.9   363.13  358.3   350.56  338.61  342.62
  342.88  348.16  353.21  349.31  352.12  359.56  360.    355.36  355.76
  352.47  346.67  351.99]

delimiter=’,’表示用逗号作为分隔符,usecols=(6,7)表示一个元组,用来指明获取哪些列的字段,unpack=True是说拆分存储不同的数据,即分别将收盘价和日成交量赋值给a和b。

现在菜已经洗好了,我们需要进行进一步的清洗。我们要做到“指哪打哪”,挑选我们真正需要的东西。
我们先定义一个多维矩阵。多维数组切片比一维数组要复杂一点,同时它也是你在用 NumPy 的时候经常会用到的。

# MD Array,
a = np.array([[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]])

print(a[2,4]) # >>>25

我们开始挑选我们需要的数据,其实无非就是某些数,某些行,某些列,某些块。

# MD slicing
print(a[0, 1:4]) # >>>[12 13 14]
print(a[1:4, 0]) # >>>[16 21 26]
print(a[::2,::2]) # >>>[[11 13 15]
                  #     [21 23 25]
                  #     [31 33 35]]
print(a[:, 1]) # >>>[12 17 22 27 32]

用一张图来说明情况。


image.png

二、数组信息获取

还是承接上文的数据,我们获得了“我们想要的数组”,那么我们总得看看我们切的数据对不对吧?那最简单的方法就是获取下信息看看。我们可以这么做:

# Array properties
a = np.array([[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]])

print(type(a)) # >>><class 'numpy.ndarray'>
print(a.dtype) # >>>int64
print(a.size) # >>>25
print(a.shape) # >>>(5, 5)
print(a.itemsize) # >>>8
print(a.ndim) # >>>2
print(a.nbytes) # >>>200

其它信息都很直观,'itemsize' 属性是每一个条目所占的字节。这个数组的数据类型是 int64,一个 int64 的大小是 64 比特,8 比特为 1 字节,64 除以 8 就得到了它的字节数,8 字节。

三、使用数组

既然获得的我们想要的数组。接下来我们就能对数组进行操作了。
那么有哪些运算呢?我们来看看基本的操作。

# Basic Operators
>>> import numpy as np
>>> a = np.arange(25)
>>> print(a)
[ 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]
>>> a = a.reshape((5,5))
>>> print(a)
[[ 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]]
>>> b = np.array([10, 62, 1, 14, 2, 56, 79, 2, 1, 45,
...               4, 92, 5, 55, 63, 43, 35, 6, 53, 24,
...               56, 3, 56, 44, 78])
>>> b = b.reshape((5,5))
>>> print(a + b)
[[ 10  63   3  17   6]
 [ 61  85   9   9  54]
 [ 14 103  17  68  77]
 [ 58  51  23  71  43]
 [ 76  24  78  67 102]]
>>> print(a - b)
[[-10 -61   1 -11   2]
 [-51 -73   5   7 -36]
 [  6 -81   7 -42 -49]
 [-28 -19  11 -35  -5]
 [-36  18 -34 -21 -54]]
>>> print(a * b)
[[   0   62    2   42    8]
 [ 280  474   14    8  405]
 [  40 1012   60  715  882]
 [ 645  560  102  954  456]
 [1120   63 1232 1012 1872]]
>>> print(a / b)
[[0.         0.01612903 2.         0.21428571 2.        ]
 [0.08928571 0.07594937 3.5        8.         0.2       ]
 [2.5        0.11956522 2.4        0.23636364 0.22222222]
 [0.34883721 0.45714286 2.83333333 0.33962264 0.79166667]
 [0.35714286 7.         0.39285714 0.52272727 0.30769231]]
>>> print(a ** 2)
[[  0   1   4   9  16]
 [ 25  36  49  64  81]
 [100 121 144 169 196]
 [225 256 289 324 361]
 [400 441 484 529 576]]
>>> print(a < b)
[[ True  True False  True False]
 [ True  True False False  True]
 [False  True False  True  True]
 [ True  True False  True  True]
 [ True False  True  True  True]]
>>> print(a.dot(b))
[[ 417  380  254  446  555]
 [1262 1735  604 1281 1615]
 [2107 3090  954 2116 2675]
 [2952 4445 1304 2951 3735]
 [3797 5800 1654 3786 4795]]

除了 dot() 之外,这些操作符都是对数组进行逐元素运算。比如 (a, b, c) + (d, e, f) 的结果就是 (a+d, b+e, c+f)。它将分别对每一个元素进行配对,然后对它们进行运算。它返回的结果是一个数组。注意,当使用逻辑运算符比如 “<” 和 “>” 的时候,返回的将是一个布尔型数组。dot() 函数计算两个数组的点积。它返回的是一个标量(只有大小没有方向的一个值)而不是数组。
dot() 函数有时候也称为点积。理解这个函数的最好方法就是看下边它的计算过程。
盗图一张,在此感谢编程派的作者!


image.png

其它一些运算符:

# dot, sum, min, max, cumsum
a = np.arange(10)

print(a.sum()) # >>>45
print(a.min()) # >>>0
print(a.max()) # >>>9
print(a.cumsum()) # >>>[ 0  1  3  6 10 15 21 28 36 45]

cumsum() 就是一个累加计算并且保存每次累加的结果,返回值就是包含所有累加结果的一个列表。比如 np.array([1, 2, 3, 4, 5]).cumsum() = [1, 3, 6, 10, 15]

四、高级索引

这个直接看例子吧!

# Fancy indexing
a = np.arange(0, 100, 10)
indices = [1, 5, -1]
b = a[indices]
print(a) # >>>[ 0 10 20 30 40 50 60 70 80 90]
print(b) # >>>[10 50 90]

布尔屏蔽(boolean masking)
布尔屏蔽是一个奇妙的特性,它允许我们根据指定条件获取数组中的元素。简单说,就是设置一个约束条件比如:mask=(a<0)用mask做下标,这样在检索的时候,都会检查一遍约束条件,这样就可以选出想要的结果。

# Boolean masking
import matplotlib.pyplot as plt

a = np.linspace(0, 2 * np.pi, 50)
b = np.sin(a)
plt.plot(a,b)
mask = b >= 0
plt.plot(a[mask], b[mask], 'bo')
mask = (b >= 0) & (a <= np.pi / 2)
plt.plot(a[mask], b[mask], 'go')
plt.show()

上边的代码展示了实现布尔屏蔽。你需要做的就是传递给数组一个与它有关的条件式,然后它就会返回给定条件下为真的值。

上边的例子将会生成下边这幅图,上面的点点就是筛选出的结果:


image.png

缺省索引是从多维数组的第一维获取索引和切片便捷方法。例如,你有一个数组 a = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]],那么 a[3] 将会返回数组第一维中索引值为 3 的元素,这里的结果是 4。

# Incomplete Indexing
a = np.arange(0, 100, 10)
b = a[:5]
c = a[a >= 50]
print(b) # >>>[ 0 10 20 30 40]
print(c) # >>>[50 60 70 80 90]

where() 函数是另外一个根据条件返回数组中的值的有效方法。只需要把条件传递给它,它就会返回一个使得条件为真的元素的列表。

# Where
a = np.arange(0, 100, 10)
b = np.where(a < 50) 
c = np.where(a >= 50)[0]
print(b) # >>>(array([0, 1, 2, 3, 4]),)
print(c) # >>>[5 6 7 8 9]

参考:
编程派教程
http://codingpy.com/article/an-introduction-to-numpy/
莫烦的教程
https://morvanzhou.github.io/tutorials/data-manipulation/np-pd/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容