Python数据清洗{Numpy}

2021/7/15 22:07:25

本文主要是介绍Python数据清洗{Numpy},对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Numpy

  • ndarray
    • 构建ndarray
    • 数据类型
  • ndarray 与 python 原生 array 有什么区别
    • Numpy 的矢量化(向量化)功能
      • 小练习
  • 创建常用的数组
    • 创建一个全0数组
    • 全1数组
    • 单位矩阵
    • 对角矩阵
    • 设定具体的值
    • 设置空值和无穷大
    • 随机数组
      • 正态分布随机数
      • 其他分布
      • 设置随机数种子
      • 创建一个线性序列的数组
    • 小练习
  • ndarray常用属性
  • 数组的索引和切片
    • 单个元素索引
    • 高维数组索引
    • 修改某一个元素值
    • 试图
      • 浅复制
      • 改为创建副本(深复制)
    • 小练习:
  • 数组的变形
    • 改变数组的形状
    • 拉伸成一维数组(数组的平铺)
    • 转置
    • 数组的拼接
    • 数据的分裂
    • 小练习
  • 广播机制
  • Numpy运算
    • 基本运算操作
    • 常用函数
    • 规约函数
    • 小练习

 Numpy (Pandas是基于Numpy的,所有在学习Pandas之前,需要先学习Numpy)
 Pandas (数据的清洗,数据统计,数据的整合,… 类似于Excel)
 Matplotlib,(基于Numpy的数据类型,画图的工具包)

  NumPy(Numerical Python)是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多(该结构也可以用来表示矩阵(matrix)),支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库

 借此,我们可以总结以下, NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。

ndarray

  Numpy 的核心是 ndarray 对象,这个对象封装了同质数据类型的n维数组。ndarray中的每个元素在内存中使用相同大小的块。 ndarray中的每个元素是数据类型对象的对象(称为 dtype)。

构建ndarray

# 先导包
import numpy as np

np.array(object, dtype=None)

  • object:转换的数据
  • dtype : 数据类型

 np.array() 就相当于我们学习过的list,int,str等等,将其他的数据类型转换为 数组

# 和我们之前学习 list  dict tuple 一个意思
# 将其他数据类型转换为 ndarray
L = [1,2,3]
t = (6,5,4)
n1 = np.array(L)
print(n1)
# 返回结果:array([1, 2, 3])
type(n1)
# 返回结果:numpy.ndarray

# 再比如说,定义一个二维列表
L2 = [[2, 3], [4, 6, 8], [3, 5, 66]]
print(L2)
# 返回结果:[[2, 3], [4, 6, 8], [3, 5, 66]]

ar2 = np.array(L2)
print(ar2)
# 返回结果:[[ 2  3  5]
#           [ 4  6  8]
#           [ 3  5 66]]

数据类型

  Numpy 中的数组比 Python 原生中的数组(只支持整数类型与浮点类型)强大的一点就是它支持更多的数据类型。

Numpy 常见的基本数据类型如下:

数据类型描述
bool_布尔(True或False),存储为一个字节
int_默认整数类型(与C long相同;通常为int64或int32)
intc与C int(通常为int32或int64)相同
intp用于索引的整数(与C ssize_t相同;通常为int32或int64)
int8字节(-128到127)
int16整数(-32768到32767)
int32整数(-2147483648至2147483647)
int64整数(-9223372036854775808至9223372036854775807)
uint8无符号整数(0到255)
uint16无符号整数(0到65535)
uint32无符号整数(0至4294967295)
uint64无符号整数(0至18446744073709551615)
float_float64的简写。
float16半精度浮点:符号位,5位指数,10位尾数
float32单精度浮点:符号位,8位指数,23位尾数
float64双精度浮点:符号位,11位指数,52位尾数
objectPython对象,放什么都可以

  重点: 请记住,不同于 Python 列表,NumPy 要求数组必须包含同一类型的数据。如果类型不匹配,NumPy 将会向上转换(如果可行)。就比如说:

import numpy as np
L  = [3,5,4.3]
 n = np.array(L)
 print(n)
 # 返回结果:[3.  5.  4.3]

L2 = [3,4.3, 'ab']
s = np.array(L2)
print(s)
# 返回结果:['3' '4.3' 'ab']

 整数类型 向上转换为 浮点类型,浮点类型转换为 字符串类型

指定数据类型

  要转换数组的类型,请使用类型本身作为函数或者.astype()方法(首选)

import numpy as np
L  = [3,5,4.3]
a = np.array(L, dtype = 'int64')
# 对于mac, 整数型默认就是 64位, 但是对于 windows ,应该是32位
L2 = [3, 3.3 , '3.56']
b = np.array(L2, dtype='float')
b = np.array(L2, dtype='float')
print(b)
# 运行结果:[3.   3.3  3.56]
# 查看一个数组的数据类型
print(b.dtype)
# 运行结果:float64

  **转换数据类型的方法: 用astype **

# 改变已经生成的ndarray的数据类型
q = b.astype('str')
print(q)
# 运行结果:['3.0' '3.3' '3.56']
e = b.astype('bool')
print(e)
# 运行结果:[ True  True  True]

print(e.dtype)
# 运行结果:bool

