数据分析之numpy模块的基本使用

Numpy (Numerical Python):

1. Numpy:提供了一个在Python中做科学计算的基础库,重在数值计算,
主要用于多维数组(矩阵)处理的库.用来存储和处理大型矩阵,比Python
自身的嵌套列表结构要高效的多.本身是由C语言开发,是个很基础的扩展,
Python其余的科学计算扩展大部分都是以此为基础.

2. 高性能科学计算和数据分析的基础包

3. ndarray,多维数组(矩阵),具有矢量运算能力,快速、节省空间

4. 矩阵运算,无需循环,可完成类似Matlab中的矢量运算

5. 线性代数、随机数生成

6. import numpy as np

numpy中的一些常见方法:

1. np.array(collection):

    collection 为 序列型对象(list)、嵌套序列对象(list of list).

2. np.zeros():

    指定大小的全0数组.注意:第一个参数是元组,用来指定大小,如(3, 4).

3. np.ones():

    指定大小的全1数组.注意:第一个参数是元组,用来指定大小,如(3, 4).

4. np.empty():

    初始化数组,不是总是返回全0,有时返回的是未初始的随机值(内存里的随机值).

5. np.arange() 和 reshape():

    arange() 类似 python 的 range() ,创建一个一维 ndarray 数组.
    
    reshape() 将 重新调整数组的维数.

6. np.arange() 和 random.shuffle():

    random.shuffle() 将打乱数组序列(类似于洗牌).

ndarray的数据类型:

1. dtype参数:

    指定数组的数据类型,类型名+位数,如float64, int32

2. astype方法:

    转换数组的数据类型

numpy中常见的更多数据类型:

类型             类型代码                说明
int8,uint8      i1,u1        有符号和无符号的8位(1个字节)整型
int16,uint16    i2,u2        有符号和无符号的16位(2个字节)整型
int32,uint32    i4,u4        有符号和无符号的32位(4个字节)整型.
int64,uint64    i8,u8        有符号和无符号的64位(8个字节)整型
float16         f2           半精度浮点数
float32         f4或f        准的单精度浮点数.与C的float兼容
float64         f8或d        标准的双精度浮点数.与C的double和Python
                             的float对象兼容
float128        f16或g       扩展精度浮点数
complex64,      c8,          分别用两个32位、
complex128      c16          64位或
complex256      c32          128位浮点数表示的复数
bool             ?           存储True和False值的布尔类型

numpy的基本使用:

import numpy as np
import random

t1 = np.array([1,2,3])
print(t1) # [1 2 3]

t2 = np.array(range(1,10))
print(t2) # [1 2 3 ...]
print(type(t2)) # <class 'numpy.ndarray'>

t3 = np.arange(1,10,2)
print(t3) # [1 3 5 7 9]

print(t3.dtype)  # int64

t4 = np.array(range(1,4),dtype="i1")
print(t4)
print(t4.dtype) # int8


# numpy中的bool类型

t5 = np.array([1,0,1,1,1,0],dtype=bool)
print(t5)
print(t5.dtype)  # bool

# 类型转换
t6 = t5.astype("int8")
print(t6)
print(t6.dtype)  # int8

# numpy中的小数
t7 = np.array([random.random() for i in range(10)])
print(t7)
print(t7.dtype) # float64

# 精确到小数点后两位
t8 = np.round(t7,2)
print(t8)

数组的形状:

查看数组的形状:
In [62]: a. shape
0ut[62]: (2,6)

修改数组的形状:
In [63]: a.reshape(3,4)
Out[63] :
array([[3, 4, 5,6],
[7,8,4,5],
[6,7,8,9]])

In [64]: a.shape
Out[64]: (2,6)一->为什么a还是2行6列的数组呢?

原来reshape()返回的是修改后的数组,而不会修改原数组

维度之间的转换的demo:

import numpy as np

a1 = np.array([1,2,3,4,5,6,7,8,9,10,11,12])
# 查看数组的形状
print(a1.shape) # (12,)

a2 = np.array([[1,3,4],[1,1,1]])
print(a2)
print(a2.shape) # (2,3)

# 修改数组的形状并返回
a3 = a1.reshape(3,4)
print(a3) # [[1 2 3 4] [5 6 7 8] [9 10 11 12]]
print(a3.shape) # (3,4)

a4 = a3.reshape(1,12)
a5 = a3.reshape(12,)
print(a4) # [[1 2 3 ...]]  二维
print(a5) # [1 2 3 ...]   一维

# 将多维数组转换成一维数组
a6 = a3.flatten()
print(a6) # [1 2 3 ...]

a7 = a1.reshape(2,6)
print(a7) # [[1 2 3 ..] [7 8 9 ..]]

数组的加减乘除运算:

import numpy as np

a8 = np.arange(0,6)
print(a8) # [0 1 2 3 ..]

