Python数据分析之NumPy——第一天(上)

本文基于《利用Python进行数据分析》,介绍了NumPy的多维数组对象ndarray。内容涵盖生成ndarray的多种方式,如np.array、zeros等函数;阐述了ndarray的数据类型及astype方法的使用;说明了数组算术的向量化特性和广播特性;还讲解了基础索引与切片,强调数组切片是原数组的视图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ndarray:多维数组对象 实质上是一个大数据容器

本文以《利用Python进行数据分析》为基础

1.生成ndarry

 (1)使用array函数。array函数接受任意的序列型对象,生成一个新的包含传递数据的NumPy数组。
import numpy as np
data1 = [6,7.5,8,0,1]
arr1 = np.array(data1)
print(arr1)

[6.  7.5 8.  0.  1. ]

嵌套的序列:

data2 = [[1,2,3,4],[5,6,7,8]]
arr2 = np.array(data2)
print(arr2)

[[1 2 3 4]
 [5 6 7 8]]

data2是一个包含列表的列表,所以NumPy数组arr2形成了一个二维数组,可以通过ndim和shape属性来确认这点

print(arr2.ndim)     #ndim用来查看数组维数
print(arr2.shape)    #shape用来查看数组行列数

2
(2, 4)

除非显示的指定,否则np.array会自动推断生成数组的数据类型。数据类型被存储在一个特殊的元数据dtype中,例如之前的两个例子:

print(arr2.dtype)

int32

除了np.array,还有很多其他函数可以创建新数组。
例如:给定长度和形状后,zeros可以一次性的创造全0数组,ones可以一次性创造全1数组。empty可以创建没有初始化数值的数组。创建高维数组,需要向shape传递一个元组:

a = np.zeros(10)
b = np.zeros((3,6))
print(a)
print(b)

[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. 0. 0. 0.]]
c = np.empty((2,3,2))
print(c)

[[[6.23042070e-307 4.67296746e-307]
  [1.69121096e-306 1.16820707e-307]
  [1.89146896e-307 1.37961302e-306]]

  [[1.05699242e-307 8.01097889e-307]
  [1.37962388e-306 6.89805151e-307]
  [1.78020169e-306 1.42410974e-306]]]

此处使用empty并未生成一个全0的数组,因为使用empty生成一个全0数组是不安全的,有时候他可能返回初始化的垃圾数值
此处生成数组还有一个函数arange,它是Python内建函数range的数组版

a = np.arange(15)
print(a)

[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14]

数组生成函数

函数名描述
array将输入数据(可以是列表,元组,数组以及其他序列) 转换为ndarray,如不显式的指明数据类型,将自动推断;默认复制所有的输入数据
asarray将输入转换为ndarry,但如果输入已经是ndarray则不再复制
arangePython内建函数range的数组版,返回一个数组
ones根据给定形状和数据类型生成一个全1数组
ones_like根据所给定的数组生成一个形状一样的全1数组
zeros根据所给定形状和数据类型生成全0数组
zeros_like根据所给定的数组生成一个形状一样的全0数组

2.ndarray的数据类型

数据类型,即dtype,是一个特殊的对象(表示数据的数据)。

arr1 = np.array([1,2,3],dtype = np.float64)
arr2 = np.array([1,2,3],dtype = np.int32)

print(arr1.dtype)
print(arr2.dtype)

float64
int32

dtype是NumPy能与其他系统灵活交互的原因。数据的dtype通常都按照一个方式命名:类型名,比如float和int,后面接上表明每个元素位数的数字。
不要担心如何记住NumPy的数据类型,尤其是当你还是新手的时候。通常你只需要关心数据的大类,比如是否是浮点型,整数,布尔值,字符串或者某个Python对象。当你需要在内存或硬盘上做更深入的存取操作时,尤其是大数据集时,你才真正需要了解数据的数据类型。

Numpy数据类型

类型类型代码描述
int8,uint8i1,u1有符号和无符号的8位整数
int16,uint16i2,u2有符号和无符号的16位整数
float16f2半精度浮点数
float32f或f4标准单精度浮点数;兼容C语言float
bool?布尔值,存储True或False

我只罗列了部分的数据类型
你可以使用astype方法显式地转换数组的数据类型:

arr = np.array([1,2,3,4,5])
print(arr.dtype)
float_arr = arr.astype(np.float64)
print(float_arr.dtype)

int32
float64

