Python数据分析三剑客:NumPy、Pandas、Matplotlib全攻略

前言

在数据科学领域,Python凭借其强大的生态系统成为首选工具。其中,NumPy、Pandas和Matplotlib被誉为"数据科学三剑客",它们协同工作,构成了Python数据科学分析的基础框架。

大家往往能看见很多非常详细的教学,但却忽视了这三者是如何来协同工作的,本文将系统讲解这三个库的核心概念、使用方法及它们之间的协作关系,最后通过一个完整的数据分析流程,帮助您快速掌握Python数据科学的实战技能。

不废话,直接上流程图

数据分析流程图展示

在这里插入图片描述

Numpy

简介

在Python中,原生列表可以存储各种类型的数据,但当我们需要进行高效的数值计算时,列表的效率会非常低下。想象一下,如果要对一个包含100万元素的列表进行平方运算,Python需要逐个元素执行,这会非常慢。

NumPy通过ndarray(N维数组)提供了一个高效的数值计算基础。它将数据存储在连续的内存块中,使用C语言实现底层计算,避免了Python解释器的开销,使得数值计算速度提升数十倍。

数组基础:Ndarray 对象

NumPy的核心对象是ndarray(n维数组),简单来说,ndarray是一个高效、多维、同类型数据的容器

例如:

import numpy as np
# 创建一个2x3的二维数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
print("维度:", arr.ndim)      # 2(二维数组)
print("形状:", arr.shape)     # (2, 3)(2行3列)
print("数据类型:", arr.dtype) # int64(64位整数)
1.数组的创建

NumPy提供了多种方式创建数组,以下是常用方法

1.1 基本数组创建

这是最直观的创建方式,将Python列表转换为ndarray。这也是数据导入的常见方式,例如从CSV文件读取数据后,可以将其转换为ndarray进行处理。

import numpy as np

# 一维数组
data_1d = np.array([1, 2, 3, 4])
print("一维数组:", data_1d)

# 二维数组
data_2d = np.array([[1, 2, 3, 4],
                    [5, 6, 7, 8],
                    [9, 10, 11, 12]])
print("二维数组:\n", data_2d)

一维数组类似于列表,而二维数组则类似于表格,有行和列。在实际应用中,我们经常需要将列表数据转换为NumPy数组以便进行高效的数值运算。

1.2 特定模式数组创建

NumPy提供了多种函数来创建具有特定模式的数组,避免手动编写循环。

# 等差数组(arange)
data_arange = np.arange(1, 10, 2)  # 从1开始,到10结束,步长为2
print("arange创建的数组:", data_arange)

# 全0数组
data_zeros = np.zeros(shape=(2, 3))
print("全0数组:\n", data_zeros)

# 全1数组
data_ones = np.ones(shape=(2, 3))
print("全1数组:\n", data_ones)

# 未初始化数组(空数组)
data_empty = np.empty(shape=(2, 3))
print("全空数组:\n", data_empty)

# 等间隔数组(linspace)
data_linspace = np.linspace(1, 10, 10)  # 从1到10,生成10个等间隔数据
print("linspace序列数组:", data_linspace)

arange函数类似于Python的range,但返回的是数组;zeros和ones用于创建全0或全1数组;empty创建未初始化的数组,其内容取决于内存状态;linspace则用于创建指定数量的等间隔数据。

1.3 随机数组

在数据分析和机器学习中,随机数生成是常见的需求。

# 随机数组(0-1之间)
data_random = np.random.rand(3, 4)
print("随机数组:\n", data_random)

# 随机整数数组
data_randint = np.random.randint(2, 5, size=(3, 4))  # 3行4列,元素值在2-5之间
print("随机整数数组:\n", data_randint)

rand函数生成0到1之间的均匀分布随机数,而randint生成指定范围内的随机整数。这些随机数组在模拟实验和随机抽样中非常有用。

2. ndarray 的核心特性
2.1 维度(ndim)

表示数组的维度数。一维数组(如向量)的维度为1,二维数组(如矩阵)的维度为2。

import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
print("维度:", arr.ndim)  # 输出: 2