# 加减乘除数字将应用到数组的每一个元素
print(a7*2) # [[2 4 6 ..] [14 16 18 ...]]

# a7的每一行都减了一个a8
print(a7-a8) # [[1 1 1 ...] [7 7 7 ..]]

a9 = a3  # [[1 2 3 4] [5 6 7 8] [9 10 11 12]]
# print(a7-a9) #报错 not be broadcast together with shapes (2,6) (3,4)

a10 = np.array([1,2,3]) # [1 2 3]
a11 = a10.reshape(3,1)
print(a11)  # [[1] [2] [3]]

a12 = a1.reshape(3,4)
print(a12) # [[1 2 3 4] [5 6 7 8] [9 10 11 12]]

# a12的每一列减去a11(列数相同)
print(a12-a11) # [[0 1 2 3] [3 4 5 6] [6 7 8 9]]

a13 = np.arange(27).reshape(3,3,3)
print(a13) # [[[0 1 2] [3 4 5] ... ] [[9 10 11] [12 ..]] [[18..] [21..] ..]]

a14 = np.arange(6).reshape(3,2)
print(a14) # [[0 1] [2 3] [4 5]]

# print(a13 - a14) # 报错

a15 = np.arange(24).reshape(4,3,2)
print(a15) # [[[0 1] [2 3] [4 5]] [[6 7][8 9][10 11]] [[12 13][14 15][16 17]] [[18 19] [20 21][22 23]]]

# a15每一块的二维数组都减去a14
print(a15 - a14)

广播原则:

如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长
度相符或其中一方的长度为1,则认为它们是广播兼容的.广播会在缺失和(或)
长度为1的维度上进行.

轴(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,2×5一共10个数据

二维数组的轴:

在这里插入图片描述

三维数组的轴:

在这里插入图片描述

明白了轴的概念之后,对于shape返回的结果和reshape的结果能够更加清楚

numpy读取数据:

CSV:Comma-Separated Value,逗号分隔值文件
显示:表格状态
源文件:换行和逗号分隔行列的格式化文本,每一行的数据表示一条记录

由于csv便于展示,读取和写入,所以很多地方也是用csv的格式存储和传输中小型的数据,
为了方便教学,我们会经常操作csv格式的文件,但是操作数据库中的数据也是很容易的实现的


np.loadtxt(fname,dtype=np.float,delimiter=None,skiprows=0,
            usecols=None,unpack=False)

参数              解释
frame       文件、字符串或产生器,可以是.gz或bz2压缩文件
dtype       数据类型,可选,CSV的字符串以什么数据类型读入数组中,默认np.float
delimiter   分隔字符串,默认是任何空格,改为逗号
skiprows    跳过前x行,一般跳过第一行表头
usecols     读取指定的列,索引,元组类型
unpack      如果True,读入属性将分别写入不同数组变量,
            False 读入数据只写入一个数组变量,默认False

np.loadtxt(US_video_data_numbers_path,delimiter=",",dtype=int,unpack=1)

注意其中添加delimiter和dtype以及unpack的效果

delimiter: 指定边界符号是什么,不指定会导致每行数据为一个整体的字符串而报错
dtype: 默认情况下对于较大的数据会将其变为科学计数的方式

那么unpack的效果呢?
upack: 默认是Flase(0),默认情况下,有多少条数据,就会有多少行.
为True(1)的情况下,每一列的数据 会组成一行,原始数据有多少列,
加载出来的数据就会有多少行,相当于转置的效果.

文件的读取,转置,索引及取行列:

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,delimiter=",",dtype="int")
# unpack转置
t2 = np.loadtxt(us_file_path,delimiter=",",dtype="int",unpack=True)

print(t1)
print(t2)
# 由transpose方法得到转置
print(t1.transpose())
# 根据T属性得到的转置
print(t1.T)
# 交换0,1轴
print(t1.swapaxes(1,0))

print("-"*20)

# 取行(第三行)
print(t1[2])

# 取连续的多行(第三行及以后)
print(t1[2:])

# 取不连续的多行(第3,9,11行)
print(t1[[2,8,10]])

# 通用方法取行(逗号前面代表行,逗号后面代表列)
print(t1[1,:]) # 行(第二行),列(全部列)
print(t1[2:,:]) # 行(第三行及以后),列(全部列)
print(t1[[2,3,5],:]) # 行(第三四六行),列(全部列)

# 通用法取列
print(t1[:,0]) # 行(全部行),列(第1列)

# 取连续的多列
print(t1[:,2:]) # 行(全部行),列(第三列及以后)

# 取不连续的多列
print(t1[:,[0,2]]) # 行(全部行),列(第1,3行)

# 取多行和多列,取第三行,第四列的值
a = t1[2,3]
print(a)

# 取多行和多列,取第三行到第五行,第二列到第四列的结果
b = t1[2:5,1:4] # 取的是行和列的交叉点的位置
print(b)