ndarray 与 python 原生 array 有什么区别

  NumPy 数组在创建时有固定的大小,但是运行速度快,不同于Python列表(可以动态增长)。可是速度慢,更改ndarray的大小将创建一个新的数组并删除原始数据。

  NumPy 数组中的元素都需要具有相同的数据类型,因此在存储器中将具有相同的大小。数组的元素如果也是数组(可以是 Python 的原生 array,也可以是 ndarray)的情况下,则构成了多维数组。

  NumPy 数组便于对大量数据进行高级数学和其他类型的操作。通常,这样的操作比使用Python的内置序列可能更有效和更少的代码执行。

  越来越多的科学和数学的基于Python的包使用NumPy数组,所以需要学会 Numpy 的使用。

Numpy 的矢量化(向量化)功能

 矢量化的意思就是,在一个二维空间内,一个数既有大小,也有方向

  比如说:如果想要将一个2-D数组 a 的每个元素与长度相同的另外一个数组 b 中相应位置的元素相加,使用 Python 原生的数组实现如下:

a = [[1, 2, 3], [5, 7, 8], [4, 5, 6]]
b = [[6, 2, 1], [2, 3, 1], [4, 5, 6]]
# 我们现根据列表的形状,创建一个空数组用于接收结果
c = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
# 两层循环,对二维数据进行遍历
for i in range(3):
    for j in range(3):
        c[i][j] = a[i][j]+ b[i][j]
print(c)
# 运行结果:[[7, 4, 4], [7, 10, 9], [8, 10, 12]]

  不难发现,利用python原生数组进行矩阵运算,其实是很不友好的。那么我们利用numpy来实现功能呢

a = [[1, 2, 3], [5, 7, 8], [4, 5, 6]]
b = [[6, 2, 1], [2, 3, 1], [4, 5, 6]]
# 将两个二维列表转换成 ndarray
a1 = np.array(a)
b1 = np.array(b)
# 直接相加,就是对应元素位置相加
t = a1 + b1
print(t)
# 运行结果:[[ 7  4  4]
#           [ 7 10  9]
 #          [ 8 10 12]]
#  加减乘除 也可以直接进行运算
a1 * 3
a1 ** 2
np.sqrt(a1)
a1 - b1
a1 * b1

矢量化代码有很多优点,其中包括:

  • 矢量化代码更简洁易读
  • 更少的代码行通常意味着更少的错误
  • 该代码更接近地类似于标准数学符号(使得更容易,通常,以正确地编码数学构造)
  • 矢量化导致更多的“Pythonic”代码。如果没有向量化,我们的代码将会效率很低,难以读取for循环。

小练习

  一家连锁店,

  A门店最近5天的营业额数据为:1200,1398,2200,1100,1521

  B门店5天营业额为: 1340,1211,1460,1121,1609

  • 计算连锁店每天的总收入
  • 计算连锁店5天的总收入
  • 计算A店和B店的销售额的对数差
  • (不做)计算A店和B店每天销售量更高的是哪个店?
import numpy as np
A = np.array([1200,1398,2200,1100,1521])
B = np.array([1340,1211,1460,1121,1609])
every_day = A+ B
print(every_day)
every_day_in = np.sum(every_day)
print(every_day_in)
five_day = every_day_in * 5
print(five_day)
ld = np.log(A) - np.log(B)
print(ld)

'''运行结果:[2540 2609 3660 2221 3130]
14160
70800
[-0.11034806  0.14359618  0.41002092 -0.01891096 -0.05624485] '''

创建常用的数组

  单位矩阵,全零矩阵,三角矩阵等常用的矩阵数组,在线性代数的辅助计算中有很多特殊的作用

题外话:我们都知道在python中,会自动只输出一行代码。

a = 1
b = 2
a
b
# python内只会输出b的结果
#全部行都能输出
rom IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
a = 1
b = 2
a
b
# 这样python就会自动全部输出结果

创建一个全0数组

  numpy.zeros(shape,dype)

  • shape:形状 ,数组的形状
  • dtype:默认为float
import numpy as np
one = np.zeros(5)
print(one)
# 运行结果:[0. 0. 0. 0. 0.]
two=np.zeros( (3,2) )
print(two)
'''
[[0. 0.]
 [0. 0.]
 [0. 0.]]
'''
 q= np.zeros((4,3), dtype= 'int')
print(q)
'''
[[0 0 0]
 [0 0 0]
 [0 0 0]
 [0 0 0]]
'''

# 三维数组
# 三维数组
w = np.zeros((4,3,2), dtype= 'int')
print(w)
# 4 代表有几个二维平面构成三维体
# 3 每一个二维元素里面都是由三个一维元素构成的
# 2 每一个一维元素里面都是由2个0维元素构成的
'''
[[[0 0]
  [0 0]
  [0 0]]

 [[0 0]
  [0 0]
  [0 0]]

 [[0 0]
  [0 0]
  [0 0]]

 [[0 0]
  [0 0]
  [0 0]]]
'''

全1数组

  numpy.ones(shape,dype)

  • shape:形状 ,数组的形状
  • dtype:默认为float
import numpy as np
o = np.ones([4,3])
print(o)
'''
[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]
'''

  跟零矩阵是一样的操作

单位矩阵

  numpy.eye()