上面的例子中,整数被转换成了浮点数。如果我把浮点数转换成整数,则小数点后的部分被消除:

arr = np.array([3.7,-1.2,-2.6,0.5,12.9,10.1])
print(arr)
print(arr.astype(np.int32))

[ 3.7 -1.2 -2.6  0.5 12.9 10.1]
[ 3 -1 -2  0 12 10]

如果你有一个数组,里面的元素都是表达数字含义的字符串,也可以通过astype将字符串转换为数字:

numeric_strings = np.array(['1.25','-9.6','42'],dtype = np.string_)
print(numeric_strings.astype(float))

[ 1.25 -9.6  42.  ]

在NumPy中,当使用numpy.string_类型作字符串数据要小心,因为NumPy会修正它的大小或删除输入且不触发警告。使用astype总是生成一个新数组,即使你传入的dtype与之前一样

3.NumPy数组算术

数组之所以重要是因为它允许你进行批量操作而无任何for循环。NumPy用户称这种特性为向量化。任何两个等尺寸之间的算术操作都应用了逐元素操作的方式:

arr = np.array([[1.,2.,3.],[4.,5.,6.]])

print(arr)
print(arr * arr)
print(arr - arr)

[[1. 2. 3.]
 [4. 5. 6.]]

[[ 1.  4.  9.]
 [16. 25. 36.]]

[[0. 0. 0.]
 [0. 0. 0.]]

带有标量计算的算术操作,会把计算参数传递给数组的每一个元素:

a = 1/arr
b = arr ** 0.5
print(a)
print(b)

[[1.         0.5        0.33333333]
 [0.25       0.2        0.16666667]]

[[1.         1.41421356 1.73205081]
 [2.         2.23606798 2.44948974]]

同尺寸数组之间的比较,会产生一个布尔值数组:

arr = np.array([[1.,2.,3.],[4.,5.,6.]])
arr2 = np.array([[0.,4.,1.],[7.,2.,12.]])

a = arr2 > arr

print(a)

[[False  True False]
 [ True False  True]]

不同尺寸的数组间的操作,将会用到广播特性

4.基础索引与切片

NumPy数组索引是一个大话题,有很多方式可以让你选中数据的子集或某个单个元素。一维数组比较简单。看起来和Python的列表很类似:

arr = np.arange(10)
print(arr)

[0 1 2 3 4 5 6 7 8 9]

a = arr[5]
print(a)

b = arr[5:8]
print(b)

5
[5 6 7]

arr[5:8] = 12
print(arr)

[ 0  1  2  3  4 12 12 12  8  9]

如你所见,如果你传入了一个数值给数组的切片,例如arr[5:8] = 12,数值被传递给了整个切片。区别于Python的内建列表,数组的切片是原数组的视图。这意味着数据表并不是被复制了,任何对于视图的修改都会反映到原数组上。
如果你想要一份数组切片的拷贝而不是一份视图的话,你就必须显式的复制这个数组,例如arr[5:8].copy()。

对更高维的数组,你会有更多的选择。在一个二维数组中,每个索引值对应的元素不再是一个值,而是一个一维数组:

arr2d = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(arr2d[2])

[7 8 9]

因此,单个元素可以通过递归的方式获得。但是要多写点代码,你可以通过传递一个索引的逗号分隔列表去选择单个元素,以下两种方式效果一样:

print(arr2d[0][2])
print(arr2d[0,2])

3
3

在多维数组中,你可以省略后续索引值,返回的对象将是降低一个维度的数组。因此在一个223的数组arr3d中:

arr3d = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])

print(arr3d)
print(arr3d[0])

[[[ 1  2  3]
  [ 4  5  6]]
  [[ 7  8  9]
  [10 11 12]]]

[[1 2 3]
 [4 5 6]]

标量和数组都可以传递给arr3d[0]

old_values = arr3d[0].copy()
arr3d[0] = 42
print(arr3d)
[[[42 42 42]
  [42 42 42]]
  [[ 7  8  9]
  [10 11 12]]]

arr3d[0] = old_values
print(arr3d)
[[[ 1  2  3]
  [ 4  5  6]]
  [[ 7  8  9]
  [10 11 12]]]

arr3d[1,0]返回的是一个一维数组

print(arr3d[1,0])
[7 8 9]
#还可以分解为以下步骤
x = arr3d[1]
print(x)
print(x[0])

[[ 7  8  9]
 [10 11 12]]

[7 8 9]

以上数组子集选择中,返回的数组都是视图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值