数据分析
7.1 数据分析三剑客
一、数据分析三剑客简介
在Python数据分析领域,有三个不可或缺的核心库,被称为"数据分析三剑客":
NumPy:数值计算基础库,提供高性能的多维数组对象
Pandas:数据处理和分析库,提供强大的数据结构和数据分析工具
Matplotlib:数据可视化库,提供丰富的绘图功能
二、NumPy 概述
☆ 什么是 NumPy
NumPy(Numerical Python)是Python科学计算的基础包,它提供了:
快速高效的多维数组对象 ndarray
用于对数组执行元素级计算以及直接对数组执行数学运算的函数
用于读写硬盘上基于数组的数据集的工具
线性代数运算、傅里叶变换,以及随机数生成
用于将C、C++、Fortran代码集成到Python的工具
☆ NumPy 的特点
高效的数组运算:比纯Python代码快10-100倍
丰富的数学函数:支持大量的数学运算
广播功能:不同形状的数组之间的数学运算
底层语言实现:核心代码用C语言编写,执行效率高
三、Pandas 概述
☆ 什么是 Pandas
Pandas是基于NumPy构建的库,为Python编程语言提供了快速、强大、灵活且易于使用的数据结构和数据分析工具。
☆ Pandas 的核心数据结构
Series:一维带标签数组
DataFrame:二维表格型数据结构
☆ Pandas 的主要功能
数据清洗和准备
数据整理和转换
数据分析和建模
数据可视化
四、Matplotlib 概述
☆ 什么是 Matplotlib
Matplotlib是Python最著名的绘图库,它提供了一整套和MATLAB类似的绘图API,非常适合交互式绘图。
☆ Matplotlib 的特点
丰富的图表类型:线图、散点图、柱状图、饼图等
高度可定制:可以控制图表的每一个细节
多种输出格式:支持PNG、PDF、SVG等格式
与IPython兼容:支持在IPython环境中交互式绘图
五、三者的关系
1 层次依赖关系
NumPy、Pandas 和 Matplotlib 三者构成了 Python 数据分析的完整技术栈,它们之间存在着清晰的层次依赖关系:
NumPy 是基础层
提供了高效的多维数组(ndarray)对象
是 Pandas 和 Matplotlib 的底层依赖
负责数值计算和数组操作
Pandas 是数据处理层
基于 NumPy 构建,使用 NumPy 数组作为底层存储
提供了更高级的数据结构(Series、DataFrame)
专注于数据清洗、整理和分析
Matplotlib 是可视化层
依赖于 NumPy 的数据结构
能够直接处理 Pandas 的数据对象
负责将数据转化为直观的图表
2 功能互补关系
三者各司其职,形成了完整的数据分析工作流:
NumPy - 数值计算引擎
核心功能:数学运算、线性代数、随机数生成
数据格式:ndarray 多维数组
优势:计算效率高,内存占用少
Pandas - 数据处理工具
核心功能:数据清洗、转换、聚合、分析
数据格式:Series(一维)、DataFrame(二维)
优势:数据操作便捷,支持缺失值处理
Matplotlib - 可视化平台
核心功能:图表绘制、图形定制、结果展示
输出形式:静态图片、交互式图表
优势:图表类型丰富,定制化程度高
3 代码示例
`# 三者的典型工作流程
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 注意:新版本需要指定 matplotlib 使用 TkAgg 作为图形后端来渲染和显示图表
import matplotlib
matplotlib.use('TkAgg')
# NumPy:数据生成和处理
data = np.random.randn(100, 3)
# Pandas:数据整理和分析
df = pd.DataFrame(data, columns=['A', 'B', 'C'])
summary = df.describe()
# Matplotlib:数据可视化
df.plot(kind='hist', alpha=0.5)
plt.show()
`7.2 NumPy
一、NumPy 安装和导入
☆ 安装 NumPy
`# 使用 pip 安装
pip install numpy
# 使用 conda 安装
conda install numpy
`☆ 导入 NumPy
`import numpy as np # 惯例缩写为 np
`二、NumPy 核心数据结构:ndarray
☆ 创建数组
`import numpy as np
# 从列表创建数组
arr1 = np.array([1, 2, 3, 4, 5])
print("一维数组:", arr1)
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print("二维数组:\n", arr2)
# 创建特殊数组
zeros_arr = np.zeros((3, 4)) # 全0数组
print("全0数组:\n", zeros_arr)
ones_arr = np.ones((2, 3)) # 全1数组
print("全1数组:\n", ones_arr)
# 创建序列数组
range_arr = np.arange(0, 10, 2) # 0到10,步长为2
print("范围数组:", range_arr)
linspace_arr = np.linspace(0, 1, 5) # 0到1,等分5份
print("等分数组:", linspace_arr)
# 创建随机数组
random_arr = np.random.rand(3, 3) # 0-1均匀分布
print("随机数组:\n", random_arr)
normal_arr = np.random.randn(3, 3) # 标准正态分布
print("正态分布数组:\n", normal_arr)
`☆ 数组属性
`import numpy as np
# 创建示例数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
print("数组:", arr)
print("数组维度:", arr.ndim) # 维度数
print("数组形状:", arr.shape) # 形状 (行数, 列数)
print("数组大小:", arr.size) # 元素总数
print("数据类型:", arr.dtype) # 数据类型
`三、NumPy 数组操作
☆ 数组索引和切片
`import numpy as np
# 创建示例数组
arr = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
print("原始数组:\n", arr)
# 索引
print("第一个元素:", arr[0, 0]) # 第一行第一列
print("最后一行:", arr[-1]) # 最后一行
print("第二列:", arr[:, 1]) # 所有行的第二列
# 切片
print("前两行:\n", arr[:2]) # 前两行
print("前两行的前两列:\n", arr[:2, :2]) # 前两行前两列
print("每隔一个元素取一个:\n", arr[::2, ::2]) # 行和列都隔一个取一个
# 布尔索引
bool_idx = arr > 5
print("大于5的元素:\n", arr[bool_idx])
print("直接布尔索引:\n", arr[arr > 5])
`☆ 数组形状操作
`import numpy as np
arr = np.arange(12)
print("原始一维数组:", arr)
# 重塑形状
arr_2d = arr.reshape(3, 4)
print("重塑为3x4数组:\n", arr_2d)
# 转置
arr_t = arr_2d.T
print("转置数组:\n", arr_t)
# 展平数组
arr_flat = arr_2d.flatten()
print("展平数组:", arr_flat)
# 调整大小
arr_resized = np.resize(arr, (3, 5))
print("调整大小:\n", arr_resized)
`四、NumPy 数学运算
☆ 基本运算
`import numpy as np
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])
print("数组a:", a)
print("数组b:", b)
# 算术运算
print("加法:", a + b)
print("减法:", a - b)
print("乘法:", a * b)
print("除法:", a / b)
print("幂运算:", a ** 2)
# 比较运算
print("大于比较:", a > 2)
print("等于比较:", a == b)
# 矩阵乘法
matrix_a = np.array([[1, 2], [3, 4]])
matrix_b = np.array([[5, 6], [7, 8]])
print("矩阵乘法:\n", np.dot(matrix_a, matrix_b))
`☆ 统计运算
`import numpy as np
arr = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print("数组:\n", arr)
print("总和:", np.sum(arr))
print("每列总和:", np.sum(arr, axis=0)) # 沿列方向
print("每行总和:", np.sum(arr, axis=1)) # 沿行方向
print("平均值:", np.mean(arr))
print("标准差:", np.std(arr))
print("方差:", np.var(arr))
print("最小值:", np.min(arr))
print("最大值:", np.max(arr))
print("最小值索引:", np.argmin(arr))
print("最大值索引:", np.argmax(arr))
`五、NumPy 广播机制
`import numpy as np
# 广播示例
a = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
b = np.array([10, 20, 30])
print("数组a:\n", a)
print("数组b:", b)
print("广播加法:\n", a + b) # b被广播到a的每一行
# 另一个广播例子
c = np.array([[1], [2], [3]])
print("数组c:\n", c)
print("广播乘法:\n", a * c) # c被广播到a的每一列
`7.3 Pandas
一、Pandas 安装和导入
☆ 安装 Pandas
`# 使用 pip 安装
pip install pandas
# 使用 conda 安装
conda install pandas
`☆ 导入 Pandas
`import pandas as pd # 惯例缩写为 pd
`二、Pandas 核心数据结构
☆ Series:一维带标签数组
`import pandas as pd
import numpy as np
# 从列表创建Series
s1 = pd.Series([1, 3, 5, np.nan, 6, 8])
print("从列表创建的Series:")
print(s1)
# 从字典创建Series
s2 = pd.Series({'a': 1, 'b': 2, 'c': 3})
print("\n从字典创建的Series:")
print(s2)
# 指定索引
s3 = pd.Series([10, 20, 30], index=['x', 'y', 'z'])
print("\n指定索引的Series:")
print(s3)
# Series操作
print("\nSeries操作:")
print("值:", s3.values)
print("索引:", s3.index)
`☆ DataFrame:二维表格数据结构
`import pandas as pd
import numpy as np
# 从字典创建DataFrame
data = {
'姓名': ['张三', '李四', '王五', '赵六'],
'年龄': [25, 30, 35, 28],
'城市': ['北京', '上海', '广州', '深圳'],
'工资': [5000, 7000, 6000, 8000]
}
df = pd.DataFrame(data)
print("创建的DataFrame:")
print(df)
# 从列表创建DataFrame
data_list = [
['张三', 25, '北京', 5000],
['李四', 30, '上海', 7000],
['王五', 35, '广州', 6000],
['赵六', 28, '深圳', 8000]
]
df2 = pd.DataFrame(data_list, columns=['姓名', '年龄', '城市', '工资'])
print("\n从列表创建的DataFrame:")
print(df2)
# 查看DataFrame基本信息
print("\nDataFrame基本信息:")
print("形状:", df.shape)
print("列名:", df.columns)
print("索引:", df.index)
print("数据类型:\n", df.dtypes)
`三、DataFrame 基本操作
☆ 数据查看和选择
`import pandas as pd
import numpy as np
# 创建示例DataFrame
data_list = [
['张三', 25, '北京', 5000],
['李四', 30, '上海', 7000],
['王五', 35, '广州', 6000],
['赵六', 28, '深圳', 8000]
]
df = pd.DataFrame(data_list, columns=['姓名', '年龄', '城市', '工资'], index=["s1", "s2", "s3", "s4"])
print("\n从列表创建的DataFrame:")
print(df)
# 查看数据
print("\n前3行:")
print(df.head(3))
print("\n后2行:")
print(df.tail(2))
print("\n描述性统计:")
print(df.describe())
# 选择数据
print("\n选择单列:")
print(df['姓名'])
print("\n选择多列:")
print(df[['姓名', '年龄']])
print("\n使用loc选择(标签索引):")
print(df.loc['s1']) # 选择一行
print(df.loc[['s1', 's3']]) # 选择多行
print(df.loc['s1':'s3']) # 切片选择
print("\n使用iloc选择(位置索引):")
print(df.iloc[0]) # 第一行
print(df.iloc[[0, 2]]) # 选择多行
print(df.iloc[0:3]) # 切片选择
`☆ 数据筛选和过滤
`import pandas as pd
import numpy as np
# 创建示例数据
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六', '钱七'],
'年龄': [25, 30, 35, 28, 32],
'部门': ['技术部', '销售部', '技术部', '人事部', '销售部'],
'工资': [5000, 7000, 6000, 5500, 7500]
})
print("原始数据:")
print(df)
# 条件筛选
print("\n年龄大于30的员工:")
print(df[df['年龄'] > 30])
print("\n技术部的员工:")
print(df[df['部门'] == '技术部'])
print("\n使用query方法筛选:")
print(df.query('年龄 > 28 and 工资 < 7000'))
# 排序
print("\n按工资降序排序:")
print(df.sort_values('工资', ascending=False))
print("\n按多列排序(部门升序,工资降序):")
print(df.sort_values(['部门', '工资'], ascending=[True, False]))
`四、数据处理和清洗
☆ 处理缺失值
已知数据如下:
`A,B,C
1.0,5.0,9
2.0,,10
,,11
4.0,8.0,12
,,
`缺失值处理代码如下:
`import pandas as pd
import numpy as np
# 读取包含缺失值的数据
df = pd.read_csv("清洗数据.csv", sep=",")
print("原始数据(包含缺失值):")
print(df)
# 检查缺失值
print("\n缺失值统计:")
print(df.isnull().sum())
print("\n非缺失值统计:")
print(df.notnull().sum())
# 删除缺失值
print("\n删除包含缺失值的行:")
print(df.dropna())
print("\n删除全部为缺失值的列:")
print(df.dropna(how='all'))
# 填充缺失值
print("\n用指定值填充缺失值:")
print(df.fillna(0))
print("\n用均值填充:")
print(df.fillna(df.mean()))
`☆ 数据转换
已知数据:
`产品,销售额,地区
A,100,北京
B,200,上海
C,150,广州
A,300,北京
B,250,上海
C,180,广州
`分组聚合代码如下:
`import pandas as pd
# 创建示例数据
df = pd.read_csv("分组聚合数据.csv", sep=",")
print("原始数据:")
print(df)
# 分组聚合
print("\n按产品分组计算总销售额:")
print(df.groupby('产品')['销售额'].sum())
print("\n按产品和地区分组计算统计量:")
print(df.groupby(['产品', '地区'])['销售额'].agg(['sum', 'mean']))
# 数据透视表
print("\n数据透视表:")
pivot_df = df.pivot_table(index='产品', values="销售额", aggfunc='sum')
print(pivot_df)
print("\n数据透视表:")
pivot_df = df.pivot_table(index=['产品', '地区'], values="销售额", aggfunc=['sum', 'mean'])
print(pivot_df)
`7.4 Matplotlib
一、Matplotlib 安装和导入
☆ 安装 Matplotlib
`# 使用 pip 安装
pip install matplotlib
# 使用 conda 安装
conda install matplotlib
`☆ 导入 Matplotlib
`import matplotlib.pyplot as plt # 惯例缩写为 plt
`二、基本绘图功能
折线图
`import numpy as np
import matplotlib.pyplot as plt
# 注意:新版本需要指定 matplotlib 使用 TkAgg 作为图形后端来渲染和显示图表
import matplotlib
matplotlib.use('TkAgg')
# 注意:中文显示需要额外设置字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 创建数据
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 1, 5, 3])
# 绘制折线图
plt.figure(figsize=(8, 5))
plt.plot(x, y,color='blue')
# 添加标题和标签
plt.title("折线图示例")
plt.xlabel("X轴")
plt.ylabel("Y轴")
# 显示网格
plt.grid()
# 显示图表
plt.show()
`☆ 散点图
`import numpy as np
import matplotlib.pyplot as plt
# 注意:新版本需要指定 matplotlib 使用 TkAgg 作为图形后端来渲染和显示图表
import matplotlib
matplotlib.use('TkAgg')
# 注意:中文显示需要额外设置字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 创建数据
np.random.seed(42) # 设置随机种子,保证结果可重复
x = np.random.randn(50)
y = x * 2 + np.random.randn(50) * 0.8 # 添加一些随机噪声
# 绘制散点图
plt.figure(figsize=(8, 5))
plt.scatter(x, y, color='red')
# 添加标题和标签
plt.title("散点图示例")
plt.xlabel("X值")
plt.ylabel("Y值")
# 显示网格
plt.grid()
# 显示图表
plt.show()
`7.5 中美日GDP数据分析综合案例
一、项目需求
需求:单独获取中美日三个国家的各个年份的GDP数据,并绘制出折线图方便对比
已知中美日GDP数据如下
最终效果如下:
二、参考代码
`# 需求: 绘制中美日三个国家的GDP数据每年变化折线图
# 1.导包
import pandas as pd
import matplotlib.pyplot as plt
# 注意:新版本需要指定 matplotlib 使用 TkAgg 作为图形后端来渲染和显示图表
import matplotlib
matplotlib.use('TkAgg')
# 注意:中文显示需要额外设置字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 2.读取数据
df = pd.read_csv("1960-2019全球GDP数据.csv", sep=',', encoding='gbk')
# 3.了解数据
print(df.shape)
# 4.数据预处理
# 因为数据中有很多列数据是空的NaN,所以需要删除空值
df.dropna(inplace=True)
print(df.shape)
# 5.数据分析
# 步骤1: 获取中美日的gdp数据
df_cn = df[df["country"] == "中国"].copy()
df_us = df[df["country"] == "美国"].copy()
df_jp = df[df["country"] == "日本"].copy()
# 步骤2: 使用年份作为索引列
df_cn.set_index("year", inplace=True)
df_us.set_index("year", inplace=True)
df_jp.set_index("year", inplace=True)
# 步骤3: 把GDP列名分别改为中国,美国,日本,方便区分
df_cn.rename(columns={"GDP": "中国"}, inplace=True)
df_us.rename(columns={"GDP": "美国"}, inplace=True)
df_jp.rename(columns={"GDP": "日本"}, inplace=True)
# 6.数据可视化
plt.title("1960-2019年中美日GDP数据折线图")
plt.plot(df_cn.index, df_cn["中国"], label="中国", color="red")
plt.plot(df_us.index, df_us["美国"], label="美国", color="green")
plt.plot(df_jp.index, df_jp["日本"], label="日本", color="blue")
# 添加图例和网格
plt.legend()
plt.grid()
# 展示
plt.show()
`