Python数据分析必备:Numpy快速上手指南


Python 数据分析必备:NumPy 快速上手指南

数据分析的世界里,Python 早已成为许多人的首选工具。而在 Python 的生态系统中,NumPy 就像一块坚实的基石,为各种高级数据分析工具和库提供了强大的底层支持。想要玩转 Python 数据分析?NumPy 绝对是你绕不开的伙伴。

这篇文章的目的很简单,就是带你快速认识 NumPy,了解它的核心功能,并且能上手进行一些基本操作。咱们不整那些虚头巴脑的理论,直接上干货,用最通俗易懂的方式,让你感受到 NumPy 的魅力。

NumPy 到底是个啥?

简单来说,NumPy (Numerical Python) 是一个用于处理数组的 Python 库。它提供了一个叫做 ndarray 的对象,这是一种高效的多维数组,可以在上面进行各种数学运算。

为什么要用 NumPy 的数组,Python 自带的列表 (list) 不香吗? 这就要说到 NumPy 的几个厉害之处了:

  • 速度快:NumPy 的数组操作是用 C 语言实现的,速度比纯 Python 代码快得多,尤其是在处理大量数据时,这种优势更加明显。
  • 内存省:NumPy 数组存储的是同类型的数据,而 Python 列表可以存储不同类型的数据。这使得 NumPy 数组占用的内存更少,更加紧凑。
  • 功能强:NumPy 提供了大量的数学函数,可以方便地进行各种运算,比如线性代数、傅里叶变换、随机数生成等等。

安装 NumPy

安装 NumPy 非常简单,只要你的电脑上装了 Python 和 pip,就可以通过以下命令安装:

bash
pip install numpy

安装完成后,就可以在 Python 代码中导入 NumPy 了:

python
import numpy as np

通常,我们都用 np 作为 NumPy 的别名,这是约定俗成的,大家最好都这么写,方便交流。

NumPy 的核心:ndarray

NumPy 的核心就是 ndarray,也就是 n 维数组 (n-dimensional array)。你可以把它想象成一个表格,或者一个矩阵,甚至更高维度的结构。

创建 ndarray

有几种方法可以创建 ndarray:

  1. 从 Python 列表创建

    ```python
    import numpy as np

    一维数组

    arr1 = np.array([1, 2, 3, 4, 5])
    print(arr1) # 输出: [1 2 3 4 5]

    二维数组

    arr2 = np.array([[1, 2, 3], [4, 5, 6]])
    print(arr2) # 输出: [[1 2 3]
    # [4 5 6]]
    ```

  2. 使用 NumPy 内置函数创建

    • np.zeros():创建元素全为 0 的数组。
    • np.ones():创建元素全为 1 的数组。
    • np.empty():创建未初始化的数组(元素值不确定)。
    • np.arange():创建等差数列。
    • np.linspace():创建等间隔数列。
    • np.eye(): 创建一个二维的单位矩阵(对角线为1,其他为0)

    ```python
    import numpy as np

    创建一个 3x4 的全 0 数组

    zeros_arr = np.zeros((3, 4))
    print(zeros_arr)

    创建一个 2x2 的全 1 数组

    ones_arr = np.ones((2, 2))
    print(ones_arr)

    创建一个从 0 到 9 的一维数组

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

    创建一个从 0 到 1,包含 5 个元素的等间隔数组

    linspace_arr = np.linspace(0, 1, 5)
    print(linspace_arr)

    创建一个3*3的单位矩阵

    eye_arr = np.eye(3)
    print(eye_arr)
    ```

ndarray 的属性

ndarray 对象有一些重要的属性,可以帮助我们了解它的结构:

  • ndarray.ndim:数组的维度(轴的个数)。
  • ndarray.shape:数组的形状(每个维度的大小)。
  • ndarray.size:数组元素的总个数。
  • ndarray.dtype:数组元素的数据类型。
  • ndarray.itemsize: 数组中每个元素的字节大小

```python
import numpy as np

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

print("维度:", arr.ndim) # 输出: 维度: 2
print("形状:", arr.shape) # 输出: 形状: (2, 3)
print("大小:", arr.size) # 输出: 大小: 6
print("数据类型:", arr.dtype) # 输出: 数据类型: int64
print("元素字节:",arr.itemsize) #输出 元素字节: 8 (这个根据系统和数据类型可能变化,int64一般是8个字节)
```

数据类型

NumPy 支持多种数据类型,常见的有:

  • int8, int16, int32, int64:有符号整数。
  • uint8, uint16, uint32, uint64:无符号整数。
  • float16, float32, float64:浮点数。
  • complex64, complex128:复数。
  • bool:布尔值 (True 或 False)。

在创建数组时,可以通过 dtype 参数指定数据类型:

```python
import numpy as np

arr = np.array([1, 2, 3], dtype=np.float32)
print(arr.dtype) # 输出: float32
```

如果不指定,NumPy 会自动推断数据类型。

NumPy 的数组操作

NumPy 的强大之处在于它提供了丰富的数组操作,可以高效地进行各种运算。

索引和切片

NumPy 数组的索引和切片操作与 Python 列表类似,但更加灵活。

  • 一维数组

    ```python
    import numpy as np

    arr = np.arange(10)
    print(arr[0]) # 输出: 0 (第一个元素)
    print(arr[2:5]) # 输出: [2 3 4] (索引 2 到 4 的元素)
    print(arr[-1]) # 输出: 9 (最后一个元素)
    ```

  • 多维数组

    ```python
    import numpy as np

    arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    print(arr[0, 0]) # 输出: 1 (第一行第一列的元素)
    print(arr[1, :]) # 输出: [4 5 6] (第二行的所有元素)
    print(arr[:, 2]) # 输出: [3 6 9] (第三列的所有元素)
    print(arr[0:2, 1:3]) # 输出: [[2 3]
    # [5 6]] (第一、二行,第二、三列的元素)
    ```

数组形状变换

NumPy 允许你改变数组的形状,只要元素总数不变。

  • reshape():改变数组的形状。
  • ravel():将数组展平成一维。
  • flatten():将数组展平成一维(返回的是拷贝)。
  • transpose():数组转置。
  • T: 数组转置的快捷方式。

```python
import numpy as np

arr = np.arange(12)
print(arr) #输出:[ 0 1 2 3 4 5 6 7 8 9 10 11]

改变形状为 3x4

new_arr = arr.reshape((3, 4))
print(new_arr) #输出:[[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]

展平成一维

flattened_arr = new_arr.ravel()
print(flattened_arr) #输出:[ 0 1 2 3 4 5 6 7 8 9 10 11]

数组转置

transposed_arr = new_arr.transpose()
print(transposed_arr) #输出: [[ 0 4 8]
# [ 1 5 9]
# [ 2 6 10]
# [ 3 7 11]]

使用T进行转置

transposed_arr_T = new_arr.T
print(transposed_arr_T) #输出: [[ 0 4 8]
# [ 1 5 9]
# [ 2 6 10]
# [ 3 7 11]]
```

数组拼接

多个数组可以拼接成一个更大的数组。

  • np.concatenate():沿着指定轴拼接数组。
  • np.vstack():垂直拼接数组(行方向)。
  • np.hstack():水平拼接数组(列方向)。

```python
import numpy as np

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

垂直拼接

vstacked_arr = np.vstack((arr1, arr2))
print(vstacked_arr) #输出:[[1 2]
# [3 4]
# [5 6]]

arr3 = np.array([[7],[8]])

水平拼接

hstacked_arr = np.hstack((arr1,arr3))
print(hstacked_arr) #输出:[[1 2 7]
# [3 4 8]]
```

数组分裂

可以将一个大数组分割成多个小数组
* np.split():沿着指定轴分割数组。
* np.vsplit():垂直分割数组(行方向)。
* np.hsplit():水平分割数组(列方向)。

```python
import numpy as np

arr = np.arange(16).reshape(4,4)
print(arr) #原始数组

[[ 0 1 2 3]

[ 4 5 6 7]

[ 8 9 10 11]

[12 13 14 15]]

水平分割

h_split = np.hsplit(arr, 2)
print(h_split)

[array([[ 0, 1],

[ 4, 5],

[ 8, 9],

[12, 13]]), array([[ 2, 3],

[ 6, 7],

[10, 11],

[14, 15]])]

垂直分割

v_split = np.vsplit(arr,2)
print(v_split)

[array([[0, 1, 2, 3],

[4, 5, 6, 7]]), array([[ 8, 9, 10, 11],

[12, 13, 14, 15]])]

```

数组运算

NumPy 的一大优势就是可以对整个数组进行运算,而不需要写循环。

  • 基本运算+, -, *, /, ** (幂运算) 等。
  • 通用函数 (ufunc):NumPy 提供了很多通用函数,可以对数组中的每个元素进行操作,比如 np.sin(), np.cos(), np.exp(), np.sqrt() 等。
  • ** 广播(broadcasting):** 当对两个形状不同的数组进行运算时,NumPy 会自动触发广播机制, 将较小的数组 "广播" 成与较大数组相同的形状,然后进行元素级运算。

```python
import numpy as np

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

基本运算

print(arr1 + arr2) # 输出: [5 7 9]
print(arr1 * arr2) # 输出: [ 4 10 18]
print(arr1 ** 2) # 输出: [1 4 9]

通用函数

print(np.sin(arr1)) # 输出: [0.84147098 0.90929743 0.14112001]
print(np.sqrt(arr2)) # 输出: [2. 2.23606798 2.44948974]

广播

arr3 = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr4 = np.array([1,2,3])
print(arr3 + arr4) #输出: [[ 2 4 6]
# [ 5 7 9]
# [ 8 10 12]]
```

广播规则:

  1. 如果两个数组的维度不同,那么维度较小的数组会在其形状的最前面补 1,直到两个数组的维度相同。
  2. 如果两个数组在某个维度上的大小相同,或者其中一个数组在该维度上的大小为 1,那么这两个数组在该维度上是兼容的。
  3. 如果两个数组在所有维度上都兼容,那么它们可以一起广播。
  4. 广播之后,每个数组的形状都等于它们各自形状中每个维度上的最大值。
  5. 如果两个数组的形状在任何维度上都不兼容,那么它们不能一起广播,会引发错误。

统计运算

NumPy 提供了一些常用的统计函数:

  • np.sum():求和。
  • np.mean():求平均值。
  • np.median():求中位数。
  • np.std():求标准差。
  • np.var():求方差。
  • np.min():求最小值。
  • np.max():求最大值。
  • np.argmin(): 求最小值的索引
  • np.argmax(): 求最大值的索引

这些函数可以对整个数组进行运算,也可以沿着指定的轴进行运算。

```python
import numpy as np

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

对整个数组求和

print(np.sum(arr)) # 输出: 21

沿着行方向求和 (axis=1)

print(np.sum(arr, axis=1)) # 输出: [ 6 15]

沿着列方向求和 (axis=0)

print(np.sum(arr, axis=0)) # 输出: [5 7 9]

求整个数组的平均值

print(np.mean(arr)) #输出 3.5
```

线性代数

NumPy 提供了一个 linalg 模块,可以进行一些常用的线性代数运算。

  • np.dot():矩阵乘法。
  • np.linalg.inv():矩阵求逆。
  • np.linalg.det():求行列式。
  • np.linalg.eig():求特征值和特征向量。
  • np.linalg.solve(): 解线性方程组

```python
import numpy as np

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

矩阵乘法

print(np.dot(arr1, arr2)) # 输出: [[19 22]
# [43 50]]

矩阵求逆

arr3 = np.array([[1,2],[3,4]])
inv_arr3 = np.linalg.inv(arr3)
print(inv_arr3) #输出:[[-2. 1. ]
# [ 1.5 -0.5]]
```

布尔索引

除了使用整数索引和切片,NumPy 还支持使用布尔数组进行索引。

```python
import numpy as np
arr = np.array([1,2,3,4,5,6])

创建一个布尔数组

bool_index = arr > 3
print(bool_index) #输出: [False False False True True True]

使用布尔数组进行索引

print(arr[bool_index]) #输出: [4 5 6]

更简洁的写法

print(arr[arr > 3]) #输出: [4 5 6]
```

NumPy 和其他库的比较

为了更直观地展现 NumPy 的优势,我们把它和 Python 内置的列表,以及另一个常用的数据分析库 Pandas 进行一个简单的比较。

处理速度比较:

假设我们要对一个包含 100 万个元素的数组进行求和操作。

  • Python 列表:使用循环求和。
  • NumPy 数组:使用 np.sum() 函数。

```python
import time
import numpy as np

Python 列表

list_data = list(range(1000000))
start_time = time.time()
sum_list = 0
for x in list_data:
sum_list += x
end_time = time.time()
print("Python 列表求和时间:", end_time - start_time)

NumPy 数组

numpy_data = np.arange(1000000)
start_time = time.time()
sum_numpy = np.sum(numpy_data)
end_time = time.time()
print("NumPy 数组求和时间:", end_time - start_time)
```

你会发现,NumPy 的速度明显快于 Python 列表。

功能丰富度比较:

如果要进行一些复杂操作,比如矩阵乘法,或者求解线性方程组,Python 内置列表是没有直接提供这些功能的,需要自己编写函数来实现。而NumPy是直接提供了这些方法的。

Pandas 的 Series 和 DataFrame:

Pandas 是另一个非常重要的数据分析库,它构建在 NumPy 之上。Pandas 提供了两种主要的数据结构:Series (一维带标签数组) 和 DataFrame (二维带标签表格)。

虽然 Pandas 在数据处理和分析方面更加方便,但它的底层仍然依赖于 NumPy。了解 NumPy 的基本概念和操作,可以帮助你更好地理解和使用 Pandas。

可以认为,NumPy 更偏向于底层的数值计算,而 Pandas 更偏向上层的数据处理和分析。

更进一步

这篇文章只是带你快速了解了 NumPy 的一些基本概念和操作,但 NumPy 的功能远不止这些。如果你想更深入地学习 NumPy,可以:

掌握了 NumPy,你就拥有了数据分析的强大工具。多加练习,你也能成为数据分析高手!

THE END