# 取多个不相邻的点
# 取出来的结果是(0,1),(3,2),(4,1)
c = t1[[0,3,4],[1,2,1]]
print(c)

numpy中数值的修改:

In [4]: t
0ut[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]])

In [6]: t[:,2:4]
0ut[6]:
    array([[2, 3],
           [8, 9],
           [14, 15],
           [20, 21]])

In [7]: t[:,2:4] = 0
In [8]: t
0ut[8]:
    array([[0, 1, 0, 0, 4, 5],
           [6, 7, 0, 0, 10, 11],
           [12, 13,0, 0, 16, 17],
           [18, 19, 0, 0, 22, 23]])


修改行列的值,我们能够很容易的实现,但是如果条件更复杂呢?
比如我们想要把t中小于10的数字替换为3

In [14]: t = np.arange(24).reshape((4,6))

In [15]: t<10
0ut[15]:
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]]

In [16]: t[t<10]=0

In [17]: t
0ut[17]:
array([[ 0,0,0,0,0,0],
       [0,0,0,0,10,11],
       [12,13,14,15,16,17],
       [18,19, 20,21,22,23]])


如果我们想把t中小于10的数字替换为0,把大于10的替换为10,应该怎么做??

numpy中三元运算符:

In [19]: t = np.arange(24).reshape((4,6))

In [20]: t
0ut[20]:

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]])

In [22]: np.where(t<10,0,10)  # numpy的三元运算符
Out [22]:
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]])

numpy中的clip(裁剪):

t = t.astype(float)

In [50]: t
0ut[50]:
array([[0.,1.,2.,3.,4.,5.],
       [6.,7.,8.,9.,10.,11.],
       [12.,13.,14.,15.,16.,17.],
       [18.,19.,20.,nan,nan,nan]])

In [52]: t.clip(10,18)
0ut[52]:
array([[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中的nan和inf:

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)


In [71]: a = np.inf

In [73]: type(a)
0ut[73]: float

In [74]: a = np.nan

In [75]: type(a)
Out[75]: float

numpy中的nan的注意点:

在这里插入图片描述

那么,在一组数据中单纯的把nan替换为0,合适么?会带来什么样的影响?

比如,全部替换为0后,替换之前的平均值如果大于0,替换之后的均值肯定会变小,
所以更一般的方式是把缺失的数值替换为均值(中值)或者是直接删除有缺失值的一行.

numpy中常用统计函数:

求和:t.sum(axis=None)
均值:t.mean(a,axis=None)  受离群点的影响较大
中值:np.median(t,axis=None) 
最大值:t.max(axis=None) 
最小值:t.min(axis=None)
极值:np.ptp(t,axis=None) 即最大值和最小值只差
标准差:t.std(axis=None) 

t.sum(axis=0)  # 求每一列的和
Out[31]: array([36., 40., 44., 48., nan, 56.])
In [32]: t.sum(axis=1) # 求每一列的和
Out[32]: array([15., 51., 87., nan])

默认返回多维数组的全部的统计结果,如果指定axis则返回一个当前轴上的结果

标准差:

标准差是一组数据平均值分散程度的一种度量.一个较大的标准差,代表大部分数值和
其平均值之间差异较大;一个较小的标准差,代表这些数值较接近平均值,反映出数据
的波动稳定情况,越大表示波动越大,约不稳定

在这里插入图片描述

元素计算函数:

1) ceil(): 向上最接近的整数,参数是 number 或 array
2) floor(): 向下最接近的整数,参数是 number 或 array
3) rint(): 四舍五入,参数是 number 或 array
4) isnan(): 判断元素是否为 NaN(Not a Number),参数是 number 或 array
5) multiply(): 元素相乘,参数是 number 或 array
6) divide(): 元素相除,参数是 number 或 array
7) abs():元素的绝对值,参数是 number 或 array
8) where(condition, x, y): 三元运算符,x if condition else y

9) randn() 返回具有标准正态分布的序列.

arr = np.random.randn(2,3)

# print(arr)
[[-0.75803752  0.0314314   1.15323032]
 [ 1.17567832  0.43641395  0.26288021]]

元素统计函数:

1) np.mean(), np.sum():所有元素的平均值,所有元素的和,参数是 number 或 array
2) np.max(), np.min():所有元素的最大值,所有元素的最小值,参数是 number 或 array
3) np.std(), np.var():所有元素的标准差,所有元素的方差,参数是 number 或 array
4) np.argmax(), np.argmin():最大值的下标索引值,最小值的下标索引值,参数是 
                          number 或 array
5) np.cumsum(), np.cumprod():返回一个一维数组,每个元素都是之前所有元素的累加和
                          和累乘积,参数是 number 或 array
6) 多维数组默认统计全部维度,axis参数可以按指定轴心统计,值为0则按列统计,值为1则按行统计.

猜你喜欢

转载自blog.csdn.net/qq_46456049/article/details/108909596