import numpy as np
e = np.eye(3)
print(e)
###
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
###
two = np.eye(5,6)
print(two)
###
[[1. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 0. 1. 0.]]
###
# 向上偏移一行
# 向上偏移一行
move = np.eye(5, k = 1)
print(move)
'''
[[0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0.]
 [0. 0. 0. 1. 0.]
 [0. 0. 0. 0. 1.]
 [0. 0. 0. 0. 0.]]
 
'''
# 向下偏移1行
move1 = np.eye(5, k = -1)
print(move1)
'''
[[0. 0. 0. 0. 0.]
 [1. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0.]
 [0. 0. 0. 1. 0.]]
'''

对角矩阵

  numpy.eye()

import numpy as np
Diagonally = np.diag([1,2,3,4,5,6])
print(Diagonally)
'''
[[1 0 0 0 0 0]
 [0 2 0 0 0 0]
 [0 0 3 0 0 0]
 [0 0 0 4 0 0]
 [0 0 0 0 5 0]
 [0 0 0 0 0 6]]
'''
# 行列增加
Diagonally1 = np.diag([1,2,3,4,5,6], k = 1)
print(Diagonally1)
'''
[[0 1 0 0 0 0 0]
 [0 0 2 0 0 0 0]
 [0 0 0 3 0 0 0]
 [0 0 0 0 4 0 0]
 [0 0 0 0 0 5 0]
 [0 0 0 0 0 0 6]
 [0 0 0 0 0 0 0]]
'''

设定具体的值

  numpy.full()

import numpy as np
q = np.full((4,3),666)
print(q)
'''
[[666 666 666]
 [666 666 666]
 [666 666 666]
 [666 666 666]]
'''

设置空值和无穷大

  有一点要尤其注意的是: numpy.nan, numpy.inf 都是浮点类型

  结合ndarray中的数据类型必须是相同的, 也就是说数组中如何有一个数据是空值,那么所有的数据都只能是浮点型。

import numpy as 
w = np.nan
print(w)
# 返回结果:nan
type(np.nan)
# 返回结果:float
# 如果数据中存在空值, 数据就是浮点型,不可能是整数型
i= np.inf
print(i)
# infinity 无穷大
# 返回结果:inf
type(np.inf)
# 返回结果:float

随机数组

  np.random()

import numpy as np
# size 和 shape一样, 就是形状,尺寸
h = np.random.randint(1,6,10) # 长度为10的一维数组
# 左闭右开区间
print(h)
# 返回结果:[4 3 5 2 4 4 2 3 5 1]
q = np.random.randint(1,6 , (3,4))
print(q)
'''
[[4 5 4 5]
 [4 4 1 1]
 [2 5 5 2]]
'''
import numpy as np
# 随机生成0-1之间的数字
ra = np.random.rand(10)
print(ra)
'''
[0.84171009 0.85636045 0.8905441  0.23906423 0.42791151 0.56882182
 0.26359657 0.69386248 0.09191729 0.98636627
'''
# 多个维度之间拆开写 0 -1
ran = np.random.rand(5,3)
print(ran)
'''
[[0.97420233 0.41148089 0.70975894]
 [0.6028417  0.11372723 0.8379255 ]
 [0.34791909 0.04173681 0.30917491]
 [0.19008997 0.10268902 0.02075769]
 [0.6486511  0.31757476 0.13535186]]
'''
# 和上面功能一样,但是参数不一样
rand = np.random.random((5,3))
print(rand)
'''
[[0.52599    0.88353775 0.84403343]
 [0.60142764 0.15824687 0.93008467]
 [0.20842113 0.33478552 0.79234547]
 [0.12549817 0.07206635 0.37206859]
 [0.3806428  0.43446087 0.56571947]]
'''
# 生成5 - 12 的一个随机序列:
# 首先将数据范围放大7倍, 然后向右平移5个单位
five_t = 7 * np.random.rand(5,3) + 5
print(five_t)
'''
[[10.90013123  5.27235512 11.03726568]
 [10.43590827  9.30266497  6.76956598]
 [11.36498775  8.84371072 11.36716209]
 [10.83695495  5.67246135  7.26543115]
 [ 8.6264895  11.09727019  6.30073484]]
'''
# 四舍五入到小数点后三位
ro = np.round(np.random.random((5,3)) , 3)
print(ro)
'''
[[0.058 0.182 0.168]
 [0.669 0.867 0.894]
 [0.813 0.586 0.902]
 [0.377 0.419 0.181]
 [0.591 0.22  0.912]]
'''

正态分布随机数

  • 标准正太分布( 均值0 标准差 1)numpy.random.randn()
import numpy as np
n = np.random.randn(4,3)
print(n)
'''
[[-0.60039108  0.60695807  0.98537722]
 [ 0.22204292 -2.22908403  0.39136029]
 [ 0.40227228 -0.37893229  0.56100572]
 [ 0.32395202 -1.48245164 -0.88986908]]
'''

  • 普通(高斯)正太分布np.random.normal( )
import numpy as np
# 均值为 5 , 标准差为3的正太分布
no = np.random.normal(5, 3, (3,4) )
print(no)
'''
[[ 5.09286106 -2.58247812  5.98901183  6.67594294]
 [ 6.51064572  4.20856988  4.23869969 -0.17317082]
 [ 1.20556585  6.41977055  5.9373478   2.1096022 ]]
'''

其他分布

impot numpy as np
# 卡方分布, 自由度5 
kabu = np.random.chisquare(5, (3,4))
print(kabu)
'''
[[ 4.18942868  1.90641354  6.8380711   7.72245033]
 [ 5.51199253  3.42581178  2.28299058 11.66515143]
 [ 3.85891538  6.3625525  10.44246889  8.84006505]]
'''
# t分布, 自由度3
t = np.random.standard_t(3, (3,4))
print(t)
'''
[[-2.06425897  1.58271619  0.33490957  0.67021206]
 [-2.83444201 -0.08385209  2.55842596 -2.02025833]
 [-3.11440855  0.79975362 -0.3667405   0.8412603 ]]
'''
# f分布
f = np.random.f(2,3,(3,4))
print(f)
'''
[[ 2.03140767  4.70292481 13.53592584  0.15130837]
 [ 0.57659996  0.3500495   1.40457076  0.48514243]
 [ 0.35982489  0.02199006  2.18912438  0.51371845]]
'''
# 泊松分布
bosong = np.random.poisson(0.5, (3,4))
print(bosong)
'''
[[3 0 2 0]
 [0 0 0 1]
 [2 2 1 0]]
'''
# 二项分布
erxiang = np.random.binomial(10, 0.5, (3,4))
print(bosong)
'''
[[3 0 2 0]
 [0 0 0 1]
 [2 2 1 0]]
'''

设置随机数种子

import numpy as np
np.random.seed(666)
# 这个种子运行了之后, 马上运行的下一个随机数就是使用这个种子
np.random.randint(10)

创建一个线性序列的数组

  numpy.arange([start,] stop[, step,])

  • 如果只填一个 stop参数, 默认从0开始 ,步长是1
  • 如果有两个参数,设定第一个参数为起始,第二个为末尾,左闭右开,默认步长为1
  • 如果有三个参数,设定第一个参数为起始,第二个为末尾,左闭右开,第三个参数为步长

  特点: 可以设置开始位置,终止位置和步长,但产生数字的数量不方便控制

import numpy as np
s = np.arange(10)
# 如果只填一个 stop参数, 默认从0开始 ,步长是1
print(s)
# [0 1 2 3 4 5 6 7 8 9]
two = np.arange(10,18)
print(two)
# [10 11 12 13 14 15 16 17]
two = np.arange(10,18)
print(two)
# [0 1 2 3 4 5 6 7 8 9]
three = np.arange(1,20,3)
print(three)
## [ 1  4  7 10 13 16 19]


# 步长为负的
back = np.arange(10, 2, -1)
print(back)
# [10  9  8  7  6  5  4  3]


# 可以是小数
xiaoshu = np.arange(0.1, 1, 0.1)
print(xiaoshu)
# [0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]

  numpy.linspace(开始位置, 终止位置, 产生数量)

  特点: 可以设置开始位置和终止位置以及产生数量,但不方便控制步长

import numpy as np
# 想要生成 1 - 20 为区间的 38个数
te = np.linspace(1,20 , 38)
print(te)
'''
[ 1.          1.51351351  2.02702703  2.54054054  3.05405405  3.56756757
  4.08108108  4.59459459  5.10810811  5.62162162  6.13513514  6.64864865
  7.16216216  7.67567568  8.18918919  8.7027027   9.21621622  9.72972973
 10.24324324 10.75675676 11.27027027 11.78378378 12.2972973  12.81081081
 13.32432432 13.83783784 14.35135135 14.86486486 15.37837838 15.89189189
 16.40540541 16.91891892 17.43243243 17.94594595 18.45945946 18.97297297
 19.48648649 20.        ]
'''
rightopen = np.linspace(1,20 , 38,endpoint=False)
# 左闭右开
print(rightopen)
'''
[ 1.   1.5  2.   2.5  3.   3.5  4.   4.5  5.   5.5  6.   6.5  7.   7.5
 1.   8.5  9.   9.5 10.  10.5 11.  11.5 12.  12.5 13.  13.5 14.  14.5
 2.  15.5 16.  16.5 17.  17.5 18.  18.5 19.  19.5]
'''
buchang = np.linspace(1,20 , 38,retstep=True)
# retstep 步长也返回回来
print(buchang)
'''
(array([ 1.        ,  1.51351351,  2.02702703,  2.54054054,  3.05405405,
        3.56756757,  4.08108108,  4.59459459,  5.10810811,  5.62162162,
        6.13513514,  6.64864865,  7.16216216,  7.67567568,  8.18918919,
        8.7027027 ,  9.21621622,  9.72972973, 10.24324324, 10.75675676,
       11.27027027, 11.78378378, 12.2972973 , 12.81081081, 13.32432432,
       13.83783784, 14.35135135, 14.86486486, 15.37837838, 15.89189189,
       16.40540541, 16.91891892, 17.43243243, 17.94594595, 18.45945946,
       18.97297297, 19.48648649, 20.        ]), 0.5135135135135135)
'''