了解数组的维度有助于我们理解数据的结构,例如在图像处理中,彩色图像是三维数组(高度、宽度、颜色通道)。

2.2 形状(shape)

表示数组在每个维度上的大小。对于二维数组,shape是(行数, 列数)。

print("形状:", arr.shape)  # 输出: (2, 3)

形状是数组的一个重要属性,许多操作(如重塑、广播)都依赖于形状。

2.3 数据类型(dtype)

表示数组中元素的数据类型。NumPy支持多种数据类型,如int64、float64、bool等。

print("数据类型:", arr.dtype)  # 输出: int64

数据类型决定了数组元素在内存中的存储方式以及所能进行的操作。例如,整数类型和浮点数类型的运算规则不同。

2.4 元素数量(size)

表示数组中元素的总数。

print("元素数量:", arr.size)  # 输出: 6

元素数量是形状各维度的乘积,通常在内存管理和性能优化时需要考虑。

3. ndarray 的基本操作
3.1 改变形状(reshape)
data = np.array([[1,2,3,4,5], [1,2,3,4,5]])
print("原形状:", data.shape)  # (2,5)
data = data.reshape((5,2))    # 5行2列
print("新形状:", data.shape)  # (5,2)

重塑操作不改变数据本身,只改变数据的视图。需要注意的是,重塑后的数组元素数量必须与原数组相同。

3.2 数组转置(T)
data = [[1,2,3], [4,5,6], [7,8,9]]
data_array = np.array(data)
print("转置前:\n", data_array)
print("转置后:\n", data_array.T)  # 行变列

转置是矩阵运算中的常见操作,例如在计算矩阵乘法时我们就经常用到。

3.3 数组运算:向量化优势
a = np.array([1,2,3])
b = np.array([4,5,6])
# 向量化加法
print(a + b)  # [5,7,9]
# 向量化乘法(点乘)
print(a * b)  # [4,10,18]

向量化运算是NumPy的核心优势之一,它允许我们直接对数组进行运算,而不需要编写循环。这不仅代码简洁,而且运行效率高。

小结

你已完成基础的NumPy学习,在以上过程中,我们学习了:

  • NumPy的核心对象ndarray
  • ndarray的创建、属性和操作
  • NumPy在数值计算中的优势
    接下来,让我们开始学习Pandas吧!

Pandas

简介

Pandas是Python中用于数据操作和分析的库,它建立在NumPy之上,提供了更高级的数据结构和操作工具。Pandas的名称源自"panel data"(面板数据)和"Python data analysis"(Python数据分析)的组合。
Pandas的核心优势在于:

  • 提供了DataFrame和Series数据结构,使表格数据处理更加直观
  • 支持多种数据格式的导入导出
  • 提供了丰富的数据处理函数,如缺失值处理、排序、分组等
  • 与NumPy紧密集成,可以高效利用NumPy的向量化操作

数据结构:Series和DataFrame

1. Series:一维带索引的数据结构

Series是Pandas的核心数据结构之一,它类似于一维数组,但带有索引(标签),使得数据访问更加灵活。
第一列为索引,第二列为Series数据

1.1 Series的创建方式:

方式1:从列表创建


temperature = pd.Series([25, 28, 30, 22], 
                       index=['北京', '上海', '广州', '成都'],
                       name='今日温度')
print("城市温度数据:")
print(temperature)

我们创建了一个包含四个城市温度的Series,并指定了索引为城市名称。这样,我们就可以通过城市名称来访问对应的温度数据。

方式2:从字典创建(更直观)

sales_data = pd.Series({'一月': 1500, '二月': 1800, '三月': 2200, '四月': 1900})# 前键后值
print("\n月度销售数据:")
print(sales_data)

通过字典创建Series时,字典的键会自动成为Series的索引,字典的值成为Series的数据。这种方式在已有字典数据时非常方便。

1.2 Series的索引访问方式:

index: 查看下标(索引/标签)
values: 查看下标的值

print(sales_data.index)
print(sales_data.values)

index属性返回索引对象,values属性返回NumPy数组。这让我们可以分别操作索引和数据。

iloc: 基于位置的索引(原下标,也就是默认值,计算机的记忆)

print("第一个元素 (iloc[0]):", sales_data.iloc[0])
print("前两个元素 (iloc[0:2]):", sales_data.iloc[0:2])

索引位置从0开始,注意,切片是左闭右开区间。

loc: 基于标签的索引(标签是由我们自主给的,计算机并不会自己产生)

print("一月数据 (loc['一月']):", sales_data.loc['一月'])
print("一月到三月 (loc['一月':'三月']):", sales_data.loc['一月':'三月'])

布尔索引: 条件筛选

high_sales = sales_data[sales_data > 2000]
print("高销售额月份 (>2000):", high_sales)

布尔索引允许我们根据条件筛选数据,返回满足条件的子集。

1.3 Series的运算:

算术运算: 支持向量化运算,索引会自动对齐

s1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
s2 = pd.Series([4, 5, 6], index=['b', 'c', 'd'])

# 直接相加:索引对齐,顺序无关
print("直接相加:", s1 + s2) # 使用这种相加,没有对应标签的情况下会错误,显示NAN

# 使用add方法:可处理缺失值
print("安全相加:", s1.add(s2, fill_value=0)) # fill_value=0代表如果出现没有值的情况,以0代替

# 同理还有:
print(s1.sub(s2,fill_value=0))
print(s1.mul(s2,fill_value=1))
print(s1.div(s2,fill_value=1))
# 需注意的是,乘除不要设为0

Series的运算会自动对齐索引,如果某个索引在其中一个Series中不存在,结果会变为NaN。使用fill_value可以填充缺失值。

统计运算: 内置常用统计方法

data = pd.Series([10, 20, 30, 40, 50])
print("最大值:", data.max())
print("最小值:", data.min())
print("总和:", data.sum())
print("平均值:", data.mean())
print("标准差:", data.std())
2. DataFrame:二维表格型数据结构

DataFrame是Pandas的另一个核心数据结构,它类似于表格,包含行和列,每列可以有不同的数据类型。

2.1 DataFrame的创建方式(常用):

由字典创建

# 每列数据长度必须相同
data = {
    '姓名': ['赵明', '钱芳', '孙强', '李娜'],
    '年龄': [19, 20, 21, 19],
    '数学': [85, 92, 78, 96],
    '英语': [88, 85, 92, 79],
    '物理': [90, 87, 85, 93]
}
df = pd.DataFrame(data)

通过字典创建DataFrame时,字典的键成为列名,字典的值(列表)成为列数据。注意,各列表的长度必须相同。

从Series创建:

student_id = pd.Series(['S001', 'S002', 'S003'], index=['赵明', '钱芳', '孙强'])
math_scores = pd.Series([85, 92, 78], index=['赵明', '钱芳', '孙强'])
df = pd.DataFrame({'学号': student_id, '数学成绩': math_scores})

我们可以将多个Series组合成DataFrame,Series的索引会成为DataFrame的行索引。

2.2 DataFrame的索引与切片:

设置行列索引

df = pd.DataFrame(data, 
                 index=['学生A', '学生B', '学生C', '学生D'],  # 行索引
                 columns=['姓名', '数学', '英语', '年龄'])   # 列索引

在创建DataFrame时,我们可以通过index参数设置行索引,通过columns参数设置列索引。

列选择

# 选择单列(返回Series)
names = df['姓名']

# 选择多列(返回DataFrame)
subset = df[['姓名', '数学']]

选择单列返回Series,选择多列返回DataFrame。注意,多列选择时需要使用列表。

行选择

# loc基于标签
print(df.loc['学生A'])           # 单行
print(df.loc['学生A':'学生C'])    # 多行(包含结束位置)

# iloc基于位置
print(df.iloc[0])               # 第一行
print(df.iloc[0:2])             # 前两行

loc通过行索引标签选择行,iloc通过行位置选择行。注意,loc的切片是闭区间,iloc的切片是左闭右开。

行列混合选择

# 选择特定行列
print(df.loc['学生A', '姓名'])           # 单个值
print(df.loc['学生A':'学生C', '姓名':'数学']) # 行列范围
print(df.iloc[0:2, 0:2])                # 位置范围

我们可以同时选择行和列,返回指定的数据子集。

条件筛选

# 单条件
high_scores = df[df['数学'] > 90]

# 多条件
good_students = df[(df['数学'] > 85) & (df['年龄'] < 21)]

# 字符串条件
zhao_students = df[df['姓名'].str.contains('赵')]

条件筛选返回满足条件的行。多条件时,每个条件要用括号括起来,并使用逻辑运算符(&、|、~)连接。

2.3 DataFrame的常用操作

查看数据基本信息

print("数据形状:", df.shape)        # (行数, 列数)
print("列名:", df.columns)      # 所有列的名称
print("索引:", df.index)        # 行索引
print("数据类型:\n", df.dtypes) # 每列的数据类型

查看这些属性能帮助我们快速了解DataFrame的结构。

数据预览

print("前5行:\n", df.head(5))    # 查看前5行
print("后5行:\n", df.tail(5))    # 查看后5行
print("统计描述:\n", df.describe()) # 数值列的统计信息

headtail方法用于查看数据的前几行或后几行。describe方法生成数值列的描述性统计,包括计数、均值、标准差、最小值、四分位数和最大值。

数据导入与导出

Pandas支持多种数据格式的导入和导出,这是数据分析流程中不可或缺的环节。

数据导入

在实际项目中,推荐使用相对路径来管理数据文件

import pandas as pd
import os

# 方法1:使用绝对路径(不推荐,可移植性差)
# fpath_excel = r"D:\数据分析\项目\data\学生成绩.xlsx"
# fpath_csv = r"D:\数据分析\项目\data\学生信息.csv"

# 方法2:使用相对路径(推荐)
# 获取脚本所在的目录
script_dir = os.path.dirname(os.path.abspath(__file__))
# 设置当前工作目录为脚本所在的目录
os.chdir(script_dir)

# 定义数据文件路径
fpath_excel = r"data\学生成绩.xlsx"
fpath_csv = r"data\学生信息.csv"
fpath_json = r"data\学生信息.json"
# CSV文件
df = pd.read_csv(fpath_csv, encoding='utf-8')

# Excel文件
df = pd.read_excel(fpath_excel, sheet_name='Sheet1')

# JSON文件
df = pd.read_json(fpath_json)

# 从URL读取
df = pd.read_csv('https://example.com/data.csv')

需要注意的是,读取CSV文件时可能需要指定编码格式,如utf-8。

还有其他的我没一一列举,但是都很好记对不对?都是read_再加上后缀名。

数据导出
# 保存为 CSV 文件
df.to_csv('output.csv', index=False, encoding='utf-8') # index=False表示不带行索引
# 保存为 Excel 文件
df.to_excel('output.xlsx', sheet_name='Sheet1', index=False)

# 保存为 JSON 文件
df.to_json('output.json', orient='records', indent=4)

# 保存为 HTML 文件
df.to_html('output.html', index=False)

导出数据时,通常我们不希望保存行索引,因此设置index=False。to_json的orient参数指定了JSON的格式,indent参数使JSON文件更易读。

数据预处理

1. 缺失值处理

缺失数据是数据分析中常见的问题,Pandas提供了丰富的处理方法。

检测缺失值:
# 检查每个单元格是否有缺失值
print(df.isnull()) # 缺省值对应的值为True,返回值为Boolean的Series或者DataFrame对象
print(df.notnull())# 缺省值对应的值为False,返回值为Boolean的Series或者DataFrame对象

# 统计每列缺失值数量
print(df.isnull().sum())

# 检查整个DataFrame是否有缺失值
print(df.isnull().any().any())

isnull和notnull方法返回与原始DataFrame形状相同的布尔值DataFrame,其中True表示缺失或非缺失。通过sum方法可以统计每列的缺失值数量。

处理缺失值

处理缺失值是数据清洗中至关重要的一步,往往你需要根据业务的具体情况来选择处理,来保证数据的质量。

# 删除缺失值
df_dropped = df.dropna()              # 删除任何包含NaN的行
df_dropped_col = df.dropna(axis=1)    # 删除任何包含NaN的列

# 填充缺失值
df_filled = df.fillna(0)              # 用0填充
df_ffill = df.fillna(method='ffill')  # 用前一个值填充
df_bfill = df.fillna(method='bfill')  # 用后一个值填充
df_mean = df.fillna(df.mean())        # 用列均值填充

删除缺失值可能会损失大量数据,因此填充往往是更好的选择。填充时,可以根据业务知识选择填充值,或者使用统计量(如均值、中位数)填充。

2. 数据筛选与操作

Pandas提供了强大的数据筛选和操作功能,使数据处理更加高效。

数据排序
# 按单列排序
df_sorted = df.sort_values('数学')

# 按多列排序
df_sorted = df.sort_values(['年龄', '数学'], ascending=[True, False])

# 按索引排序
df_sorted_index = df.sort_index()

排序可以帮助我们快速找到最大值、最小值,或者按照特定顺序查看数据。多列排序时,先按第一列排序,第一列相同再按第二列排序。

数据分组
# 添加班级列用于分组
df['班级'] = ['一班', '二班', '一班', '二班']

# 单列分组
grouped = df.groupby('班级')

# 分组后聚合
result = grouped.agg({
    '数学': ['mean', 'max', 'min', 'count'],
    '英语': 'mean',
    '年龄': 'mean'
})

分组操作是数据分析中的常见操作,它允许我们对每个组进行聚合计算。agg方法允许我们对不同的列应用不同的聚合函数。

数据转换
# 添加新列
df['数学等级'] = df['数学'].apply(lambda x: '优秀' if x > 90 else '良好')

# 类型转换
df['年龄'] = df['年龄'].astype(float)

# 重命名列
df = df.rename(columns={'数学': '数学成绩', '英语': '英语成绩'})

apply方法允许我们对Series的每个元素应用一个函数。类型转换可以确保数据类型的正确性。重命名列可以使列名更清晰。

Pandas与NumPy的协作

Pandas建立在NumPy之上,两者可以完美协作,具体如下:

1. 二者的相互转换
# DataFrame/Series 转 NumPy数组
numpy_array = df.values
series_array = series.values

# NumPy数组 转 DataFrame
df_from_numpy = pd.DataFrame(numpy_array, columns=['姓名', '年龄', '数学', '英语'])
2. 协同计算
# 使用NumPy函数处理Pandas数据
df['标准化数学成绩'] = (df['数学'] - df['数学'].mean()) / df['数学'].std()

# 在Pandas中直接使用NumPy运算
result = np.sqrt(df[['数学', '英语']])

# 布尔索引结合
high_scores = df[np.array(df['数学']) > 90]

小结

你已完成Pandas的核心学习,掌握了:

  • Series和DataFrame数据结构
  • 数据导入导出方法
  • 缺失值处理和数据清洗技巧
  • 与NumPy的协作关系
    现在,让我们进入最后一个环节:数据可视化,使用Matplotlib将处理后的数据以图表形式展示。

Matplotlib

简介

Matplotlib是Python中用于数据可视化的库,可以轻松地将Pandas DataFrame中的数据可视化。

Matplotlib的核心特点:

  • 提供了丰富的图表类型(折线图、散点图、柱状图等)
  • 高度可定制的图表样式
  • 与Pandas无缝集成
  • 支持多种输出格式(PNG、PDF、SVG等)

Matplotlib架构

Matplotlib采用面向对象的设计理念,其核心架构由三个关键组件构成:

1. Figure(画布)

Figure 是 Matplotlib 中最顶层的容器,相当于整个绘图的"画布",包含了所有绘图元素。它是整个图形的顶级容器,可以包含一个或多个坐标区域(Axes)。

# 创建一个10x8英寸、300DPI的画布
fig = plt.figure(figsize=(10, 8), dpi=300)
2. Axes(坐标区域)

Axes 是 Figure 中的一个绘图区域,是实际进行数据绘制的"画布上的画布"。它是 Matplotlib 中最常用的绘图对象,包含了坐标轴、刻度、标签、图例等所有元素。

# 创建包含一个坐标区域的 Figure
fig, ax = plt.subplots(figsize=(8, 6))

# 或者在已有 Figure 上添加坐标区域
fig = plt.figure()
ax = fig.add_subplot(111)  # 创建1x1网格的第一个子图

