什么是numpy
一个在Python中做科学计算的基础库,重在数值计算,也是大部分PYTHON科学计算库的基础库,多用于在大型、多维数组上执行数值运算。
numpy基础
numpy创建数组(矩阵)
np.array()
numpy创建数组测试:
import numpy as np
#使用numpy生成数组,得到numpt.ndarray数据类型
t1 = np.array([1,2,3])
print('t1',t1)
print(type(t1))
t2 = np.array(range(10))
print('t2',t2)
t3 = np.arange(10) #numpy自有的方法,快速生成一堆数字, 和range(n)方法一样
print('t3',t3)
#dtype numpy数组存储的数据类型
print('t3 dtype',t3.dtype)
t4 = np.arange(4,10,2)
print('t4', t4)
输出:
t1 [1 2 3]
<class 'numpy.ndarray'>
t2 [0 1 2 3 4 5 6 7 8 9]
t3 [0 1 2 3 4 5 6 7 8 9]
t3 dtype int32
t4 [4 6 8]
指定numpy数组的数据类型 array.astype()
numpy中常见的更多数据类型
改变numpy数组的数据类型:
array.astype(dtype)
numpy数据类型测试:
import numpy as np
import random
#numpy中的数据类型
t1 = np.array(range(1,4), dtype=float)
print(t1)
print(t1.dtype)
#numpy中的bool类型
t2 = np.array(range(0,4), dtype='bool')
print(t2)
print(t2.dtype)
#调整numpy array的数据类型
t3 = t2.astype('int8')
print(t3)
print(t3.dtype)
# numpy中的小数
t4 = np.array([random.random() for i in range(10)])
print(t4)
print(t4.dtype)
# 取小数
t5 = np.round(t4,2)
print(t5)
输出:
[1. 2. 3.]
float64
[False True True True]
bool
[0 1 1 1]
int8
[0.81910089 0.12703546 0.08847865 0.23887472 0.68077415 0.36955078
0.10936044 0.33791395 0.06766471 0.22993483]
float64
[0.82 0.13 0.09 0.24 0.68 0.37 0.11 0.34 0.07 0.23]
修改numpy数组的形状
array.reshape()
reshape()返回一个新的array,原始array不会改变。
array.flatten()
将数组展平为一维数组
import numpy as np
t1 = np.arange(12)
print('t1',t1)
#查看numpy数组的形状
print('t1 shape',t1.shape)
t2 = np.array([[1,2,3],[4,5,6]])
print('t2', t2)
print('t2 shape',t2.shape)
#修改numpy数组的形状
t3 = t1.reshape((3,4))
print('t3',t3)
print('t3 shape',t3.shape)
#将数组变为一维数组
t4 = t3.reshape(-1)
print('t4', t4)
print('t4 shape', t4.shape)
#将数组展平
t5 = t3.flatten()
print('t5', t5)
print('t5 shape', t5.shape)
输出:
t1 [ 0 1 2 3 4 5 6 7 8 9 10 11]
t1 shape (12,)
t2 [[1 2 3]
[4 5 6]]
t2 shape (2, 3)
t3 [[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
t3 shape (3, 4)
t4 [ 0 1 2 3 4 5 6 7 8 9 10 11]
t4 shape (12,)
t5 [ 0 1 2 3 4 5 6 7 8 9 10 11]
t5 shape (12,)
数组和数字的运算
将数组和数字进行运算的时候,numpy会将数组中的每一个元素和数字进行计算(numpy的广播机制)。
import numpy as np
t1 = np.arange(24).reshape(4,6)
print(t1)
print(t1 + 2)
print(t1*4)
输出:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
[[ 2 3 4 5 6 7]
[ 8 9 10 11 12 13]
[14 15 16 17 18 19]
[20 21 22 23 24 25]]
[[ 0 4 8 12 16 20]
[24 28 32 36 40 44]
[48 52 56 60 64 68]
[72 76 80 84 88 92]]
numpy数组和数组的计算
形状一样的numpy数组,对应位置元素进行计算。
若形状不一样的数组,如果某一个维度一样,则在某一个维度上进行计算。
import numpy as np
t1 = np.arange(24).reshape((4,6))
t2 = np.arange(100,124).reshape((4,6))
t3 = np.arange(4).reshape((4,1))
t4 = np.arange(6).reshape((1,6))
print('t1:\n',t1)
print('t2:\n',t2)
print('t3:\n',t3)
print('t4:\n',t4)
print('t1+t2:\n',t1+t2) #对应元素位置相加
print('t1-t3:\n',t1-t3) #t1每一列减去t3
print('t2-t4:\n',t2-t4) #t2每一行减去t4
print('t1*t2:\n',t1*t2) #t1元素乘以t2对应元素
输出:
t1:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
t2:
[[100 101 102 103 104 105]
[106 107 108 109 110 111]
[112 113 114 115 116 117]
[118 119 120 121 122 123]]
t3:
[[0]
[1]
[2]
[3]]
t4:
[[0 1 2 3 4 5]]
t1+t2:
[[100 102 104 106 108 110]
[112 114 116 118 120 122]
[124 126 128 130 132 134]
[136 138 140 142 144 146]]
t1-t3:
[[ 0 1 2 3 4 5]
[ 5 6 7 8 9 10]
[10 11 12 13 14 15]
[15 16 17 18 19 20]]
t2-t4:
[[100 100 100 100 100 100]
[106 106 106 106 106 106]
[112 112 112 112 112 112]
[118 118 118 118 118 118]]
t1*t2:
[[ 0 101 204 309 416 525]
[ 636 749 864 981 1100 1221]
[1344 1469 1596 1725 1856 1989]
[2124 2261 2400 2541 2684 2829]]
numpy数组的广播原则
轴 (axis)
轴在numpy中可以理解为方向,使用0,1,2…数字表示,对于一个一维数组,只有一个0轴,对于2维数组(shape(2,2)),有0轴和1轴,对于三维数组(shape(2,2, 3)),有0,1,2轴。
有了轴的概念之后,我们计算会更加方便,比如计算一个2维数组的平均值,必须指定是计算哪个方向上面的数字的平均值。
回顾np.arange(0,10).reshape((2,5)),reshpe中2表示0轴长度(包含数据的条数)为2, 1轴长度为5, 所以数组一共有2X5等于10个数据。
二维数组的轴:
三维数组的轴:
numpy数组的转置 (三种方法)
array.transpose()
array.T
array.swapaxes(1,0)
from struct import unpack
import numpy as np
t = np.arange(24).reshape(4,6)
print('t:\n',t)
print('t.transpose():\n', t.transpose())
print('t.T:\n', t.T)
print('t.swapaxes(1,0):\n', t.swapaxes(1,0))
输出:
t:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
t.transpose():
[[ 0 6 12 18]
[ 1 7 13 19]
[ 2 8 14 20]
[ 3 9 15 21]
[ 4 10 16 22]
[ 5 11 17 23]]
t.T:
[[ 0 6 12 18]
[ 1 7 13 19]
[ 2 8 14 20]
[ 3 9 15 21]
[ 4 10 16 22]
[ 5 11 17 23]]
t.swapaxes(1,0):
[[ 0 6 12 18]
[ 1 7 13 19]
[ 2 8 14 20]
[ 3 9 15 21]
[ 4 10 16 22]
[ 5 11 17 23]]
numpy读取本地数据
CSV:Comma-Separated Value,逗号分隔值文件。
显示:表格状态。
源文件:换行和逗号分隔行列的格式化文本,每一行的数据表示一条记录。
由于csv便于展示,读取和写入,所以很多地方也是用csv的格式存储和传输中小型的数据。
numpy从文本文件中读取数据。
np.loadtxt(fname,dtype=np.float,delimiter=None,skiprows=0,usecols=None,unpack=False)
a.csv
import numpy as np
data = np.loadtxt('d:/a.csv', delimiter=',', dtype = int, unpack = True) #unpack 转置,将得到的numpy数组进行转置, delimiter是array分隔字符串。
print(data)
print(type(data))
输出:
[[ 1 2 3 4]
[24 25 26 24]]
<class 'numpy.ndarray'>
numpy索引和切片
numpy中使用较多的功能。
索引和切片
import numpy as np
t = np.arange(24).reshape(4,6)
print('t:\n',t)
#取连续多行
print('t[2:]:\n',t[2:])
#取不连续的多行
print('t[[0,2,3]]:\n',t[[0,2,3]])
#取连续多个列
print('t[:,1:]:\n',t[:,1:])
#取不连续的多个列
print('t[:,[0,3,5]]:\n',t[:,[0,3,5]])
#取某一个点
print('t[2,3]:\n', t[2,3])
#取多个不相邻的点
#选出来的结果是(0,0) (2,1) (2,3)
c = t[[0,2,2],[0,1,3]]
print(c)
输出:
t:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
t[2:]:
[[12 13 14 15 16 17]
[18 19 20 21 22 23]]
t[[0,2,3]]:
[[ 0 1 2 3 4 5]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
t[:,1:]:
[[ 1 2 3 4 5]
[ 7 8 9 10 11]
[13 14 15 16 17]
[19 20 21 22 23]]
t[:,[0,3,5]]:
[[ 0 3 5]
[ 6 9 11]
[12 15 17]
[18 21 23]]
t[2,3]:
15
[ 0 13 15]
numpy中数值的修改
import numpy as np
t = np.arange(24).reshape(4,6)
print('t:\n',t)
t[:,2:4] = 0
print(t)
输出:
t:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
[[ 0 1 0 0 4 5]
[ 6 7 0 0 10 11]
[12 13 0 0 16 17]
[18 19 0 0 22 23]]
numpy中的布尔索引
import numpy as np
t = np.arange(24).reshape(4,6)
print('t:\n',t)
#t中小于10的替换成3
t[t<10] = 3
print(t<10)
print(t)
输出:
t:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
[[ True True True True True True]
[ True True True True False False]
[False False False False False False]
[False False False False False False]]
[[ 3 3 3 3 3 3]
[ 3 3 3 3 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
numpy中的三元运算符 np.where(t,num1,num2)
将numpy数组数值固定在num1-num2之间
np.where(t,num1,num2)
将t中小于t的替换为num1,大于等于t的替换为num2
import numpy as np
t = np.arange(24).reshape(4,6)
print('t:\n',t)
#t中小于10的替换成0,大于等于10的赋值为10
t2 = np.where(t<10,0,10)
print(t2)
输出:
t:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
[[ 0 0 0 0 0 0]
[ 0 0 0 0 10 10]
[10 10 10 10 10 10]
[10 10 10 10 10 10]]
numpy中的clip(裁剪)np.clip(t,num1,num2)
np.clip(t,num1,num2)
将t中小于num1的替换为num1;大于num2的替换为num2
from cmath import nan
import numpy as np
t = np.arange(24).reshape(4,6)
t = t.astype(float)
t[3,3:] = np.nan
print('t:\n',t)
#t中小于10的替换成10,大于等于10的替换18
#但是nan没有被替换,
t2 = t.clip(10,18)
print(t2)
输出:
t:
[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. 8. 9. 10. 11.]
[12. 13. 14. 15. 16. 17.]
[18. 19. 20. nan nan nan]]
[[10. 10. 10. 10. 10. 10.]
[10. 10. 10. 10. 10. 11.]
[12. 13. 14. 15. 16. 17.]
[18. 18. 18. nan nan nan]]
numpy常用统计方法
np.sum() 求和
np.sum(t) 对所有元素进行求和 array.sum()
np.sum(t, axis = 0) 按行,对所有列进行求和 array.sum(axis = 0)
np.sum(t, axis = 1) 按列,对所有行进行求和 array.sum(axis = 1)
import numpy as np
t = np.arange(24).reshape(4,6)
#对所有元素进行求和
r1 = np.sum(t)
#按行,对每列进行求和
r2 = np.sum(t,axis=0)
#按列,对每行进行求和
r3 = np.sum(t,axis=1)
print(r1)
print(r2)
print(r3)
输出:
276
[36 40 44 48 52 56]
[ 15 51 87 123]
np.mean() 求均值
np.mean(t) 求所有元素的均值 array.mean()
np.mean(t, axis = 0) 按行,对列求均值 array.mean(axis = 0)
np.mean(t, axis = 1) 按列,对行求均值 array.mean(axis = 1)
np.midian() 求中位数 只有全局方法np.midian()形式
np.midian(t)
np.median(t, axis = 0)
np.median(t, axis = 1)
np.max() 求最大值
np.min() 求最小值
np.ptp() 求最大值和最小值之差
np.std() 求标准差
【默认返回多维数组的全部的统计结果,如果指定axis则返回一个当前轴上的结果】
标准差是一组数据平均值分散程度的一种度量。一个较大的标准差,代表大部分数值和其平均值之间差异较大;一个较小的标准差,代表这些数值较接近平均值反映出数据的波动稳定情况,越大表示波动越大,越不稳定
numpy中的nan和inf
nan和inf的数据类型为float。
nan(NAN,Nan):not a number表示不是一个数字。
什么时候numpy中会出现nan:
- 当我们读取本地的文件为float的时候,如果有缺失,就会出现nan;
- 当做了一个不合适的计算的时候(比如无穷大(inf)减去无穷大);
inf(-inf,inf):infinity,inf表示正无穷,-inf表示负无穷
什么时候回出现inf包括(-inf,+inf)
- 比如一个数字除以0,(python中直接会报错,numpy中是一个inf或者-inf)。
统计数组中有多少nan
from cmath import nan
import numpy as np
t = np.arange(24).reshape(4,6)
t = t.astype(float)
t[3,3:] = np.nan
#方法一:通过t!=t判断
r = t!=t # np.nan !=- np.nan 所以遇到nan t!=t 相应位置会返回True
print(r)
count = np.count_nonzero(r) # 统计t!=t的非零个数就是nan的个数
print(count)
#方法二:通过np.isnan判断
r = np.isnan(t)
count = np.count_nonzero(r)
print()
输出:
[[False False False False False False]
[False False False False False False]
[False False False False False False]
[False False False True True True]]
3
3
numpy中nan的注意点
替换array中的nan
在一组数据中单纯的把nan替换为0,合适么?会带来什么样的影响?
比如,全部替换为0后,替换之前的平均值如果大于0,替换之后的均值肯定会变小,所以更一般的方式是把缺失的数值替换为均值(中值)或者是直接删除有缺失值的一行。
import numpy as np
def fill_array(t):
for i in range(t.shape[1]):
temp_col = t[:,i] #当前的一列
num_nan = np.count_nonzero(temp_col != temp_col)
if num_nan != 0:
#选中当前一列不为nan的array
temp_col_not_nan = temp_col[temp_col == temp_col]
#当前一列不为nan的array的均值
mean = temp_col_not_nan.mean()
#将temp_col的nan位置替换为均值
temp_col[np.isnan(temp_col)] = mean
return t
if __name__ == '__main__':
t = np.arange(24).reshape(4,6).astype('float')
t[1,2:] = np.nan
print(t)
fill_t = fill_array(t)
print(fill_t)
输出:
[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. nan nan nan nan]
[12. 13. 14. 15. 16. 17.]
[18. 19. 20. 21. 22. 23.]]
[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. 12. 13. 14. 15.]
[12. 13. 14. 15. 16. 17.]
[18. 19. 20. 21. 22. 23.]]
统计、绘图
英国和美国各自youtube1000的数据结合之前的matplotlib绘制出各自的评论数量的直方图。
针对读取的数据差距特别大,可以选择使用numpy的布尔索引,过滤掉过大或者过小的数据,以更直观的反应数据。
import numpy as np
from matplotlib import pyplot as plt
path1 = 'GB_video_data_numbers.csv'
path2 = 'US_video_data_numbers.csv'
t_gb = np.loadtxt(path1, delimiter = ',', dtype = 'int')
#取评论数据
t_gb_comments = t_gb[:,-1]
#选择比5000小的数据
t_gb_comments = t_gb_comments[t_gb_comments<5000]
max = t_gb_comments.max()
min = t_gb_comments.min()
#设置组组距
d = 100
bin_nums = int((max-min)/d)
#设置图像大小
fig = plt.figure(figsize=(20,8), dpi = 80)
#绘制直方图
plt.hist(t_gb_comments,bins=bin_nums)
#展示
plt.show()
结果:
采用numpy的布尔索引过滤掉>5000的值,直方图x轴数据在0-5000之间。组距根据可视化结果动态调整为d = 100,bins = (max(t)-min(t))/d。
希望了解英国的youtube中视频的评论数和喜欢数的关系,应该如何绘制改图?
from turtle import width
import numpy as np
from matplotlib import pyplot as plt
path1 = 'GB_video_data_numbers.csv'
path2 = 'US_video_data_numbers.csv'
t_uk = np.loadtxt(path1, delimiter = ',', dtype = 'int')
#取评论数据
t_uk_comments = t_uk[:,-1]
#取用户喜欢数据
t_uk_like = t_uk[:,1]
#选择喜欢数量比5e5小的
t_uk_comments_ = t_uk_comments[t_uk_like<=5e5]
t_uk_like_ = t_uk_like[t_uk_like<=5e5]
#设置图像大小
fig = plt.figure(figsize=(20,8), dpi = 80)
#绘制直方图
plt.scatter(t_uk_like_, t_uk_comments_)
#展示
plt.show()
结果:
numpy数组的拼接
np.vstack((t1,t2)) #垂直拼接
np.hstack((t1,t2)) #水平拼接
数组水平或者竖直拼接很简单,但是拼接之前应该注意什么?
竖直拼接的时候:每一列代表的意义相同。
如果每一列的意义不同,这个时候应该交换某一组的数的列,让其和另外一类相同。
如何交换某个数组的行或者列呢?
测试数组拼接:
from turtle import width
import numpy as np
from matplotlib import pyplot as plt
uk_data = 'GB_video_data_numbers.csv'
us_data = 'US_video_data_numbers.csv'
uk_data = np.loadtxt(uk_data, delimiter = ',', dtype = 'int')
us_data = np.loadtxt(us_data, delimiter = ',', dtype = 'int')
#构造全0全1数组
zeros_data = np.zeros((uk_data.shape[0],1)).astype(int)
ones_data = np.ones((us_data.shape[0],1)).astype(int)
uk_data = np.hstack((uk_data, zeros_data))
us_data = np.hstack((us_data, ones_data))
final_data = np.vstack((uk_data, us_data))
print(final_data)
结果:
[[7426393 78240 13548 705 0]
[ 494203 2651 1309 0 0]
[ 142819 13119 151 1141 0]
...
[ 142463 4231 148 279 1]
[2162240 41032 1384 4737 1]
[ 515000 34727 195 4722 1]]
numpy数组中的其它方法
- 获取最大值最小值的位置
np.argmax(t,axis=0)
np.argmin(t,axis=1) - 创建一个全0的数组: np.zeros((3,4))
- 创建一个全1的数组:np.ones((3,4))
- 创建一个对角线为1的正方形数组(方阵):np.eye(3)
numpy生成随机数:
np.random()
- 均匀分布 np.random.rand(shape) 浮点数:0-1
在相同的大小范围内的出现概率是等可能的。
生成均匀分布随机数测试:
from turtle import width
import numpy as np
from matplotlib import pyplot as plt
data = np.random.rand(1000)
plt.hist(data)
plt.show()
print(data)
结果:
- 正态分布 np.random.randn(shape)
呈钟型,两头低,中间高,左右对称。
生成正态分布随机数测试:
from turtle import width
import numpy as np
from matplotlib import pyplot as plt
data = np.random.randn(1000)
plt.hist(data)
plt.show()
print(data)
结果: