一个在Python中做科学计算的基础库,重在数值计算,也是大部分Python科学计算库的基础库,多用于在大型、多维数组上执行数值运算。
numpy:处理数值型数据;快速、方便、科学计算的基础库
(1) 创建数组
# 使用numpy生成数组
import numpy as np
a=np.array([1,2,3,4,5])
b=np.array(range(1,6))
c=np.arange(1,6)
# 上面a,b,c内容相同,注意arange和range的区别
(2) 数组类别
a=np.array([1,2,3,4,5])
print=(type(a))
>>>numpy.ndarray
(3) 数据类型
a.dtype
>>>dtype('int64')
(1) 指定创建的数组的数据类型
a=np.array([1,0,1,0],dtype=np.bool) #或者使用dtype='float64'
a
>>>array([True,False,True,False],dtype=bool)
(2) 修改数组的数据类型
a.astype('i1') #或者使用a.astype(np.int8)
>>>array([1,0,1,0],dtype=bool)
(3) 修改浮点型的小数位数
import random
b=np.array([random.random() for i in range(10)]) # 生成生成10个[0,1]的8位随机小数
print(b)
print(b.dtype)
>>>[0.98313373 0.91107927 0.89802009 0.33505108 0.80601206 0.44612311 0.88800664 0.12313158 0.26119645 0.0022805 ]
>>>float64
b1=np.round(b,2) # 保留2位小数
print(b1)
>>>[0.8 0.58 0.51 0.69 0.23 0.02 0.86 0.68 0.17 0.6 ]
# 也可以用下面的方法
'%.2f' % random.random()
>>>'0.72'
(1) 查看数组的形状
数组的形状:几行几列
t1=np.arange(12)
t1.shape
>>>(12,)
t2=np.array([[1,2,3],[4,5,6]])
t2.shape
>>>(2, 3)
t3=np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]) # 三维数组
t3.shape
>>>(2, 2, 3)
(2) 修改数据的形状
t4=np.arange(12)
>>>
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
t4.reshape(3,4) # 修改形状
>>>array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
t5=np.arange(24).reshape(2,3,4) # 2块,3行4列
>>>array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
t5.reshape(4,6) # 将t5转成二维数组
>>>array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
t5.reshape(24,) # 将t5转成一维数组
>>>array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23])
t5.reshape(24,1) # 将t5转成一维数组
>>>array([[ 0],
[ 1],
[ 2],
[ 3],
[ 4],
[ 5],
[ 6],
[ 7],
[ 8],
[ 9],
[10],
[11],
[12],
[13],
[14],
[15],
[16],
[17],
[18],
[19],
[20],
[21],
[22],
[23]])
t5.reshape(1,24) # 将t5转成一维数组
>>>array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]])
t5=t5.reshape(4,6) # 将t5转成二维数组
>>>array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
# 方法一:转成一维数组 reshape
t6=t5.reshape((t5.shape[0]*t5.shape[1],))
>>>array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23])
# 方法二:转成一维数组 flatten
t5.flatten()
>>>array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23])
(1) 数组和数的计算
d1=np.arange(24).reshape(4,6)
>>>array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
d1+2
>>>array([[ 2, 3, 4, 5, 6, 7],
[ 8, 9, 10, 11, 12, 13],
[14, 15, 16, 17, 18, 19],
[20, 21, 22, 23, 24, 25]])
d1*2
>>>array([[ 0, 2, 4, 6, 8, 10],
[12, 14, 16, 18, 20, 22],
[24, 26, 28, 30, 32, 34],
[36, 38, 40, 42, 44, 46]])
d1/2
>>>array([[ 0. , 0.5, 1. , 1.5, 2. , 2.5],
[ 3. , 3.5, 4. , 4.5, 5. , 5.5],
[ 6. , 6.5, 7. , 7.5, 8. , 8.5],
[ 9. , 9.5, 10. , 10.5, 11. , 11.5]])
d1/0
>>>array([[nan, inf, inf, inf, inf, inf],
[inf, inf, inf, inf, inf, inf],
[inf, inf, inf, inf, inf, inf],
[inf, inf, inf, inf, inf, inf]])
# nan: not a number; inf: infinity
(2) 数组和数组的计算
d1=np.arange(24).reshape(4,6)
>>>array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
d2=np.arange(100,124).reshape(4,6)
>>>array([[100, 101, 102, 103, 104, 105],
[106, 107, 108, 109, 110, 111],
[112, 113, 114, 115, 116, 117],
[118, 119, 120, 121, 122, 123]])
d1+d2
>>>array([[100, 102, 104, 106, 108, 110],
[112, 114, 116, 118, 120, 122],
[124, 126, 128, 130, 132, 134],
[136, 138, 140, 142, 144, 146]])
d1*d2 # 点乘
>>>array([[ 0, 101, 204, 309, 416, 525],
[ 636, 749, 864, 981, 1100, 1221],
[1344, 1469, 1596, 1725, 1856, 1989],
[2124, 2261, 2400, 2541, 2684, 2829]])
(3) 广播原则
定义:如果两个数组的后缘维度,即从末尾开始算起的维度,的轴长相符或其中一方的长度为1,则认为他们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行。
怎么理解呢?
-可以把维度指的是shape所对应的数字个数
那么问题来了:
-shape(3,3,3)的数组能够和(3,2)的数组进行计算?——不能
-shape(3,3,2)的数组能够和(3,2)的数组进行计算?——能
有什么好处呢?
-举个例子:每列的数据减去列的平均值的结果
d3=np.arange(0,24).reshape(4,6)
>>>array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
d4=np.array([0,1,2,3,4,5])
>>>array([0, 1, 2, 3, 4, 5])
d5=np.arange(4).reshape(4,1)
>>>array([[0],
[1],
[2],
[3]])
d3-d4
>>>array([[ 0, 0, 0, 0, 0, 0],
[ 6, 6, 6, 6, 6, 6],
[12, 12, 12, 12, 12, 12],
[18, 18, 18, 18, 18, 18]])
d3-d5
>>>array([[ 0, 1, 2, 3, 4, 5],
[ 5, 6, 7, 8, 9, 10],
[10, 11, 12, 13, 14, 15],
[15, 16, 17, 18, 19, 20]])
(1) 轴的介绍
轴(axis):方向,使用0,1,2…数字表示。对于1个一维数组,只有1个0轴,对于二维数组(shape(2,2)),有0轴和1轴,对于三维数组(shape(2,2,3)),有0,1,2轴.
优点:计算方便。比如计算1个二维数组的平均值,必须指定是计算哪个方向上面的数字的平均值。
问题:在前面的知识,轴在哪里?
np.arange(0,10).reshape(2,5),reshape中2表示0轴长度(包含数据的条数)为2,1轴长度为5,2×5一共10个数据
(2) 读取数据
np.loadtxt(frame,dtype=np.float,delimiter=None,skiprows=0,usecols=None,unpack=False)
参数 | 解释 |
---|---|
frame | 文件、字符串或产生器,可以是.gz或.bz2压缩文件 |
dtype | 数据类型,可选,CSV的字符串以什么数据类型读入数组中,默认np.float |
delimiter | 分隔字符串,默认是空格,改为逗号 |
skiprows | 跳过前x行,一般跳过第1行表头 |
usecols | 读取指定的列,索引,元组类型 |
unpack | True:读入属性将分别写入不同数组变量;False:读入数据只写入1个数据变量,默认False |
问题:现在这里有一个英国和美国各自youtube1000多个视频的点击,喜欢,不喜欢,评论数量([‘views’,‘like’,‘comment’,‘comment_total’])的csv,运用上述知识,对其对其进行操作
数据来源:https://www.kaggle.com/datasnaek/youtube/data
import numpy as np
us_file_path='./youtube_video_data/US_video_data_numbers.csv'
uk_file_path='./youtube_video_data/GB_video_data_numbers.csv'
t1=np.loadtxt(us_file_path,dtype='int',delimiter=','unpack=True)
# delimiter:指定边界符号是什么,不指定会导致每行数据为一个整体的字符串而报错
# dtype:默认情况下对于较大的数据会将其变为科学计数的方式
# upack:False:默认情况,实际数据;True:转置效果
(3) 矩阵转置
转置:是一种变换,对于numpy中的数组来说,就是在对角线方向交换数据,目的也是为了更方便地去处理数据。
下面三种方法呈现的效果是一样的。
# 矩阵转置的方法
t2=np.arange(24).reshape(4,6)
>>>array([[ 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.transpose()
>>>array([[ 0, 6, 12, 18],
[ 1, 7, 13, 19],
[ 2, 8, 14, 20],
[ 3, 9, 15, 21],
[ 4, 10, 16, 22],
[ 5, 11, 17, 23]])
# 方法二
t2.T
>>>array([[ 0, 6, 12, 18],
[ 1, 7, 13, 19],
[ 2, 8, 14, 20],
[ 3, 9, 15, 21],
[ 4, 10, 16, 22],
[ 5, 11, 17, 23]])
# 方法三
t2.swapaxes(1,0)
>>>array([[ 0, 6, 12, 18],
[ 1, 7, 13, 19],
[ 2, 8, 14, 20],
[ 3, 9, 15, 21],
[ 4, 10, 16, 22],
[ 5, 11, 17, 23]])
那么,结合之前所学的matplotlib把英国和美国的数据呈现出来?
我们应该考虑什么:
① 我们想要反映出什么样的结果,解决什么问题?
② 选择什么样的呈现方式?
③ 数据还需要做什么样的处理?
④ 写代码
t2=np.arange(24).reshape(4,6)
>>>array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
# 取行
print(t2[2])
>>>[12 13 14 15 16 17]
# 取连续多行
print(t2[2:])
>>>[[12 13 14 15 16 17]
[18 19 20 21 22 23]]
# 取不连续多行
print(t2[[0,2,3]])
>>>[[ 0 1 2 3 4 5]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
# 取列
print(t2[:,0])
>>>[ 0 6 12 18]
# 取连续的多列
print(t2[:,2:])
>>>[[ 2 3 4 5]
[ 8 9 10 11]
[14 15 16 17]
[20 21 22 23]]
# 取不连续的多列
print(t2[:,[0,2,3]])
>>>[[ 0 2 3]
[ 6 8 9]
[12 14 15]
[18 20 21]]
# 取多行多列,第3行第4列
a=t2[2,3]
print(a)
print(type(a))
>>>15
>>><class 'numpy.int32'>
# 取多行多列,第1-2行第2-4列
b=t2[0:2,1:4]
print(b)
print(type(b))
>>>[[1 2 3]
[7 8 9]]
>>><class 'numpy.ndarray'>
# 取多个不连续的点,对应位置的值
c=t2[[0,2],[0,3]] # 等价于t2[0,0] 和 t2[2,3]
print(c)
print(type(c))
>>>[ 0 15]
>>><class 'numpy.ndarray'>
数值修改
# 问题1:比如把t中小于10的数字替换为3?
t=np.arange(24).reshape(4,6)
>>>array([[ 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<10
>>>array([[ True, True, True, True, True, True],
[ True, True, True, True, False, False],
[False, False, False, False, False, False],
[False, False, False, False, False, False]])
t[t<10]=3
>>>array([[ 3, 3, 3, 3, 3, 3],
[ 3, 3, 3, 3, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
# 问题2:比如把t中小于10的数字替换为3,大于20的替换为20?
np.where(t<10,0,10) # numpy的三元运算符
>>>array([[ 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 10, 10],
[10, 10, 10, 10, 10, 10],
[10, 10, 10, 10, 10, 10]])
# clip裁剪 t.clip(a,b):把≤a的替换为a, ≥a的替换为b.
t1=t.astype(float)
t1[3,3]=np.nan # 转化为浮点型
print(t1)
>>>[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. 8. 9. 10. 11.]
[12. 13. 14. 15. 16. 17.]
[18. 19. 20. nan 22. 23.]]
(1) 数组的拼接
import numpy as np
a=np.arange(12).reshape(2,6)
>>>array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11]])
b=np.arange(12,24).reshape(2,6)
>>>array([[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
# 竖直拼接(vertically)
np.vstack(a,b)
>>>array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
# 水平拼接(horizontally)
np.hstack((a,b))
>>>array([[ 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16, 17],
[ 6, 7, 8, 9, 10, 11, 18, 19, 20, 21, 22, 23]])
(2) 数组的行列交换
t=np.arange(12,24).reshape(3,4)
>>>array([[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]])
# 行交换
t[[1,2],:]=t[[2,1],:]
>>>array([[12, 13, 14, 15],
[20, 21, 22, 23],
[16, 17, 18, 19]])
# 列交换
t[:,[0,2]]=t[:,[2,0]]
>>>array([[14, 13, 12, 15],
[22, 21, 20, 23],
[18, 17, 16, 19]])
(1) 案例分析
import numpy as np
us_data='USvideos.csv'
uk_data='GBvideos.csv'
# 加载国家数据
us_data=np.loadtxt(us_data,delimiter=',',dtype=int)
uk_data=np.loadtxt(uk_data,delimiter=',',dtype=int)
# 添加国家信息
# 构造全为0的数据
zeros_data=np.zeros(us_data.shape(0),1).astype(int)
ones_data=np.ones(uk_data.shape(0),1).astype(int)
# 分别添加一列全为0,1的数组
us_data=np.hstack(us_data,zeros_data)
uk_data=np.hstack(uk_data,ones_data)
# 拼接两组数据
final_data = np.vstack((us_data,uk_data))
print(final_data)
(2) 其他方法
# 获取最大值最小值的位置
t=[[3,5,8,2],[6,3,8,9],[9,3,7,9],[3,7,4,9]]
np.argmax(t,axis=0) # 行
>>>array([2, 3, 0, 1], dtype=int64)
np.argmin(t,axis=1) # 列
>>>array([3, 1, 1, 0], dtype=int64)
# 创建1个全0的数组
np.zeros((3,4))
>>>array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
# 创建1个全1的数组
np.ones((3,4))
>>>array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
# 创建一个对角线为1的方阵
np.eye(3)
>>>array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
(3) 生成随机数
.rand(d0,d1,…dn): 创建d0-dn维度的均匀分布的随机数数据,范围0-1
.randn(d0,d1,…dn): 创建d0-dn维度的标准正态分布随机数,浮点数,平均数0,标准差1
.randint(low,hign,(shape)): 从给定上下限范围选取随机数整数,范围是low-high,形状shape
.uniform(low,hign,(size)): 产生具有均匀分布的数组,low是起始值,high结束值,size形状
.normal(loc,scale,(size)): 从指定正态分布中随机抽取样本,分布中心是loc(概率分布的均值),标准差是scale,形状是size
.seed(s): 随机数种子,s是给定的种子值。因为计算机生成的是伪随机数,所以通过设定相同的随机数种子,可以每次生成相同的随机数
均匀分布:在相同的大小范围内的出现概率是等可能的
正态分布:呈钟型,两头低,中间高,左右对称
np.random.randint(10,20,(4,5)) # 生成10-20的4行5列数组
>>>array([[17, 10, 15, 17, 11],
[19, 14, 10, 19, 14],
[16, 11, 12, 18, 14],
[12, 11, 17, 12, 16]])
np.random.randint(10,20,(4,5)) # 每次运算的结果不同
>>>array([[14, 12, 16, 13, 16],
[15, 16, 10, 19, 12],
[13, 15, 13, 17, 10],
[16, 13, 12, 18, 18]])
np.random.seed(10)
t=np.random.randint(0,20,(3,4)) #每次运算的结果相同
>>>array([[ 9, 4, 15, 0],
[17, 16, 17, 8],
[ 9, 0, 10, 8]])
(4) 注意点copy和view
a=b: 完全不复制,a和b相互影响
a=b[:]: 视图的操作,一种切片,会创建新的对象a,但a的数据完全由b保管,他们两个的数据变化是一致的
a=b.copy(): 复制,a和b互不影响
(1) nan和inf
nan(NAN,Nan): not a number表示不是一个数字
当读取本地文件为float的时候,如果有缺失,就会出现nan
当做了一个不合适的计算的时候(比如无穷大减去无穷大)
inf(-inf,inf): infinity, inf表示正无穷,-inf表示负无穷
比如一个数字除以0
# 1:nan和inf两者都是浮点类型
a=np.nan
b=np.inf
type(a)
>>>float
type(b)
>>>float
# 2:两个nan是不相等的
np.nan==np.nan
>>>False
# 3:np.nan!=np.nan
np.nan!=np.nan
>>>True
# 4:判断数组中nan的个数
t=np.array([1.,2.,np.nan])
>>>[1.0, 2.0, nan]
np.count_nonzero(t!=t)
>>>1
# 4:把nan替换为0,判断数组中nan的个数
t[np.isnan(t)]=0
np.count_nonzero(t==0)
>>>1
# 5:nan和任何职计算都为nan
t1=np.array([1.,2.,np.nan])
t2=np.arange(12).reshape(3,4)
np.sum(t1)
>>>nan
np.sum(t2)
>>>66
np.sum(t2,axis=0)
>>>array([12, 15, 18, 21])
np.sum(t2,axis=1)
>>>array([ 6, 22, 38])
(2) nan的注意点
解决nan的方式:把缺失的数值替换为均值(中值)或者直接删除有缺失值的一行
问题:
-如何计算一组数据的中值或者是均值
-如何删除有缺失数据的那一行(列)[pandas中详细介绍]
t1=np.array([1.,2.,np.nan],[3,4,5],[6,4,8])
>>>array([[ 1., 2., nan],
[ 3., 4., 5.],
[ 6., 4., 8.]])
t1.sum(axis=0) # 求和
>>>array([10., 10., nan])
t1.mean(axis=0) # 求均值
>>>array([3.33333333, 3.33333333, nan])
np.median(t1,axis=0) # 求中值
>>>array([ 3., 4., nan])
t1.max(axis=0) # 求最大值
>>>array([ 6., 4., nan])
t1.min(axis=0) # 求最小值
>>>array([ 1., 2., nan])
np.ptp(t1,axis=0) # 求极差
>>>array([ 5., 2., nan])
t1.std(axis=0) # 求标准差,反映数据的波动稳定情况
>>>array([2.05480467, 0.94280904, nan])
import numpy as np
t1=np.arange(12).reshape(3,4).astype('float')
t1[1,2:]=np.nan
>>>array([[ 0., 1., 2., 3.],
[ 4., 5., nan, nan],
[ 8., 9., 10., 11.]])
# 如何计算一组数据的中值或者是均值
def fill_ndarray(t1):
for i in range(t1.shape[1]): # 遍历每一列
temp_col=t1[:,i] # 当前的一列
nan_num=np.count_nonzero(temp_col!=temp_col)
if nan_num!=0: # 不为0,说明当前这一列中有nan
temp_not_nan_col=temp_col[temp_col==temp_col] # 当前一列不为nan的array
# 选中当前为nan的位置,把值赋值给不为nan的均值
temp_col[np.isnan(temp_col)]=temp_not_nan_col.mean()
return t1
if __name__=='__main__':
t1=np.arange(12).reshape(3,4).astype('float')
t1[1,2:]=np.nan
print(t1)
t1=fill_ndarray(t1)
print(t1)
>>>[[ 0. 1. 2. 3.]
[ 4. 5. nan nan]
[ 8. 9. 10. 11.]]
[[ 0. 1. 2. 3.]
[ 4. 5. 6. 7.]
[ 8. 9. 10. 11.]]
问题:英国和美国各自YouTube1000的数据结合之前的matplotlib绘制出各自的评论数量的直方图
希望了解英国的YouTube中视频的评论数和喜欢数的关系,应该如何绘制该图(散点图)
import numpy as np
from matplotlib import pyplot as plt
us_data='USvideos.csv'
uk_data='GBvideos.csv'
# 加载国家数据
t_us=np.loadtxt(us_data,delimiter=',',dtype=int)
t_uk=np.loadtxt(uk_data,delimiter=',',dtype=int)
# 问题:英国和美国各自YouTube1000的数据结合之前的matplotlib绘制出各自的评论数量的直方图
# 评论的数据
t_us_comments=t_us[:,-1]
# 选择比5000小的数据
t_us_comments=t_us_comments[t_us_comments<=5000]
d=250
bin_nums=(t_us_comments.max()-t_us_comments.min())//d
# 绘图
plt.figure(figsize=(20,8),dpi=80)
plt.hist(t_us_comments,bin_nums)
plt.show()
import numpy as np
from matplotlib import pyplot as plt
uk_data='GBvideos.csv'
# 加载国家数据
t_uk=np.loadtxt(uk_data,delimiter=',',dtype=int)
# 问题:英国的YouTube中视频的评论数和喜欢数的关系,应该如何绘制该图——散点图
# 选择喜欢比500000小的数据
t_uk=t_uk[t_uk[:,1]<=500000]
t_uk_comments=t_uk[:,-1]
t_uk_like=t_uk[:,1]
# 绘图
plt.figure(figsize=(20,8),dpi=80)
plt.scatter(t_uk_like,t_uk_comments)
plt.show()