# 或者创建2x2网格的坐标区域
fig, axs = plt.subplots(2, 2)  # 2x2网格的坐标轴
3. Axis(坐标轴)

Axis 是 Axes 中的坐标轴,负责管理坐标轴的细节,如刻度、刻度标签、轴标签和范围。注意:Axes 是单数,Axis 才是坐标轴。

# 设置x轴和y轴的标签
ax.set_xlabel('X轴', fontsize=12)
ax.set_ylabel('Y轴', fontsize=12)

# 设置坐标轴范围
ax.set_xlim(0, 10)
ax.set_ylim(0, 100)
三者的关系

Figure > Axes > Axis
(画布 > 绘图区域 > 坐标轴)

Matplotlib绘图流程

1. 创建Figure:初始化画布

作用:创建绘图的基础容器,设置画布大小、分辨率等全局参数。

2. 添加Axes:指定绘图区域

作用:在画布上创建实际的绘图区域,一个画布可以包含多个绘图区域。

3. 绘制数据:在Axes上添加图表元素

作用:在指定的绘图区域上绘制实际的数据图形。

4. 设置属性:定制图表外观

作用:美化图表,添加标题、标签、图例等,使图表更专业、易读。

5. 显示/保存:plt.show()或plt.savefig()

作用:展示或保存最终的图表成果。

绘图流程图展示

在这里插入图片描述

常用图形绘制

1. 折线图 - 趋势分析
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 创建示例数据
dates = pd.date_range('2023-01-01', periods=12, freq='M')
sales_a = [120, 135, 148, 165, 180, 195, 210, 225, 240, 255, 270, 285]
sales_b = [100, 115, 130, 145, 160, 170, 175, 185, 195, 205, 215, 225]

fig, ax = plt.subplots(figsize=(12, 6))

# 绘制两条折线
ax.plot(dates, sales_a, marker='o', linewidth=2, label='产品A', color='#2E86AB')
ax.plot(dates, sales_b, marker='s', linewidth=2, label='产品B', color='#A23B72')

# 图表装饰
ax.set_title('月度销售趋势分析', fontsize=16, fontweight='bold', pad=20)
ax.set_xlabel('月份', fontsize=12)
ax.set_ylabel('销售额(万元)', fontsize=12)
ax.legend(loc='upper left', frameon=True, fancybox=True, shadow=True)
ax.grid(True, alpha=0.3)

# 设置x轴刻度格式
ax.xaxis.set_major_formatter(plt.matplotlib.dates.DateFormatter('%Y-%m'))
plt.xticks(rotation=45)

plt.tight_layout()
plt.show()
2. 柱状图 - 分类比较
# 创建产品数据
products = ['笔记本', '手机', '平板', '耳机', '手表']
sales_q1 = [120, 200, 80, 150, 90]
sales_q2 = [140, 220, 95, 160, 110]

x = np.arange(len(products))
width = 0.35

fig, ax = plt.subplots(figsize=(10, 6))

# 绘制分组柱状图
bars1 = ax.bar(x - width/2, sales_q1, width, label='第一季度', 
               color='#4CB5AE', edgecolor='grey', alpha=0.8)
bars2 = ax.bar(x + width/2, sales_q2, width, label='第二季度', 
               color='#D4A5A5', edgecolor='grey', alpha=0.8)

# 添加数据标签
def add_labels(bars):
    for bar in bars:
        height = bar.get_height()
        ax.annotate(f'{height}',
                    xy=(bar.get_x() + bar.get_width() / 2, height),
                    xytext=(0, 3),  # 垂直偏移
                    textcoords="offset points",
                    ha='center', va='bottom', fontsize=10)

add_labels(bars1)
add_labels(bars2)

# 图表装饰
ax.set_title('各产品季度销售额对比', fontsize=16, fontweight='bold')
ax.set_xlabel('产品类别', fontsize=12)
ax.set_ylabel('销售额(万元)', fontsize=12)
ax.set_xticks(x)
ax.set_xticklabels(products)
ax.legend()

plt.tight_layout()
plt.show()
3. 散点图 - 相关性分析
from matplotlib import colors