小练习

  1. 生成一个6行6列的单位矩阵数组,数据类型为字符串
  2. 生成一个(2,3,4)的数组,并使用无穷大进行填充
  3. 生成5,15的随机整数数组,形状为(3,6)
  4. 生成3行4列的标准正态分布数组
  5. 生成均值为10,标准差为5的(7,3)的正太分布
  6. 生成从12到22,步长为2的序列
  7. 生成从12到22的序列,序列的长度为100个
import numpy 
six_six = numpy.eye(6,dtype='str')
print(six_six)
infull = numpy.full((2,3,4),numpy.inf)
print(infull)
rand = numpy.random.randint(5,15,(3,6))
print(rand)
biaozhun = numpy.random.randn(3,4)
print(biaozhun)
zhengchang = numpy.random.normal(10,5,(7,3))
buchang_2 = numpy.arange(12,22,2)
print(buchang_2)
changdu_100 = numpy.linspace(12,22,100)
print(changdu_100)

ndarray常用属性

  • 查看数组形状shape()
  • 查看数组维度ndim()
  • 查看数组元素个size()
  • 查看数组的数据类型dtype()
import numpy as np
x1 = np.random.randint(10, size=6) # 一维数组
x2 = np.random.randint(10, size=(3, 4)) # 二维数组
x3 = np.random.randint(10, size=(3, 4, 5)) # 三维数组

# 查看数组形状
print(x1.shape)

# 查看数组维度
print(x2.nidm)

# 查看数组元素个数
print(x3.size)

# 查看数组的数据类型
print(x1.dtype)

数组的索引和切片

  Python 中原生的数组就支持使用方括号([])进行索引和切片操作,Numpy 也同样具有这个强大的特性。

单个元素索引

  1-D数组的单元素索引是人们期望的。它的工作原理与其他标准Python序列一样。它是从0开始的,并且接受负索引来从数组的结尾进行索引。

import numpy as np
x = np.arange(10)
print(x)
print(x[2:5])
print(x[-1])
print(x[::2])
'''
[0 1 2 3 4 5 6 7 8 9]
[2 3 4]
9
[0 2 4 6 8]
'''

高维数组索引

  与Python原生的列表、元组不同的是,Numpy数组支持多维数组的多维索引。x[ 第一个维度(行) , 第二个维度(列) ]

  每一个逗号, 代表索引的一个维度

import numpy as np
x2 = np.random.randint(10, size=(3, 4)) # 二维数组
print(x2)
'''
[[0 3 8 4]
 [0 6 3 6]
 [0 2 0 4]]
'''
print(x2[0])
# [[0 3 8 4]
print(x2[2][1])
# 2

# 如果我们用python原生列表去切割,会发现局限性很强
print(x2[1: , :2])
'''
[[0 6]
 [0 2]]
'''
print(x2[:2 , ::3])
'''
[[0 4]
 [0 6]]
'''
# 第一行,第一列
print(x2[1, 1])
# 6
# 切除左上角四个元素
print(x2[:2 , :2])
'''
[[0 3]
 [0 6]]
'''
print(x2[1:, 1:3])
'''
[[6 3]
 [2 0]]
'''

修改某一个元素值

import numpy as np
x3 = x2 = np.random.randint(10, size=(3, 4)) # 二维数组
print(x3)
'''
[[7 3 4 0]
 [1 4 3 5]
 [6 0 2 0]]
'''
# 修改一个
x3[-1,-1] = 700
print(x3)
'''
[[  7   3   4   0]
 [  1   4   3   5]
 [  6   0   2 700]]
'''
# 左上角四个都改成100
x3[:2,:2] = 100
print(x3) 
'''
[[100 100   4   0]
 [100 100   3   5]
 [  6   0   2 700]]
'''
# 原来基础上乘100
x3[:2, -1] *= 100 
print(x3)
'''
[[100 100   4   0]
 [100 100   3 500]
 [  6   0   2 700]]
'''

试图

  关于数组切片有一点很重要也非常有用,那就是数组切片返回的是数组数据的视图,而不是数值数据的副本。这一点也是 NumPy 数组切片和 Python 列表切片的不同之处:在 Python 列表中,切片是值的副本。

# 为了确保大家都能生成一样的数组, 我们先设置随机数种子
np.random.seed(0)
x2 = np.random.randint(10, size=(3, 4)) # 二维数组
print(x2)
'''
[[5 0 3 3]
 [7 9 3 5]
 [2 4 7 6]]
'''
# 切左上角的四个元素
x2_0 = x2[:2,:2]
print(x2_0)
'''
[[5 0]
 [7 9]]
'''
# 对x2_0 中的数据进行修改
x2_0[0,0] = 500
print(x2_0)
'''
[[500   0]
 [  7   9]]
'''
# x2 上面的数据,也同步发生了变化
print(x2)
'''
[[500   0   3   3]
 [  7   9   3   5]
 [  2   4   7   6]]
'''

浅复制

  不同的数组对象可以共享相同的数据。view方法创建一个新数组对象,该对象看到相同的数据。与前一种情况不同,新数组的维数更改不会更改原始数据的维数,但是新数组数据更改后,也会影响原始数据

import numpy as np
np.random.seed(0)
a = np.arange(0, 12, 1).reshape(6, 2)
print(a)
'''
[[ 0  1]
 [ 2  3]
 [ 4  5]
 [ 6  7]
 [ 8  9]
 [10 11]]
'''
# 创建a的视图c
c = a.view()
print(c)
'''
[[ 0  1]
 [ 2  3]
 [ 4  5]
 [ 6  7]
 [ 8  9]
 [10 11]]
'''
c[0,0] = 100
print(c)
'''
[[100   1]
 [  2   3]
 [  4   5]
 [  6   7]
 [  8   9]
 [ 10  11]]
'''
# a 的数据发生了变化
print(a)
'''
[[100   1]
 [  2   3]
 [  4   5]
 [  6   7]
 [  8   9]
 [ 10  11]]
'''
# 对shape属性 重新赋值
c.shape = 3,4
print(c)
'''
[[100   1   2   3]
 [  4   5   6   7]
 [  8   9  10  11]]
'''
# a 的形状没有发生变化
print(a)
[[100   1]
 [  2   3]
 [  4   5]
 [  6   7]
 [  8   9]
 [ 10  11]]

改为创建副本(深复制)

&msp; 也可以通过.copy()方法创建一个副本

# 为了确保大家都能生成一样的数组, 我们先设置随机数种子
np.random.seed(0)
x2 = np.random.randint(10, size=(3, 4)) # 二维数组
print(x2)
'''
[[5 0 3 3]
 [7 9 3 5]
 [2 4 7 6]]
'''

# 副本(深复制)
x2_1 = x2[:2,:2].copy()
print(x2_1)
'''
[[5 0]
 [7 9]]
'''
x2_1[0,0] = 500
print(x2_1)
'''
[[500   0]
 [  7   9]]
'''
print(x2)
'''
[[5 0 3 3]
 [7 9 3 5]
 [2 4 7 6]]
'''

小练习:

  创建一个随机数组,数组分布在0-1之间,形状为(5,7)

  • 把其中的第一列数据中的第2,3个,第二列的第1,5个设置为空
  • 输出数组的形状,数据类型,元素个数
  • 把右下角的数字改为0.38
  • 把最右排数字统一加上0.25
  • 整个数组统一乘以3
import numpy as np
np.random.seed(0)
x = np.random.rand(5,7)
print(x)
x[1:3,0] =np.nan
x[1:6:4,1] = np.nan
print(x)
print(x.shape,x.dtype,x.size)
x[-1,-1] = 0.38
print(x)
x[:,-1] *= 0.25
print(x)
x *= 3
print(x)

数组的变形

改变数组的形状

  数组的变形也是一类非常有用的操作。数组变形最灵活的实现方式是通过 reshape() 函数来实现。

import numpy as np
# 为了确保大家都能生成一样的数组, 我们先设置随机数种子
np.random.seed(0)
x1 = np.random.randint(10, size=6) # 一维数组
print(x1)
'''
[5 0 3 3 7 9]

'''
# 数组的变形: 只要个数能对的上,怎么变都行
one = x1.reshape(2,3)
print(one)
'''
[[5 0 3]
 [3 7 9]]
'''
two = x1.reshape(6,1)
# 我们依旧查看改变后的形状,
print(two.shape)
#  (6,1)

小技巧

    技巧:在使用 reshape 时,可以将其中的一个维度指定为 -1,Numpy 会自动计算出它的真实值

x2 = np.random.randint(10, size=(3, 4)) # 二维数组

print(x2)
'''
[[3 5 2 4]
 [7 6 8 8]
 [1 6 7 7]]
'''

# 因为元素个数不能变, 当所有维度中只剩下一个维度没有确定的时候,实际上这个维度已经确定了
# 可以省略一个维度用-1代替
three = x2.reshape(-1,6)
print(three)
'''
[[3 5 2 4 7 6]
 [8 8 1 6 7 7]]
'''

拉伸成一维数组(数组的平铺)

  • .ravel()
x2 = np.random.randint(10, size=(3, 4)) # 二维数组

print(x2)
'''
[[3, 5, 2, 4],
[7, 6, 8, 8],
[1, 6, 7, 7]]
'''
# 拉成一维,拉成一维
pingpu = x2.ravel()
print(pingpu)
[3 5 2 4 7 6 8 8 1 6 7 7]

转置

  • .T
x2 = np.random.randint(10, size=(3, 4)) # 二维数组

print(x2)
'''
[[3 5 2 4]
 [7 6 8 8]
 [1 6 7 7]]
'''
# 交换行和列
# 交换行和列
zhuanzhi = x2.T
print(zhuanzhi)
'''
[[3 7 1]
 [5 6 6]
 [2 8 7]
 [4 8 7]]
'''

 无论是ravel、reshape、T,它们都不会更改原有的数组形状,都是返回一个新的数组。也就是我们之前学过的浅复制

数组的拼接

拼接或连接 NumPy 中的两个数组主要由.concatenate实现

import numpy as np
x = np.array([34, 43, 12])
y = np.array([343, 34, 676])
# 拼接
pinjie = np.concatenate((x,y))
print(pinjie)
'''
[ 34  43  12 343  34 676]

'''
z = [0, 0, 0]
x2 = np.concatenate([x, y, z]).reshape((3, 3))
print(x2)
'''
[[ 34  43  12]
 [343  34 676]
 [  0   0   0]]
'''
x3 = x2.copy()
# 将两个二维数组 纵向拼接
zong = np.concatenate((x2,x3),axis=0 )
print(zong)
'''
[[ 34  43  12]
 [343  34 676]
 [  0   0   0]
 [ 34  43  12]
 [343  34 676]
 [  0   0   0]]
'''
# 将两个二维数组 横向拼接
heng = np.concatenate((x2,x3),axis=1 )
print(heng)
'''
[[ 34  43  12  34  43  12]
 [343  34 676 343  34 676]
 [  0   0   0   0   0   0]]
'''

数据的分裂

  将一个数组分成几个较小的数组既然可以将多个数组进行对堆叠,自然也可以将一个数组拆分成多个小数组。使用split,可以指定均匀切割成几份,也可以指定沿着哪个位置进行切割, 还可以指定沿着哪个轴进行切割..split(ary, indices_or_sections, axis=0)

  • sections均匀切分成几份
  • indices 手动指定切分点
a = np.arange(24).reshape(4,6)
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]]
'''
two_fen = np.split(a,2 ,axis = 0)
print(two_fen)
# 返回的结果,是列表
'''
[array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]]), 
array([[12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])]
'''
four_fen = np.split(a,4 ,axis = 0)
print(four_fen)
'''
[array([[0, 1, 2, 3, 4, 5]]), 
array([[ 6,  7,  8,  9, 10, 11]]), 
array([[12, 13, 14, 15, 16, 17]]),
array([[18, 19, 20, 21, 22, 23]])]

'''
#可以特定提取出第几组
four_fen = np.split(a,4 ,axis = 0)[3]
print(four_fen)
'''
[[18 19 20 21 22 23]]

'''
zong_qie = np.split(a, 6, axis = 1)
print(zong_qie)
'''
[array([[ 0],
       [ 6],
       [12],
       [18]]), array([[ 1],
       [ 7],
       [13],
       [19]]), array([[ 2],
       [ 8],
       [14],
       [20]]), array([[ 3],
       [ 9],
       [15],
       [21]]), array([[ 4],
       [10],
       [16],
       [22]]), array([[ 5],
       [11],
       [17],
       [23]])]
'''
## 我们发现这种会有一种局限就是,只能均匀切

在这里插入图片描述

# 不均匀切分
buJunyun  = np.split(a,[2,5] , axis= 1 )
print(buJunyun)
# [2,5]表示在索引为2,5处分别切一刀
'''
[array([[ 0,  1],
       [ 6,  7],
       [12, 13],
       [18, 19]]), array([[ 2,  3,  4],
       [ 8,  9, 10],
       [14, 15, 16],
       [20, 21, 22]]), array([[ 5],
       [11],
       [17],
       [23]])]
'''

小练习

  1. 创建一个形状为(4, 5)的数组线性序列, 线性序列的值从5开始到25.
  2. 把数字拉伸成一维数组, 直接在原数组上变化
  3. 把数组的形状改为(5, 4)
  4. 对数组进行转置
  5. 将数组分裂成(1, 5)(2, 5)(1, 5)的三个子数组
  6. 把得到的第一个数组和第三个数组进行横向拼接和纵向拼接
import numpy as np
x = np.arange(5,25).reshape(4,5)
print(x)
la = x.ravel()
print(la)
gaibian = x.reshape(5,4)
print(gaibian)
zhuanzhi = x.T
print(zhuanzhi)
fenlie  = np.split(x,[1,3],axis = 0 )
print(fenlie)
a1 = np.split(x,[1,3],axis = 0 )[0]
a3 = np.split(x,[1,3],axis = 0 )[2]
pinjie = np.concatenate((a1,a3), axis = 0)
print(pinjie)

广播机制

什么是广播

  我们都知道,Numpy中的基本运算(加、减、乘、除、求余等等)都是元素级别的,但是这仅仅局限于两个数组的形状相同的情况下。可是大家又会发现,如果让一个数组加1的话,结果是整个数组的结果都会加1,这是什么情况呢?

x = np.array(range(12)).reshape(3, 4)
print(x)
'''
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
'''
x2 = np.array([1, 2, 3, 4])
print(x2)
'''
[1 2 3 4]

'''
x3 = x +x2
print(x3)
'''
[[ 1  3  5  7]
 [ 5  7  9 11]
 [ 9 11 13 15]]
'''

  我们发现x2分别加到了x的每一行当中去,这就是广播机制,当把一个低维和一个高维数据进行计算时,会自动将低维数据拉伸到和高维相同的形状,然后进行对应元素位置操作
在这里插入图片描述

Numpy运算

  Numpy 中数组上的算术运算符使用元素级别。最后的结果使用新的一个数组来返回。

基本运算操作

import numpy as np
a = np.array( [20,30,40,50] )
b = np.arange( 4 )
print(a)
print(b)
'''
[20 30 40 50]
[0 1 2 3]
'''
c = a - b
print(c)
'''
[20 29 38 47]

'''
d = b ** 2
print(d)
'''
[0 1 4 9]

'''
e = a < 35
print(e)
'''
[ True  True False False]

