[NumPy]入门-学习笔记

[NumPy]入门-学习笔记


实习是关于机器学习的一个项目,博主渣硕之前只有学过Python的基础,没有Python方面的项目经历。鉴于目前Python在机器学习方面的火爆,以及对Python未来的看好。决定用Python来,希望能够完成实习任务。推荐一个很好的Data Science方向在线学习网站DATAQUEST。该网站部分免费,免费部分也很有意思,思路非常清晰。本文只介绍NumPy的常用的基本操作。

数据集


本来想自己敲代码,演示下。但是原文的数据集: world_alcohol.csv 我没有找到,所以我只能“翻译”原文了。教程中的数据如下表所示(后续的联系都是基于这个数据集):

YearRegionCountryBeverage TypesDisplay Value
1986‘Western Pacific’‘Viet Nam’‘Wine’0
1986‘Americas’‘Uruguay’‘Other’0.5
1985‘Africa’‘Cte d’Ivoire’‘Wine’1.62

每行代表改国家在某年某类饮品的人均消费量(单位:升)。比如1986年越南人均酒的消费量为0升

  • Year: 调查年份
  • Region: 国家所在地区
  • Country: 国家
  • Beverage Types: 饮品类别
  • Display Value: 该国公民该类饮品平均消费量,单位升

列表的列表 (list of lists)


列表的列表,其实就是矩阵 (Matrix)。原生的Python就支持此操作。在介绍NumPy之前,先介绍Python原生操作。这样方便对比两者之间的优劣。

world_alcohol.csv 中的数据是表格的形式存在的,其实就是矩阵啦。下面是数据集中的几个数据展示。

world_alcohol = [
                 [1986, "Western Pacific", "Viet Nam", "Wine", 0],
                 [1986, "Americas", "Uruguay", "Other", 0.5],
                 [1986, "Africa", "Cte d'Ivoire", "Wine", 1.62]
                ]

我们能用list的操作来得到第一行数据:

first_row = world_alcohol[0]

first_row 的内容是:

[1986, "Western Pacific", "Viet Nam", "Wine", 0]

first_row[0] 能得到1986, first_row[1]能得到Wine。第一个index取得相应的行,第二个index取得相应的列。行列号都是从0开始的。比如world_alcohol[1][1]能德高‘Americas’。

原生Python中不方便的地方是计算统计值。比如我们想计算Display Value的平均值,我们必须要循环遍历数组,如下:

>>> liters_drank = [] 
>>> for row in world_alcohol:
...     liters_drank.append(row[4])
>>> liters_drank = liters_drank[1:len(liters_drank)]
>>> total = 0
>>> for item in liters_drank:
...    total = total + float(item)
>>> print(sum(liters_drank) / len(liters_drank))

我们可以看到,用原生list计算数据统计数值的时候,需要遍历list,这样很不方便。NumPy引入了对矩阵的统计方法。

NumPy


Numpy比Python原生的数组,矩阵操作高效多了。Numpy是Python用来操作多维数组的一个模块。它效率更高,提供的接口方法更多。

创建方法

  • 直接用array()方法创建
>>> import numpy
>>> 
>>> vector = numpy.array([5, 10, 15, 20])
  • 引用 .csv文件, genfromtext(filename, dtype, delimiter…). 需要注意的是NumPy只能是同一种数据类型,关于数据类型,下文中会讲到。
>>> import numpy
>>> 
>>> world_alcohol = numpy.genfromtext('world_alcohol.csv', delimiter = ',' =)

数据类型

可以用dtype属性来查看数据类型,一个NumPy数组只支持一种数据类型。NumPy可支持的数据类型有:

  • bool: 布尔型, True 或者False
  • int: 整型,其中有 int16, int32, 和 int64类型。后缀16, 32, 和 64 表示数据长度。
  • float:浮点数。同样有float16, float32, 和 float64。后缀16, 32, 和 64 表示数据长度,长度越长,数据准确度越高。
  • string:字符串。

读取world_alcohol.csv会发现,里面有数据类型na (Not Available)nan (Not A Number),前者表示读取的数值是空的,是不存在的。后者是因为数据类型转换出错。

>>> numbers = numpy.array([1, 2, 3, 4])
>>> print(numbers.dtype)
int64 
# the datatype is int64 

Array Shape

通过shape属性能够查看array的大小, 或者通过shape()方法查看

>>> vector1 = numpy.array([1, 2, 3, 4])
>>> # use shape property to print
>>> print(vector1.shape) 
4

>>> vector2 = numpy.array([[1, 2, 3], [4, 5, 6]])
>>> # use shape() method to print
>>> print(numpy.shape(vector2))
(2, 3)

正确读取数据

我们在数据类型这段提到过nan错误,我们可以用genfromtxt()来转化数据类型。对于world_alcohol.csv我们可以这样做:

  • dtype关键字要设定为‘U75’. 表示每个值都是75byte的 unicode。
  • skip_header关键字设为 True, 这个参数能让跳过表格第一行,可就是关于列信息那行。
>>> import numpy
>>> import csv