# 生成模拟数据
np.random.seed(42)
n_points = 100
study_hours = np.random.normal(20, 8, n_points)
exam_scores = 50 + 2 * study_hours + np.random.normal(0, 10, n_points)

fig, ax = plt.subplots(figsize=(10, 6))

# 绘制散点图
scatter = ax.scatter(study_hours, exam_scores, 
                    c=exam_scores, cmap='viridis', 
                    alpha=0.7, s=60, edgecolors='white', linewidth=0.5)

# 添加趋势线
z = np.polyfit(study_hours, exam_scores, 1)
p = np.poly1d(z)
ax.plot(study_hours, p(study_hours), "r--", alpha=0.8, linewidth=2)

# 图表装饰
ax.set_title('学习时间与考试成绩关系', fontsize=16, fontweight='bold')
ax.set_xlabel('每周学习时间(小时)', fontsize=12)
ax.set_ylabel('考试成绩', fontsize=12)

# 添加颜色条
cbar = plt.colorbar(scatter)
cbar.set_label('成绩分数', rotation=270, labelpad=15)

# 添加相关系数
correlation = np.corrcoef(study_hours, exam_scores)[0, 1]
ax.text(0.05, 0.95, f'相关系数: {correlation:.3f}', 
        transform=ax.transAxes, fontsize=12,
        bbox=dict(boxstyle="round,pad=0.3", facecolor="white", alpha=0.8))

plt.tight_layout()
plt.show()
4. 饼图 - 占比分析
# 市场份额数据
categories = ['电商', '线下零售', '批发', '跨境电商', '其他']
market_share = [35, 25, 20, 15, 5]
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7']
explode = (0.1, 0, 0, 0, 0)  # 突出显示第一项

fig, ax = plt.subplots(figsize=(10, 8))

# 绘制饼图
wedges, texts, autotexts = ax.pie(market_share, explode=explode, labels=categories, 
                                  colors=colors, autopct='%1.1f%%', shadow=True,
                                  startangle=90, textprops={'fontsize': 12})

# 美化百分比文本
for autotext in autotexts:
    autotext.set_color('white')
    autotext.set_fontweight('bold')

ax.set_title('销售渠道市场份额分布', fontsize=16, fontweight='bold', pad=20)

plt.tight_layout()
plt.show()

实战案例:简单的薪资数据分析

第一步、下载数据集到本地

🔗 点击访问完整项目:数据集和Jupyter Notebook
在这里插入图片描述

第二步、启动jupyter notebook

如果有小伙伴没有使用过jupyter notebook的,可以先往后看,后面再自己实践。

第三步、导入并查看数据的基础信息

在这里插入图片描述

第四步、数据清洗(载入、去重、处理缺失值、格式调整、异常值处理)

在这里插入图片描述

第五步、可视化分析(部分展示,具体可看下载的笔记本)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第六步、总结分析

在这里插入图片描述
这是我简单展示的一个流程,但在你实际操作中,你可以完成更多的数据操作和分析,写出更多也更有价值的信息。

结束语

可能刚开始接触数据分析的你,会觉得上面的东西很繁琐,很难记忆,也不清楚自己究竟该怎么来学习数据分析,我完全理解你的感受。确实,对于刚接触数据分析的朋友来说,面对这么多的函数、方法和概念,很容易感到不知所措。

让我们换个角度来看待这个问题:学习数据分析其实很像学做菜。第一次进厨房时,看到满架的调料、各种厨具,也会觉得无从下手。但当你真正动手做几道菜后,就会发现常用的也就那几样,慢慢地就知道什么菜该放什么调料了。

数据分析也是如此。你现在不需要记住每一个函数、每一个参数,更重要的是理解整个流程——拿到数据后怎么清洗、怎么探索、怎么用合适的图表呈现结果。具体的函数用法,完全可以在用的时候查文档,或者翻回这篇文章看看。

我建议你先找个自己感兴趣的小数据集进行练习。比如分析一下电商销量、电影评分、天气变化,或者你感兴趣的任何话题。在实践中遇到问题时,再回头来看相关的知识点,这样学起来既扎实又有趣。

最后,求点赞、收藏、评论,这将成为我不断更新的动力。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