'''

  需要注意的是,乘法运算符*的运算在NumPy数组中也是元素级别的(这与许多矩阵语言不同)。如果想要执行矩阵乘积,可以使用dot函数

# 二维数组就可以当做矩阵用
A = np.array( [[1,1], [0,1]] )
B = np.array( [[2,0], [3,4]] )
print(A)
print(B) 
'''
[[1 1]
 [0 1]]
[[2 0]
 [3 4]]
'''
## 对应元素相乘
C = A * B
print(C)
'''
[[2 0]
 [0 4]]
'''
# 显然这并不符合矩阵乘法运算


# 矩阵相乘(matrix product)
# A 左乘 B
D = A.dot(B)  # 也可以写成 D = np.dot(A,B)
print(D)
'''
[[5 4]
 [3 4]]
'''
# B 左乘 A
E = B.dot(A)   # 也可以写成 E = np.dot(B,A)
print(E)
'''
[[2 2]
 [3 7]]
'''

常用函数

数学运算函数
add(x1,x2 [,out])按元素添加参数,等效于 x1 + x2
subtract(x1,x2 [,out])按元素方式减去参数,等效于x1 - x2
multiply(x1,x2 [,out])逐元素乘法参数,等效于x1 * x2
divide(x1,x2 [,out])逐元素除以参数,等效于x1 / x2
exp(x [,out])计算输入数组中所有元素的指数。
exp2(x [,out])对于输入数组中的所有p,计算2 * p*。
log(x [,out])自然对数,逐元素。
log2(x [,out])x的基础2对数。
log10(x [,out])以元素为单位返回输入数组的基数10的对数。
expm1(x [,out])对数组中的所有元素计算exp(x) - 1
log1p(x [,out])返回一个加自然对数的输入数组,元素。
sqrt(x [,out])按元素方式返回数组的正平方根。
square(x [,out])返回输入的元素平方。
sin(x [,out])三角正弦。
cos(x [,out])元素余弦。
tan(x [,out])逐元素计算切线。

 与manth包一样

A = np.array( [[1,1], [0,1]] )
B = np.array( [[2,0], [3,4]] )
print(A)
print(B)
C = np.add(A,B)
print(C)
'''
[[1 1]
 [0 1]]
[[2 0]
 [3 4]]
[[3 1]
 [3 5]]
'''


规约函数

  下面所有的函数都支持axis来指定不同的轴,用法都是类似的。

函数名称函数功能
ndarray.sum([axis,dtype,out,keepdims])返回给定轴上的数组元素的总和。
ndarray.cumsum([axis,dtype,out])返回沿给定轴的元素的累积和。
ndarray.mean([axis,dtype,out,keepdims])返回沿给定轴的数组元素的平均值。
ndarray.var([axis,dtype,out,ddof,keepdims])沿给定轴返回数组元素的方差。
ndarray.std([axis,dtype,out,ddof,keepdims])返回给定轴上的数组元素的标准偏差。
ndarray.argmax([axis,out])沿着给定轴的最大值的返回索引。
ndarray.min([axis,out,keepdims])沿给定轴返回最小值。
ndarray.argmin([axis,out])沿着给定轴的最小值的返回索引。
x = np.random.randint(10, size=12).reshape(4,3)
print(x)
'''
[[5 2 4]
 [8 4 9]
 [0 7 4]
 [4 3 7]]
'''
he = np.sum(x) # 默认全部相加
print(he)
# 57
zong_he = np.sum(x, axis=0)
print(zong_he)
# [17 16 24]
heng_he = np.sum(x, axis = 1)
print(heng_he)
# [11 21 11 14]
zong_max = np.max(x, axis = 0)
print(zong_max)
# [8 7 9]

小练习

  以下数据是我们班级学生的平均身高

[179 , 160 , 179 , 153 , 173 , 161 , 185 , 158 , 173 , 173 , 173 , 163 , 175 , 178 , 173 , 183 , 168 , 173 , 174 , 173 , 173 , 168 , 170 , 168 , 172 , 170 , 173 , 168 , 172 , 178 , 165 , 169 , 173 , 183 , 172 , 173 , 167 , 175 , 178 , 178 , 182 , 185]

 根据数据计算:

  • 班级同学的平均身高
  • 身高最高的同学的身高
  • 身高最低的同学的身高
  • 班级同学身高的标准差
  • 身高的中位数
  • 然后编写函数, 计算出所有数据的sigmoid函数值
L = [179 , 160 , 179 , 153 , 173 , 161 , 185 , 158 , 173 , 173 , 173 , 163 , 175 , 178 , 173 , 183 , 168 , 173 , 174 , 173 , 173 , 168 , 170 , 168 , 172 , 170 , 173 , 168 , 172 , 178 , 165 , 169 , 173 , 183 , 172 , 173 , 167 , 175 , 178 , 178 , 182 , 185]
H = np.array(L)
print(H)
# 规约函数
pingjun =  np.mean(H)
print(pingjun)
zuigao = np.max(H)
print(zuigao)
zuidi = np.min(H)
print(zuidi)
biaozhuncha = np.std(H)
print(biaozhuncha)
zhongwei = np.median(H)
print(zhongwei)
def sigmoid(x):
    return 1 / ( 1 + np.exp(-x))
print(sigmoid(H / 100))



这篇关于Python数据清洗{Numpy}的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程