>>> world_alcohol_csv = csv.reader(open('world_alcohol.csv'))
>>> world_alcohol = numpy.genfromtxt('world_alcohol.csv', dtype='U75', delimiter=',', skip_head=True)

Indexing Arrays

NumPy支持list一样的定位操作。

>>> matrix = numpy.array([
...                         [5, 10, 15], 
...                         [20, 25, 30]
...                      ])
>>> print(matrix[1, 2])
30

切片(Slicing)

NumPy支持list一样的切片操作。

>>> matrix = numpy.array([
...                     [5, 10, 15], 
...                     [20, 25, 30],
...                     [35, 40, 45]
...                   ])
>>> print(matrix[:1])
[[ 5 10 15]]
>>> print(matrix[:,1])
[10 25 40]
>>> print(matrix[1:3, 0:2])
[[20 25]
 [35 40]]

数组比较

NumPy最强大的地方是数组的比较。数组比较会产生boolean值。
对数组的比较:

>>> vector = numpy.array([1, 2, 3, 4])
>>> vector == 1
array([ True, False, False, False], dtype=bool)

对矩阵的比较:


>>> matrix = numpy.array([
...             [5, 10, 15],
...             [20, 25, 30],
...             [35, 40, 45]
...     ])
>>> matrix == 25
array([[False, False, False],
       [False,  True, False],
       [False, False, False]], dtype=bool)

现在我们做一个练习,在world_alcohol.csv中:

  • 获取国家是否是Canada的数组
  • 获取年份是否是1984的数组
>>> import numpy
>>> 
>>> # 重新演示如何从csv文件中生成矩阵
>>> world_alcohol = numpy.genfromtxt('world_alcohol.csv', dtype='U75', delimiter=',', skip_header=True)
>>>    
>>> countries_canada = (world_alcohol[:, 2] == 'Canada')
>>> years_1984 = (world_alcohol[:, 0] == '1984')

选择元素

现在我们要体验一下为什么数组比较是这么强大。我们可以用数组比较得到的布尔值来条件取值。
在数组中:

>>> vector = numpy.array([5, 10, 15, 20])
>>> print(vector)
[ 5 10 15 20]
>>> equal_to_ten = (vector == 10)
>>> print(equal_to_ten)
[False  True False False]
>>> # 输出只有相对于位布尔值是True位置上的值
>>> print(vector[equal_to_ten])
[10]

在矩阵中:

>>> matrix = numpy.array([
...             [5, 10, 15],
...             [20, 25, 30],
...             [35, 40, 45]
...     ])
>>> second_column_25 =  (matrix[:,1] == 25)
>>> print(second_column_25)
[False  True False]
>>> print(matrix[second_column_25, :])
[[20 25 30]]
>>> 

在这段代码中:

  • 我们先创立数组matrix
  • 将matrix的第二列和25比较,得到一个布尔值数组second_column_25
  • 在matrix中,选择second_column_25是True的行

现在做一个小练习,在world_alcohol中获取国家是Algeria(阿尔及利亚)的数据:


>>> country_is_algeria = world_alcohol[:, 2] == 'Algeria'
>>> country_algeria = world_alcohol[country_is_algeria, :]

我们没有world_alcohol.csv的数据集,我贴一份从DATAQUEST上得到的运行结果吧

ndarray (<class 'numpy.ndarray'>)
array([['1984', 'Africa', 'Algeria', 'Spirits', '0.01'],
       ['1987', 'Africa', 'Algeria', 'Beer', '0.17'],
       ['1987', 'Africa', 'Algeria', 'Spirits', '0.01'],
       ['1986', 'Africa', 'Algeria', 'Wine', '0.1'],
       ['1984', 'Africa', 'Algeria', 'Other', '0'],
       ['1989', 'Africa', 'Algeria', 'Beer', '0.16'],
       ['1989', 'Africa', 'Algeria', 'Spirits', '0.01'],
       ['1989', 'Africa', 'Algeria', 'Wine', '0.23'],
       ['1986', 'Africa', 'Algeria', 'Spirits', '0.01'],
       ['1984', 'Africa', 'Algeria', 'Wine', '0.12'],
       ['1985', 'Africa', 'Algeria', 'Beer', '0.19'],
       ['1985', 'Africa', 'Algeria', 'Other', '0'],
       ['1986', 'Africa', 'Algeria', 'Beer', '0.18'],
       ['1985', 'Africa', 'Algeria', 'Wine', '0.11'],
       ['1986', 'Africa', 'Algeria', 'Other', '0'],
       ['1989', 'Africa', 'Algeria', 'Other', '0'],
       ['1987', 'Africa', 'Algeria', 'Other', '0'],
       ['1984', 'Africa', 'Algeria', 'Beer', '0.2'],
       ['1985', 'Africa', 'Algeria', 'Spirits', '0.01'],
       ['1987', 'Africa', 'Algeria', 'Wine', '0.1']], 
      dtype='<U75')

替代值(Replacing Value)

NumPy可以运用布尔值来替换值。
在数组中:

>>> vector = numpy.array([5, 10, 15, 20])
>>> equal_to_ten_or_five = (vector == 10) | (vector == 5)
>>> vector[equal_to_ten_or_five] = 50
>>> print(vector)
[50, 50, 15, 20]

在矩阵中:

>>> matrix = numpy.array([
...             [5, 10, 15],
...             [20, 25, 30],
...             [35, 40, 45]
...     ])
>>> second_column_25 = matrix[:,1] == 25
>>> matrix[second_column_25, 1] = 10
>>>> print(matrix)
[[ 5 10 15]
 [20 10 30]
 [35 40 45]]

在这段代码中:

  • 我们先创立数组matrix
  • 将matrix的第二列和25比较,得到一个布尔值数组second_column_25
  • 将matrix第二列值为25的替换为10

惯例,我们做一个小练习。将world_alcohol年份为1986的行替换成年份2014。

world_alcohol[world_alcohol[:, 0] == '1986', 0] = 2014
world_alcohol[world_alcohol[:, 3] == 'Wine', 3] = 'Grog'

偷个懒,数据就不粘上来了。

替换有一个很棒的应用之处,就是替换那些空值。之前提到过NumPy中只能有一个数据类型。刚才我们把所有的world_alcohol.csv中的值按String读取。所以原来的整形都被自动转换成String了。其中的空值我们很有必要把他们替换成其他值,比如数据的平均值或者把他们删除。这在大数据处理中很有必要。这里,我们演示把Display value中空值替换为0的操作。

>>> is_value_empty = world_alcohol[:, 4] == ''
>>> world_alcohol[is_value_empty, 4] = '0'

数据类型转换

我们能用astype()方法来转换数据类型。
比如,把String转换成float。如下:

>>> vector = numpy.array(["1", "2", "3"])
>>> vector = vector.astype(float)

小练习,把world_alcohol.csv中Display value从String转换成Float:

>>> alcohol_consumption = world_alcohol[:, 4]
>>> alcohol_consumption = alcohol_consumption.astype(float)

NumPy的统计计算方法

NumPy内置很多计算方法。其中最重要的统计方法有:

  • sum():计算数组元素的和;对于矩阵计算结果为一个一维数组,需要指定行或者列
  • mean():计算数组元素的平均值;对于矩阵计算结果为一个一维数组,需要指定行或者列
  • max():计算数组元素的最大值;对于矩阵计算结果为一个一维数组,需要指定行或者列
    需要注意的是,用于这些统计方法计算的数值类型必须是int或者float。
    数组例子:
>>> vector = numpy.array([5, 10, 15, 20])
>>> vector.sum()
50

矩阵例子:

>>> matrix
array([[ 5, 10, 15],
       [20, 10, 30],
       [35, 40, 45]])
>>> matrix.sum(axis=1)
array([ 30,  60, 120])
>>> matrix.sum(axis=0)
array([60, 60, 90])

有例子所示,axis = 1计算的是行的和,结果以列的形式展示。axis = 0计算的是列的和,结果以行的形式展示。

练习

NumPy的基本操作介绍得差不多了,现在需要的就是练习啦。
Ex1:计算Canada 1986年的饮品消费总量。

>>> is_canada_1986 = (world_alcohol[:, 0] == '1986') & (world_alcohol[:, 2] == 'Canada')
>>> canada_1986 = world_alcohol[is_canada_1986, :]
>>> canada_1986[canada_1986[:, 4] == '', 4] = '0'
>>> canada_alcohol = canada_1986[:, 4]
>>> canada_alcohol = canada_alcohol.astype(float)
>>> total_canadian_drinking = canada_alcohol.sum()

解题方法很直接。基本思路就是先选出国家是Canada,年份是1986的数组。然后在调用NumPy内置的素描()方法。

Ex2:计算每个国家的饮品消费总量。

>>> totals = {}
>>> countries = world)alcohol[:2]
>>> 
>>> for country in countries:
...    is_country_1989 = (world_alcohol[:, 0] == '1989') & (world_alcohol[:, 2] == country)
...    country_consumption = world_alcohol[is_country_1989, :]
...    country_consumption[country_consumption[:, 4] == '', 4] = '0'
...    country_alcohol = country_consumption[:, 4].astype(float)
...    totals[country] = country_alcohol.sum()

Ex3:计算饮品消费总量最多的国家。

>>> highest_value = 0
>>> highest_key = None
>>>
>>>for key in totals.keys():
...    if totals[key] > highest_value:
...        highest_value = totals[key]
...        highest_key = key

NumPy的优缺点

通过上面基本介绍和给出的列子,我们发现NumPy比list of lists更方便:

  • 更简单地数值统计计算
  • indexing和slicing更快更简单
  • 数值类型更容易转换

NumPy多数据的处理更快更高效,所以应用很广泛。特别是在机器学习方面。
同时,我们也注意到了NumPy的不足之处:

  • 整个列表需要有相同的数据类型,这对于有些数据集来说很不方便
  • 行列只能用数值来选取,来表示。不能通过列的名称去定位列
    很幸运,前辈们已经注意到NumPy的不足之处。Pandas库很好的弥补了NumPy的缺点。下面,要开始学习Pandas了。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值