Python 数据分析与可视化:开启数据洞察之旅(5/10)
一、Python 数据分析与可视化简介
在当今数字化时代,数据就像一座蕴藏无限价值的宝藏,等待着我们去挖掘和探索。而 Python,作为数据科学领域的明星语言,凭借其丰富的库和强大的功能,成为了开启这座宝藏的关键钥匙,在数据分析和可视化领域占据着举足轻重的地位。
(一)Python 在数据分析领域的重要性
Python 之所以备受青睐,主要有以下几个原因:
- 简单易学:Python 以其简洁、易读的语法闻名,它采用了人类自然语言的思维方式,使得代码就像一段段清晰的指令,降低了编程的门槛。对于初学者而言,无论是刚踏入编程世界的新手,还是其他领域想要转行从事数据分析的人员,都能轻松上手,快速掌握基本的编程技能。例如,使用 Python 进行简单的数学运算,代码直观易懂,就像在纸上书写数学公式一样。
- 丰富的库和工具:Python 拥有庞大的开源社区,这使得它积累了数量众多、功能各异的库,这些库就像是一个个强大的工具包,涵盖了数据处理、分析、建模、可视化等数据分析的各个环节。无论你是需要进行复杂的数据清洗,还是构建高级的机器学习模型,亦或是创建精美的数据可视化图表,都能在 Python 的库中找到合适的工具。比如,Pandas 库提供了高效的数据处理和分析工具,NumPy 库则为数值计算提供了坚实的基础。
- 强大的数据处理能力:Python 具备高效的数据处理能力,能够轻松应对大规模数据集。通过合理使用 Pandas、NumPy 等库,我们可以实现数据的快速读取、清洗、转换和分析。这些库在底层进行了高度优化,利用了先进的数据结构和算法,大大提高了数据处理的效率。例如,使用 Pandas 读取和处理包含数百万条记录的 CSV 文件,速度快且占用内存少。
- 广泛的应用领域:Python 在金融、医疗、电商、科研等众多领域都得到了广泛的应用。在金融领域,它被用于风险评估、投资分析和量化交易;在医疗领域,可用于疾病预测、药物研发和医疗数据分析;在电商领域,能帮助进行用户行为分析、销售预测和精准营销;在科研领域,可助力实验数据处理、模型构建和结果可视化。Python 的通用性使其成为各个领域数据分析师和科学家的首选工具。
(二)常用的 Python 数据分析与可视化库
在 Python 的数据分析与可视化生态系统中,有许多优秀的库,它们各自发挥着独特的作用,相互配合,为我们提供了强大的数据分析和可视化能力。下面为大家介绍几个常用的库:
- Pandas:Pandas 是 Python 数据分析的核心库,就像是数据处理的瑞士军刀,提供了快速、灵活、明确的数据结构,旨在简单、直观地处理关系型、标记型数据。它的主要数据结构是 Series(一维带标签数组)和 DataFrame(二维带标签表格),这两种数据结构足以应对金融、统计、社会科学、工程等领域里的大多数典型数据处理任务。Pandas 不仅擅长数据的读取、清洗、转换和合并,还内置了基本的绘图功能,能够快速生成简单的图表,使数据分析流程更加连贯和高效。例如,使用 Pandas 可以轻松地从 CSV 文件中读取数据,对数据进行去重、缺失值处理等操作,还能通过几行代码创建数据透视表,对数据进行多维度分析。
- NumPy:NumPy 是 Python 的基础科学计算库,为 Python 提供了快速的数组处理能力,是 Python 数据分析的基石。它支持大量的维度数组与矩阵运算,并且内置了许多数学函数库,如三角函数、指数函数、对数函数等,能够高效地进行各种数值计算。NumPy 的数组操作比 Python 原生的列表操作更加高效,因为它在底层使用了 C 语言实现,减少了 Python 的循环开销。例如,在进行大规模矩阵运算时,使用 NumPy 可以显著提高计算速度,节省计算时间。此外,NumPy 还为其他科学计算库(如 SciPy、Pandas 等)提供了基础支持,许多库都依赖于 NumPy 进行数组操作。
- Matplotlib:Matplotlib 是 Python 中最常用的 2D 绘图库,它就像是一位多才多艺的画师,能够以多种硬拷贝格式和跨平台的交互式环境生成高质量的图形。Matplotlib 提供了广泛的函数和方法,可以轻松绘制各种类型的图表,如折线图、散点图、柱状图、饼图、直方图等,满足不同的数据可视化需求。同时,Matplotlib 还支持对图表的细节进行高度自定义,包括线条颜色、宽度、标记类型、图例、标题、坐标轴标签、刻度等,让我们能够根据具体的需求创建出个性化的图表。例如,通过 Matplotlib 可以精确地控制图表的每一个元素,调整图表的布局和样式,使其更加美观和专业。
- Seaborn:Seaborn 是基于 Matplotlib 的高级绘图库,它在 Matplotlib 的基础上进行了更高层次的封装,提供了更美观、更现代的默认样式和更高级的绘图函数,使得绘制的图表更具吸引力和表现力。Seaborn 专注于统计数据可视化,提供了许多用于展示数据分布、关系和统计特性的函数,如分布图(distplot)、关系图(relplot)、分类图(catplot)、热力图(heatmap)等。这些函数能够帮助我们更直观地理解数据的内在结构和规律,发现数据中的模式和趋势。例如,使用 Seaborn 的热力图可以清晰地展示数据之间的相关性,通过分布图可以快速了解数据的分布情况。而且,Seaborn 与 Pandas 数据结构无缝集成,使用起来非常方便。
- Plotly:Plotly 是一个用于创建交互式可视化的库,它为数据可视化带来了全新的体验。与传统的静态图表不同,Plotly 创建的图表具有交互性,用户可以通过鼠标悬停、缩放、点击等操作来探索数据,获取更多的细节信息。Plotly 支持多种图表类型,包括常见的折线图、柱状图、散点图,以及更高级的 3D 图表、地图、等高线图等,适用于各种数据展示场景。此外,Plotly 还可以将图表导出为 HTML 格式,方便在网页中嵌入和分享。例如,在创建数据仪表盘时,使用 Plotly 可以创建出动态、交互式的可视化界面,让用户能够更加直观地与数据进行交互,深入了解数据背后的信息。
这些库各有所长,在实际的数据分析与可视化项目中,我们通常会根据具体的需求和场景选择合适的库进行组合使用。例如,使用 Pandas 和 NumPy 进行数据处理和分析,然后使用 Matplotlib 或 Seaborn 进行静态图表绘制,当需要创建交互式图表时,则可以选择 Plotly。通过合理运用这些库,我们能够更加高效地完成数据分析与可视化任务,从数据中挖掘出有价值的信息,并以直观、清晰的方式展示给他人。
二、开发工具介绍
在进行 Python 数据分析与可视化的旅程中,选择合适的开发工具至关重要。它们就像是工匠手中的精良工具,能够极大地提升我们的工作效率和开发体验。下面将为大家介绍两款在 Python 数据分析领域广泛使用的开发工具:Jupyter Notebook 和 VSCode。
2.1 Jupyter Notebook
Jupyter Notebook 是一款广受欢迎的开源交互式计算环境,它以网页的形式呈现,为用户提供了一个集成的工作空间,在这个空间里,用户可以创建和共享包含实时代码、数学方程、可视化内容以及说明文本的文档,这些文档被称为 “笔记本”,文件扩展名为.ipynb 。Jupyter Notebook 就像是一个功能强大的实验室工作台,让我们能够在一个地方完成数据分析的整个流程,从数据探索、清洗、分析到可视化展示,一应俱全。
特点和优势
- 交互式编程:这是 Jupyter Notebook 最为突出的特点之一。它允许用户逐行或逐块地执行代码,并立即查看结果,就像与代码进行实时对话一样。这种即时反馈的编程方式非常适合数据分析和探索性编程,我们可以快速迭代和调整代码,直至达到期望的结果。例如,在进行数据探索时,我们可以先读取一小部分数据,然后通过执行单行代码对数据进行简单的统计分析,如计算均值、最大值、最小值等,根据结果再决定下一步的操作。
- 即时查看结果:在 Jupyter Notebook 中,代码的运行结果会直接显示在代码块下方,无论是数据的统计信息、计算结果还是可视化图表,都能一目了然。这使得我们能够迅速验证代码的正确性,及时发现问题并进行调整。比如,当我们使用 Matplotlib 库绘制折线图时,执行代码后,折线图会立即呈现在代码块的下方,方便我们查看和分析数据的趋势。
- 多语言支持:虽然 Jupyter 最初是为 Python 设计的,但它已扩展支持多种编程语言,如 R、Julia 等。通过安装不同的内核(kernel),我们可以在同一个 Notebook 中使用不同的编程语言进行编程,这使得 Jupyter Notebook 成为一个功能强大的平台,可以满足不同编程语言用户的需求。例如,在进行数据分析项目时,我们可能需要使用 Python 进行数据处理,使用 R 进行统计建模,Jupyter Notebook 就能够轻松实现这一需求。
- 富文本展示:Jupyter Notebook 支持 Markdown 和 HTML 等富文本格式,我们可以在文档中插入文本、图片、数学公式、链接等,使得文档内容更加丰富和易于理解。此外,Jupyter Notebook 还支持多种输出格式,如图表、视频等,便于我们展示数据分析和模型训练的结果。比如,在撰写数据分析报告时,我们可以使用 Markdown 语法添加标题、段落、列表等,使报告结构清晰;同时,还可以插入数据可视化图表,增强报告的可视化效果。
- 易于分享:Jupyter Notebook 文档(.ipynb 文件)可以轻松地通过电子邮件、GitHub 等平台与他人分享。这些文件包含了数据处理、模型训练、结果分析的所有步骤,便于他人复现和验证工作。此外,Jupyter Notebook 还支持将文档导出为多种格式,如 HTML、PDF、Markdown 等,以适应不同的展示和分享需求。例如,我们可以将完成的数据分析项目以.ipynb 文件的形式分享给团队成员,他们可以直接打开文件并运行其中的代码,查看分析过程和结果;如果需要在会议上展示,我们可以将 Notebook 导出为 PDF 格式,方便演示。
- 模块化:代码可以分割成多个可执行的单元格,使得大型分析项目更易于管理和组织。我们可以将不同功能的代码放在不同的单元格中,每个单元格可以独立运行,也可以按照顺序依次运行。这样,我们可以更加清晰地组织代码结构,便于调试和维护。比如,在进行一个复杂的机器学习项目时,我们可以将数据读取、数据预处理、模型训练、模型评估等步骤分别放在不同的单元格中,每个单元格专注于一个特定的功能,使代码的逻辑更加清晰。
安装和基本使用方法
- 安装:安装 Jupyter Notebook 通常有两种方式,分别是使用 Anaconda 和 pip 命令。
-
- 使用 Anaconda 安装:Anaconda 是一个流行的 Python 发行版,它包含了许多常用的数据科学库和工具,并且已经自动为我们安装了 Jupyter Notebook 及其他相关工具。我们可以从 Anaconda 官方网站(https://www.anaconda.com/products/individual)下载适合自己操作系统的安装包,然后按照安装向导的提示进行安装。安装完成后,我们可以在开始菜单(Windows 系统)或应用程序文件夹(Mac 系统)中找到 Anaconda Navigator,打开它,在其中可以直接启动 Jupyter Notebook。
-
- 使用 pip 命令安装:如果我们已经安装了 Python,也可以使用 pip 命令来安装 Jupyter Notebook。首先,打开命令行终端(Windows 系统可以通过 “开始菜单” -> “运行”,输入 “cmd” 打开;Mac 系统可以通过 “应用程序” -> “实用工具” -> “终端” 打开),然后输入以下命令将 pip 升级到最新版本:
pip install --upgrade pip
升级完成后,再输入以下命令安装 Jupyter Notebook:
pip install jupyter
- 基本使用方法:
-
- 启动 Jupyter Notebook:安装完成后,在命令行终端中输入以下命令启动 Jupyter Notebook:
jupyter notebook
执行该命令后,系统会自动打开默认的浏览器,并在浏览器中显示 Jupyter Notebook 的主界面。如果浏览器没有自动打开,我们可以复制命令行中显示的 URL 地址(通常是http://localhost:8888/ ),然后手动粘贴到浏览器的地址栏中打开。
- 创建新的 Notebook:在 Jupyter Notebook 的主界面中,点击右上角的 “New” 按钮,在弹出的菜单中选择 “Python 3”(如果我们安装了其他内核,还可以选择其他编程语言),即可创建一个新的 Notebook。新创建的 Notebook 会自动打开,我们可以在其中进行代码编写和运行。
- 编写和运行代码:在 Notebook 中,我们可以看到一个一个的单元格,每个单元格可以输入代码或文本。默认情况下,单元格是代码类型,我们可以在其中输入 Python 代码。例如,输入以下代码:
print("Hello, World!")
然后按下 “Shift + Enter” 组合键,即可运行该单元格中的代码,运行结果会显示在单元格下方。“Shift + Enter” 组合键的作用是运行当前单元格,并自动跳转到下一个单元格;如果我们只想运行当前单元格,不跳转到下一个单元格,可以使用 “Ctrl + Enter” 组合键;如果我们想在当前单元格下方插入一个新的单元格并运行当前单元格,可以使用 “Alt + Enter” 组合键。
- 添加和删除单元格:如果我们需要添加新的单元格,可以点击菜单栏中的 “Insert” -> “Insert Cell Above”(在当前单元格上方插入)或 “Insert Cell Below”(在当前单元格下方插入);如果要删除某个单元格,可以先选中该单元格,然后点击菜单栏中的 “Edit” -> “Delete Cells”,或者使用快捷键 “D, D”(连续按两次 D 键)。
- 修改单元格类型:单元格的类型可以在代码、Markdown 和 Raw NBConvert 之间切换。如果我们想在单元格中输入文本说明,可以将单元格类型切换为 Markdown。选中单元格后,点击菜单栏中的 “Cell” -> “Cell Type”,在弹出的子菜单中选择 “Markdown” 即可。在 Markdown 类型的单元格中,我们可以使用 Markdown 语法编写文本,例如添加标题、段落、列表、链接、图片等。编写完成后,按下 “Shift + Enter” 组合键,即可将 Markdown 文本渲染成富文本格式显示。
- 保存和关闭 Notebook:在编写代码的过程中,我们需要及时保存 Notebook,以免数据丢失。可以点击菜单栏中的 “File” -> “Save and Checkpoint”,或者使用快捷键 “Ctrl + S”(Windows 和 Linux 系统)或 “Command + S”(Mac 系统)进行保存。当我们完成工作后,可以点击菜单栏中的 “File” -> “Close and Halt”,关闭当前 Notebook 并停止内核运行;如果我们只是暂时离开,可以点击浏览器的关闭按钮,下次打开时,Notebook 会恢复到上次保存的状态。
2.2 VSCode
VSCode(Visual Studio Code)是一款由微软开发的轻量级、跨平台的代码编辑器,虽然它本身并不直接支持 Python 数据分析和可视化,但通过安装丰富的插件,它可以成为一个功能强大的 Python 开发环境,在 Python 数据分析领域也得到了广泛的应用。VSCode 就像是一个高度可定制的工作间,我们可以根据自己的需求安装各种插件,打造出适合自己的开发工具。
作为 Python 开发编辑器的优势
- 丰富的插件生态:这是 VSCode 最为显著的优势之一。VSCode 拥有一个庞大的插件市场,其中包含了大量与 Python 开发相关的插件,这些插件可以满足我们在 Python 数据分析和可视化过程中的各种需求。例如,通过安装 “Python” 插件,我们可以获得 Python 语法高亮、智能提示、代码自动补全、代码调试等基本功能;安装 “Jupyter” 插件,我们可以在 VSCode 中直接打开和编辑 Jupyter Notebook 文件,实现与 Jupyter Notebook 类似的交互式编程体验;安装 “Pylance” 插件,可以提供更强大的代码分析和智能感知功能,帮助我们更快地编写高质量的 Python 代码。此外,还有许多其他插件,如代码格式化插件(如 “black”、“autopep8”)、版本控制插件(如 “GitLens”)、数据库管理插件(如 “SQLite”)等,可以进一步增强 VSCode 的功能。
- 轻量级和快速:相比于一些大型的集成开发环境(IDE),VSCode 是一款轻量级的编辑器,它启动速度快,占用系统资源少,这使得我们在编写 Python 代码时能够获得更加流畅的体验。尤其是在处理大型项目或同时打开多个文件时,VSCode 的性能优势更加明显,不会因为资源占用过多而导致系统卡顿。
- 良好的调试支持:VSCode 提供了强大的内置调试工具,支持设置断点、单步执行、变量观察等多种调试功能。在进行 Python 数据分析和可视化开发时,我们经常需要调试代码来查找错误和优化性能。通过 VSCode 的调试功能,我们可以方便地在代码中设置断点,当程序执行到断点处时会暂停,我们可以查看变量的值、跟踪程序的执行流程,从而快速定位和解决问题。例如,在调试一个数据处理脚本时,我们可以在关键代码行设置断点,观察数据在不同处理步骤后的变化情况,找出可能存在的问题。
- 便捷的 Git 集成:VSCode 内置了对 Git 版本控制系统的支持,这使得我们在开发过程中能够方便地进行代码版本管理和团队协作。我们可以直接在 VSCode 中进行 Git 操作,如提交代码、拉取代码、创建分支、合并分支等,无需频繁切换到命令行终端。同时,VSCode 还提供了直观的界面来显示代码的修改情况和版本历史,方便我们查看和管理代码的变更。例如,在一个多人协作的数据分析项目中,我们可以使用 VSCode 的 Git 集成功能,及时将自己的代码提交到远程仓库,并与团队成员的代码进行合并,确保项目的顺利进行。
- 跨平台支持:VSCode 支持 Windows、macOS 和 Linux 等多种操作系统,无论我们使用哪种操作系统,都可以享受到 VSCode 带来的便利。这使得我们在不同的开发环境中都能够保持一致的开发体验,无需为适应不同的编辑器而花费额外的时间和精力。例如,我们可以在 Windows 系统上进行日常的开发工作,在 Mac 系统上进行项目展示和汇报,在 Linux 服务器上进行代码部署,而始终使用 VSCode 作为主要的开发工具。
配置 VSCode 以进行 Python 数据分析开发
要在 VSCode 中进行 Python 数据分析开发,我们需要进行以下配置:
- 安装 VSCode:首先,从 VSCode 官方网站(Visual Studio Code - Code Editing. Redefined)下载适合自己操作系统的安装包,然后按照安装向导的提示进行安装。安装完成后,打开 VSCode。
- 安装 Python 插件:打开 VSCode 后,点击左侧边栏的 “扩展” 图标(看起来像四个方块组成的正方形),在搜索框中输入 “Python”,然后在搜索结果中找到由 Microsoft 提供的 “Python” 插件,点击 “安装” 按钮进行安装。安装完成后,VSCode 将具备 Python 开发的基本支持,如语法高亮、智能提示等。
- 配置 Python 解释器:安装完 Python 插件后,我们需要告诉 VSCode 使用哪个 Python 解释器来运行我们的代码。打开一个新的或现有的 Python 文件,然后点击 VSCode 窗口底部状态栏中的 Python 版本信息(例如 “Python 3.9.10 64-bit (venv)”),在弹出的列表中选择我们想要使用的 Python 解释器。如果列表中没有我们需要的解释器,可以点击 “Enter interpreter path...” 手动指定解释器的路径。例如,如果我们使用 Anaconda 管理 Python 环境,那么可以在 Anaconda 安装目录下的 “envs” 文件夹中找到对应的环境目录,在该目录下的 “Scripts” 文件夹(Windows 系统)或 “bin” 文件夹(Mac 和 Linux 系统)中找到 “python.exe”(Windows 系统)或 “python3”(Mac 和 Linux 系统)作为解释器路径。
- 安装其他插件:根据我们的具体需求,还可以安装其他与 Python 数据分析和可视化相关的插件。例如,安装 “Jupyter” 插件,以便在 VSCode 中使用 Jupyter Notebook;安装 “Pylance” 插件,提升代码智能感知能力;安装 “Matplotlib Interactive” 插件,实现 Matplotlib 图表的交互式显示等。安装插件的方法与安装 Python 插件类似,在扩展搜索框中输入插件名称,然后点击 “安装” 按钮即可。
- 创建 Python 项目:在 VSCode 中,我们可以通过创建项目文件夹来组织我们的 Python 代码。点击菜单栏中的 “文件” -> “新建文件夹”,选择一个目录来存放我们的 Python 项目。然后在该目录中,右键点击空白处,选择 “新建文件”,将文件保存为以.py 为扩展名的 Python 源文件。例如,我们可以创建一个名为 “data_analysis” 的项目文件夹,在其中创建一个名为 “main.py” 的 Python 文件,用于编写我们的数据分析代码。
- 运行和调试 Python 代码:在编写完 Python 代码后,我们可以通过以下几种方式运行和调试代码:
-
- 运行代码:右键点击编辑器中的代码,选择 “在终端中运行 Python 文件”,VSCode 会在终端中执行我们的 Python 代码,并显示运行结果。也可以使用快捷键 “Ctrl + F5”(Windows 和 Linux 系统)或 “Command + F5”(Mac 系统)来运行代码。
-
- 调试代码:在我们想要设置断点的行号旁边点击,出现一个红点表示断点设置成功。然后点击侧边栏的 “调试” 图标(看起来像一个虫子),在弹出的调试配置列表中选择 “Python 文件”(如果没有该选项,可以点击 “创建配置” 按钮,选择 “Python 文件” 创建一个调试配置)。最后点击调试工具栏中的 “启动调试” 按钮(绿色三角形图标),或者使用快捷键 “F5” 来启动调试会话。在调试过程中,我们可以通过调试面板管理断点、查看变量值、单步执行代码等。例如,在调试一个数据处理函数时,我们可以在函数内部设置断点,然后通过单步执行观察函数的执行过程和变量的变化情况,找出可能存在的问题。
通过以上步骤,我们就可以将 VSCode 配置为一个功能强大的 Python 数据分析开发环境,利用其丰富的插件生态和强大的功能,高效地进行 Python 数据分析和可视化工作。
三、核心库基础
在 Python 数据分析与可视化的领域中,Pandas、NumPy、Matplotlib 和 Seaborn 这几个核心库犹如璀璨的明星,各自发挥着独特而关键的作用,是我们进行数据分析和可视化的得力工具。接下来,让我们深入探索这些库的基础用法,领略它们的强大魅力。
3.1 Pandas
Pandas 是 Python 数据分析的核心支撑,它为我们提供了快速、灵活、明确的数据结构,使我们能够高效地处理和分析各种类型的数据。无论是简单的表格数据,还是复杂的时间序列数据,Pandas 都能轻松应对。
3.1.1 Series 数据结构
Series 是 Pandas 中用于表示一维带标签数组的数据结构,它由一组数据和与之对应的索引组成。可以将其看作是一个列数据,索引则是每一行数据的标识,就像给每个数据点都贴上了独特的标签,方便我们进行数据的定位和操作。
创建 Series 对象非常简单,我们可以通过多种方式来实现。最常见的方式是从 Python 列表或 NumPy 数组创建:
import pandas as pd
import numpy as np# 从列表创建Series
data = [10, 20, 30, 40, 50]
s1 = pd.Series(data)
print(s1)
上述代码中,我们首先导入了 Pandas 库并别名为 pd,然后定义了一个 Python 列表 data,接着使用 pd.Series () 函数将列表转换为 Series 对象 s1。运行代码后,我们可以看到输出的 Series 对象,它不仅包含了数据,还自动生成了从 0 开始的整数索引。
我们还可以从字典创建 Series,此时字典的键将作为索引,值作为数据:
# 从字典创建Series
data_dict = {'a': 100, 'b': 200, 'c': 300, 'd': 400}
s2 = pd.Series(data_dict)
print(s2)
在这段代码中,我们定义了一个字典 data_dict,然后将其传递给 pd.Series () 函数创建了 Series 对象 s2。输出结果中,索引为字典的键 'a'、'b'、'c'、'd',对应的数据分别为 100、200、300、400。
访问 Series 中的数据也很直观,我们可以通过索引来获取单个数据或多个数据:
# 访问单个数据
print(s2['b']) # 访问多个数据
print(s2[['a', 'c']])
在第一行代码中,我们通过索引 'b' 获取了 s2 中对应的数据 200;第二行代码中,我们通过传递一个包含索引 'a' 和 'c' 的列表,获取了这两个索引对应的数据,输出结果是一个包含这两个数据的新 Series 对象。
此外,Series 还支持许多强大的操作方法,比如数学运算、数据过滤、缺失值处理等。例如,我们可以对 Series 进行简单的数学运算:
# Series数学运算
s3 = s2 * 2
print(s3)
这段代码将 s2 中的每个数据都乘以 2,生成了一个新的 Series 对象 s3,展示了 Series 在数学运算方面的便捷性。
3.1.2 DataFrame 数据结构
DataFrame 是 Pandas 中的二维表格型数据结构,它由多个 Series 组成,可以看作是一个由列组成的表格,每一列都是一个 Series,且所有列共享同一索引。DataFrame 的出现,使得我们能够更加方便地处理和分析结构化数据,是 Pandas 库中最为常用的数据结构之一。
创建 DataFrame 的方式同样丰富多样。我们可以从字典创建,字典的键将成为 DataFrame 的列名,值为对应列的数据:
# 从字典创建DataFrame
data = {'姓名': ['张三', '李四', '王五', '赵六'],'年龄': [25, 30, 35, 40],'城市': ['北京', '上海', '广州', '深圳']
}
df = pd.DataFrame(data)
print(df)
在上述代码中,我们定义了一个包含 ' 姓名 '、' 年龄 '、' 城市 ' 三个键的字典 data,然后使用 pd.DataFrame () 函数将其转换为 DataFrame 对象 df。运行代码后,我们可以看到一个规整的表格,列名分别为字典的键,每列的数据对应字典中键的值。
也可以从二维列表创建 DataFrame,并通过 columns 参数指定列名:
# 从二维列表创建DataFrame
data_list = [['张三', 25, '北京'],['李四', 30, '上海'],['王五', 35, '广州'],['赵六', 40, '深圳']
]
df2 = pd.DataFrame(data_list, columns=['姓名', '年龄', '城市'])
print(df2)
这里,我们定义了一个二维列表 data_list,然后使用 pd.DataFrame () 函数创建 DataFrame 对象 df2,并通过 columns 参数明确指定了列名。
对 DataFrame 进行索引、切片和筛选操作是数据分析中常见的任务。通过索引,我们可以获取指定行或列的数据:
# 获取列数据
age_column = df['年龄']
print(age_column)# 获取行数据
row_data = df.loc[2]
print(row_data)
在第一行代码中,我们通过列名 ' 年龄 ' 获取了 df 中的 ' 年龄 ' 列数据,返回的是一个 Series 对象;第二行代码中,我们使用 loc 索引器通过行索引 2 获取了第三行的数据,同样返回的是一个 Series 对象,其索引为列名,值为对应列的数据。
切片操作可以帮助我们获取指定范围的数据:
# 切片操作
subset_df = df.loc[1:3, ['姓名', '城市']]
print(subset_df)
这段代码中,我们使用 loc 索引器进行切片操作,获取了 df 中索引为 1、2、3 的行,以及 ' 姓名 ' 和' 城市 ' 两列的数据,返回的是一个新的 DataFrame 对象。
根据条件筛选数据也是 DataFrame 的重要功能之一,例如筛选出年龄大于 30 岁的行:
# 条件筛选
filtered_df = df[df['年龄'] > 30]
print(filtered_df)
在这段代码中,我们通过布尔索引 df [' 年龄 '] > 30 筛选出了 df 中年龄大于 30 岁的行,返回的是一个新的 DataFrame 对象,只包含满足条件的行数据。
3.1.3 数据读取与写入
在实际数据分析中,我们通常需要从外部文件读取数据,进行处理后再将结果保存到文件中。Pandas 提供了丰富的函数来读取和写入各种常见格式的数据文件,使得数据的输入输出操作变得简单高效。
读取 CSV 文件是数据分析中极为常见的操作,Pandas 的 read_csv () 函数可以轻松完成这一任务:
# 读取CSV文件
data = pd.read_csv('data.csv')
print(data.head())
上述代码中,我们使用 pd.read_csv () 函数读取了名为 'data.csv' 的 CSV 文件,并将其存储为一个 DataFrame 对象 data。通过调用 head () 方法,我们可以查看 DataFrame 的前 5 行数据,以快速了解数据的结构和内容。
读取 Excel 文件也同样便捷,借助 read_excel () 函数即可实现:
# 读取Excel文件
data_excel = pd.read_excel('data.xlsx')
print(data_excel.head())
这里,我们使用 pd.read_excel () 函数读取了名为 'data.xlsx' 的 Excel 文件,并将其转换为 DataFrame 对象 data_excel,同样通过 head () 方法查看前 5 行数据。
当我们完成数据处理后,需要将结果保存到文件中。Pandas 提供了 to_csv () 和 to_excel () 函数来实现数据的保存:
# 将DataFrame保存为CSV文件
data.to_csv('new_data.csv', index=False) # 将DataFrame保存为Excel文件
data_excel.to_excel('new_data.xlsx', index=False)
在第一行代码中,我们使用 to_csv () 函数将 data 保存为名为 'new_data.csv' 的 CSV 文件,并通过 index=False 参数指定不保存行索引;第二行代码中,使用 to_excel () 函数将 data_excel 保存为名为 'new_data.xlsx' 的 Excel 文件,同样不保存行索引。这样,我们就可以方便地将处理后的数据保存下来,以便后续使用或分享。通过这些数据读取与写入的操作,Pandas 为我们搭建了一座连接外部数据和数据分析流程的桥梁,使得数据的获取和保存变得轻松自如。
3.2 NumPy
NumPy 是 Python 科学计算的基础库,它提供了高效的多维数组对象以及丰富的数组操作函数,为 Python 在数据分析、机器学习、科学计算等领域的广泛应用奠定了坚实的基础。NumPy 的数组操作速度极快,这得益于其底层使用 C 语言实现,大大减少了 Python 循环带来的开销,使得我们能够快速处理大规模的数值数据。
3.2.1 数组创建
在 NumPy 中,创建数组是进行后续操作的基础。我们可以通过多种方式创建数组,以满足不同的需求。最直接的方式是从 Python 列表或元组转换:
import numpy as np# 从列表创建一维数组
arr1 = np.array([1, 2, 3, 4, 5])
print(arr1)# 从嵌套列表创建二维数组
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(arr2)
在上述代码中,我们首先导入了 NumPy 库并别名为 np。然后,使用 np.array () 函数从 Python 列表创建了一维数组 arr1,从嵌套列表创建了二维数组 arr2。运行代码后,可以看到输出的数组,它们的数据类型会根据输入数据自动推断。
除了从已有数据结构创建数组,NumPy 还提供了许多函数来创建具有特定特征的数组。例如,使用 arange () 函数创建等差数列数组:
# 使用arange创建等差数列数组
arr3 = np.arange(0, 10, 2)
print(arr3)
这段代码中,np.arange (0, 10, 2) 表示创建一个从 0 开始,到 10 结束(不包含 10),步长为 2 的等差数列数组,运行结果为 [0 2 4 6 8]。
使用 zeros () 和 ones () 函数可以创建全零或全一的数组:
# 创建全零数组
arr4 = np.zeros((3, 4))
print(arr4)# 创建全一数组
arr5 = np.ones((2, 3))
print(arr5)
在第一行代码中,np.zeros ((3, 4)) 创建了一个形状为 (3, 4) 的全零数组,即 3 行 4 列,每个元素都是 0;第二行代码中,np.ones ((2, 3)) 创建了一个 2 行 3 列的全一数组。
另外,使用 random 模块可以创建随机数数组,为数据分析和模拟实验提供了便利:
# 创建随机数数组
arr6 = np.random.rand(2, 3)
print(arr6)
这里,np.random.rand (2, 3) 创建了一个 2 行 3 列的数组,数组中的元素是在 0 到 1 之间均匀分布的随机数。
3.2.2 数组操作
NumPy 数组支持丰富多样的操作,这些操作是进行数据分析和科学计算的核心。基本运算如加法、减法、乘法、除法等可以直接对数组进行,而且是元素级别的运算:
# 数组基本运算
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = a + b
print(c)
上述代码中,我们定义了两个一维数组 a 和 b,然后进行加法运算 a + b,得到的结果 c 是一个新的数组,其每个元素是 a 和 b 对应元素之和。
索引和切片操作与 Python 列表类似,但在多维数组中更加灵活:
# 数组索引和切片
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr[1, 2])
print(arr[0:2, 1:3])
在第一行代码中,arr [1, 2] 表示获取二维数组 arr 中第二行(索引从 0 开始)第三列的元素,结果为 6;第二行代码中,arr [0:2, 1:3] 表示获取 arr 中前两行(索引 0 和 1),第二列和第三列(索引 1 和 2)的子数组,返回的是一个形状为 (2, 2) 的二维数组。
广播机制是 NumPy 的一大特色,它允许不同形状的数组进行运算,在满足一定条件下,较小的数组会自动扩展以匹配较大数组的形状:
# 广播机制
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([10, 20, 30])
c = a + b
print(c)
这里,数组 b 的形状为 (3,),数组 a 的形状为 (2, 3),在进行加法运算 a + b 时,由于 b 的形状可以通过广播扩展为 (2, 3),因此可以顺利进行运算,结果 c 是一个形状为 (2, 3) 的数组,其元素是 a 和 b 对应元素之和。广播机制极大地简化了数组运算,提高了代码的简洁性和效率,是 NumPy 强大功能的重要体现。
3.3 Matplotlib
Matplotlib 是 Python 最常用的绘图库之一,它提供了一套简洁、直观的 API,使得我们能够轻松创建各种类型的高质量图表,将数据以可视化的形式呈现出来,帮助我们更好地理解数据背后的信息和趋势。无论是简单的折线图、散点图,还是复杂的多子图组合,Matplotlib 都能胜任。
3.3.1 基本绘图
Matplotlib 的基本绘图函数非常简单易用,通过几行代码就能创建出常见的图表类型。以绘制折线图为例:
import matplotlib.pyplot as plt
import numpy as np# 生成数据
x = np.arange(0, 10, 0.1)
y = np.sin(x)# 绘制折线图
plt.plot(x, y)
plt.show()
在上述代码中,我们首先导入了 Matplotlib 的 pyplot 模块并别名为 plt,以及 NumPy 库。然后,使用 np.arange () 函数生成了一组 x 数据,范围是从 0 到 10(不包含 10),步长为 0.1,接着计算出对应的 y 数据(这里是正弦值)。最后,使用 plt.plot () 函数绘制折线图,将 x 和 y 数据作为参数传入,再调用 plt.show () 函数显示图表。运行代码后,我们可以看到一个展示正弦函数曲线的折线图。
绘制散点图同样简单,使用 scatter () 函数即可:
# 生成数据
x = np.random.rand(50)
y = np.random.rand(50)# 绘制散点图
plt.scatter(x, y)
plt.show()
这段代码中,我们使用 np.random.rand () 函数生成了两组随机数作为 x 和 y 数据,然后使用 plt.scatter () 函数绘制散点图,展示了这些随机点的分布情况。
柱状图可以使用 bar () 函数绘制,用于比较不同类别或组的数据:
# 数据
categories = ['A', 'B', 'C', 'D']
values = [25, 40, 15, 30]# 绘制柱状图
plt.bar(categories, values)
plt.show()
在这段代码中,我们定义了类别列表 categories 和对应的值列表 values,然后使用 plt.bar () 函数绘制柱状图,每个类别对应一个柱子,柱子的高度表示对应的值。运行代码后,我们可以直观地比较不同类别数据的大小。
Matplotlib 还支持对图表的外观进行设置,如颜色、标记、线型等,使图表更加美观和富有表现力:
# 生成数据
x = np.arange(0, 10, 0.1)
y1 = np.sin(x)
y2 = np.cos(x)# 绘制折线图并设置颜色、标记和线型
plt.plot(x, y1, color='red', marker='o', linestyle='--', label='Sin')
plt.plot(x, y2, color='blue', marker='s', linestyle='-.', label='Cos')
plt.legend()
plt.show()
在这段代码中,我们分别绘制了正弦函数 y1 和余弦函数 y2 的折线图,并通过参数设置了颜色(color)、标记(marker)和线型(linestyle)。同时,使用 label 参数为每条曲线添加了标签,最后调用 plt.legend () 函数显示图例,以便区分不同的曲线。这样,我们就创建了一个更加丰富和易读的图表。
3.3.2 图表定制
为了使图表更加清晰和易于理解,我们可以对图表进行各种定制,包括添加标题、轴标签、刻度、图例等。添加标题可以使用 title () 函数,轴标签可以通过 xlabel () 和 ylabel () 函数添加:
# 生成数据
x = np.arange(0, 10, 0.1)
y = np.sin(x)# 绘制折线图
plt.plot(x, y)# 添加标题和轴标签
plt.title('Sine Function')
plt.xlabel('X')
plt.ylabel('Sin(X)')
plt.show()
四、数据获取
在 Python 数据分析与可视化的旅程中,数据获取是第一步,也是至关重要的一步。就像厨师需要新鲜的食材才能烹饪出美味佳肴一样,我们需要获取高质量的数据,才能进行有效的分析和可视化展示。数据的来源多种多样,下面将介绍从文件、数据库和网络中获取数据的常见方法。
4.1 从文件读取数据
在数据分析中,我们经常会遇到各种格式的文件,如 CSV、Excel、JSON 等,Pandas 库为我们提供了便捷的函数来读取这些文件中的数据。
CSV 文件:CSV(Comma-Separated Values)是一种常见的文本文件格式,以逗号分隔字段,常用于存储表格数据。使用 Pandas 的 read_csv () 函数可以轻松读取 CSV 文件,将其转换为 DataFrame 对象,方便后续处理。
import pandas as pd# 读取CSV文件
data_csv = pd.read_csv('data.csv')
print(data_csv.head()) # 查看前5行数据
上述代码中,我们使用 pd.read_csv () 函数读取了名为 'data.csv' 的文件,并将其存储为 DataFrame 对象 data_csv。通过调用 head () 方法,我们可以快速查看数据的前 5 行,了解数据的结构和内容。read_csv () 函数还有许多参数可以设置,以满足不同的读取需求。例如,sep 参数可以指定字段分隔符,header 参数可以指定作为列名的行,index_col 参数可以指定作为行索引的列等。如果 CSV 文件使用分号作为分隔符,我们可以这样设置参数:
data_csv = pd.read_csv('data.csv', sep=';')
Excel 文件:Excel 文件是另一种常见的数据存储格式,它具有丰富的格式设置和数据处理功能。Pandas 的 read_excel () 函数可以读取 Excel 文件中的数据。在使用该函数之前,需要确保安装了 openpyxl 或 xlrd 库,分别用于处理.xlsx 和.xls 格式的文件。
# 读取Excel文件(.xlsx格式)
data_excel = pd.read_excel('data.xlsx', engine='openpyxl')
print(data_excel.head())# 读取特定工作表(假设工作表名为'Sheet2')
data_sheet2 = pd.read_excel('data.xlsx', sheet_name='Sheet2', engine='openpyxl')
print(data_sheet2.head())
在上述代码中,我们首先使用 read_excel () 函数读取了名为 'data.xlsx' 的文件,并通过 engine='openpyxl' 指定使用 openpyxl 库来处理。然后,通过 sheet_name 参数指定读取名为 'Sheet2' 的工作表。如果想查看所有工作表的名字,可以使用以下代码:
with pd.ExcelFile('data.xlsx') as xls:print(xls.sheet_names)
JSON 文件:JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于在不同的应用程序之间传输数据。Pandas 的 read_json () 函数可以将 JSON 数据读取为 DataFrame 对象。
# 读取JSON文件
data_json = pd.read_json('data.json')
print(data_json.head())
上述代码中,我们使用 read_json () 函数读取了名为 'data.json' 的文件,并将其转换为 DataFrame 对象 data_json。read_json () 函数支持从 JSON 文件、JSON 字符串或 JSON 网址中加载数据,并且可以通过 orient 参数指定 JSON 数据的结构方式,常见的值有'split'、'records'、'index'、'columns'、'values' 等。例如,从 JSON 字符串加载数据并指定 orient 为 'records':
import pandas as pd# JSON字符串
json_data = '''[{"Name": "Alice", "Age": 25, "City": "New York"},{"Name": "Bob", "Age": 30, "City": "Los Angeles"},{"Name": "Charlie", "Age": 35, "City": "Chicago"}
]'''# 从JSON字符串读取数据,指定orient='records'
df = pd.read_json(json_data, orient='records')
print(df)
4.2 从数据库获取数据
数据库是存储和管理大量数据的重要工具,在实际应用中,我们经常需要从数据库中获取数据进行分析。Python 提供了多种库来连接和操作常见的数据库,如 MySQL、SQLite 等。
MySQL 数据库:MySQL 是一种广泛使用的关系型数据库,使用 Python 连接 MySQL 数据库并获取数据,通常可以使用 pymysql 库。在使用之前,需要先安装该库,可以使用 pip 命令进行安装:
pip install pymysql
安装完成后,以下是一个连接 MySQL 数据库并查询数据的示例:
import pymysql# 建立数据库连接
try:connection = pymysql.connect(host="localhost", # 主机地址port=3306, # 端口号user="your_username", # 用户名password="your_password", # 密码database="your_database", # 数据库名称charset="utf8" # 编码)if connection.open:print("成功连接到MySQL数据库")# 创建游标对象with connection.cursor() as cursor:# 执行查询操作select_query = "SELECT * FROM your_table"cursor.execute(select_query)# 获取所有查询结果results = cursor.fetchall()# 打印查询结果print("查询结果:")for row in results:print(row)except pymysql.Error as e:print(f"连接数据库时出错: {e}")finally:if connection.open:connection.close()print("数据库连接已关闭")
在上述代码中,我们首先使用 pymysql.connect () 方法建立与 MySQL 数据库的连接,需要提供主机地址、端口号、用户名、密码、数据库名称和编码等信息。然后,通过 connection.cursor () 创建一个游标对象,用于执行 SQL 语句。接着,执行 SELECT 语句查询指定表中的所有数据,并使用 fetchall () 方法获取所有查询结果。最后,在操作完成后,关闭数据库连接。
SQLite 数据库:SQLite 是一种轻量级的嵌入式数据库,它不需要独立的服务器进程,非常适合小型应用程序和快速开发。Python 内置了 sqlite3 模块,用于连接和操作 SQLite 数据库。
import sqlite3# 连接到SQLite数据库(如果数据库不存在,将创建一个新数据库)
conn = sqlite3.connect('example.db')# 创建一个游标对象
cursor = conn.cursor()# 执行SQL查询
cursor.execute("SELECT * FROM your_table")# 获取所有记录
rows = cursor.fetchall()# 遍历并打印记录
for row in rows:print(row)# 关闭游标和连接
cursor.close()
conn.close()
在上述代码中,我们使用 sqlite3.connect () 方法连接到名为 'example.db' 的 SQLite 数据库,如果数据库不存在,将创建一个新的数据库。然后,创建游标对象并执行 SQL 查询,使用 fetchall () 方法获取所有查询结果,最后关闭游标和数据库连接。
4.3 网络数据获取
随着互联网的发展,网络成为了丰富的数据来源。我们可以通过网络获取各种类型的数据,如网页内容、API 数据等。下面将介绍使用 requests 库获取网页数据以及网页爬虫的基础知识。
4.3.1 使用 requests 库
requests 库是 Python 中用于发送 HTTP 请求的常用库,它提供了简单易用的 API,使得我们能够轻松地与网页进行交互,获取网页数据。
发送 HTTP GET 请求是最常见的操作之一,通过 requests.get () 函数可以实现。例如,获取百度首页的内容:
import requests# 发送GET请求
response = requests.get('https://www.baidu.com')# 检查响应状态码
if response.status_code == 200:print("请求成功")print(response.text) # 打印网页内容
else:print(f"请求失败,状态码: {response.status_code}")
在上述代码中,我们使用 requests.get () 函数向'百度一下,你就知道' 发送 GET 请求,并将响应结果存储在 response 变量中。通过检查 response.status_code 属性,可以判断请求是否成功,如果状态码为 200,表示请求成功,此时可以通过 response.text 属性获取网页的文本内容。
有时,我们需要在请求中传递参数。例如,在百度搜索框中搜索关键词,可以通过 params 参数传递搜索关键词:
import requests# 搜索关键词
keyword = "Python数据分析"# 发送GET请求并传递参数
response = requests.get('https://www.baidu.com/s', params={'wd': keyword})# 检查响应状态码
if response.status_code == 200:print("请求成功")print(response.url) # 打印请求的URL
else:print(f"请求失败,状态码: {response.status_code}")
在上述代码中,我们通过 params 参数传递了一个字典 {'wd': keyword},其中 'wd' 是百度搜索的参数名,keyword 是搜索关键词。发送请求后,通过 response.url 可以查看实际请求的 URL,其中包含了我们传递的参数。
4.3.2 网页爬虫基础
网页爬虫是一种自动获取网页内容的程序,它通过模拟浏览器行为,按照一定的规则遍历网页,提取所需的数据。网页爬虫在数据采集、搜索引擎优化、市场调研等领域有着广泛的应用。
网页爬虫的基本原理是通过发送 HTTP 请求获取网页的 HTML 内容,然后使用解析库(如 BeautifulSoup、lxml 等)对 HTML 进行解析,提取出我们需要的数据。下面是一个使用 requests 和 BeautifulSoup 库编写的简单爬虫示例,用于获取豆瓣电影 Top250 的电影名称和评分:
import requests
from bs4 import BeautifulSoup# 发送GET请求获取网页内容
url = 'https://movie.douban.com/top250'
response = requests.get(url)# 检查响应状态码
if response.status_code == 200:# 使用BeautifulSoup解析HTMLsoup = BeautifulSoup(response.text, 'html.parser')# 找到所有电影条目movie_items = soup.find_all('div', class_='item')# 遍历电影条目,提取电影名称和评分for item in movie_items:title = item.find('span', class_='title').textrating = item.find('span', class_='rating_num').textprint(f"电影名称: {title}, 评分: {rating}")else:print(f"请求失败,状态码: {response.status_code}")
在上述代码中,我们首先使用 requests.get () 函数获取豆瓣电影 Top250 页面的内容。然后,使用 BeautifulSoup 库对获取到的 HTML 内容进行解析,通过 find_all () 方法找到所有包含电影信息的 div 标签,其 class 属性为 'item'。接着,在每个电影条目中,使用 find () 方法找到电影名称和评分对应的 span 标签,并提取其文本内容。最后,打印出电影名称和评分。
需要注意的是,在进行网页爬虫时,要遵守网站的使用规则和法律法规,不要对网站造成过大的负担,避免侵犯他人的权益。同时,一些网站可能会采取反爬虫措施,如限制访问频率、检测爬虫行为等,我们需要根据实际情况进行相应的处理,如设置合理的请求头、添加随机延迟等,以确保爬虫的正常运行。
五、数据清洗与预处理
在数据分析的过程中,原始数据往往存在各种各样的问题,如缺失值、异常值、重复值等,这些问题会严重影响数据分析的准确性和可靠性。因此,在进行数据分析之前,我们需要对数据进行清洗和预处理,将原始数据转换为干净、整齐、可用的数据。下面将详细介绍数据清洗与预处理的常见方法和操作。
5.1 缺失值处理
缺失值是指数据集中某些数据点的数值缺失或未被记录。缺失值的存在可能会导致数据分析结果的偏差,因此需要对其进行处理。
5.1.1 检测缺失值
在 Pandas 中,我们可以使用 isnull () 或 isna () 方法来检测数据集中的缺失值,这两个方法的功能相同,只是名称不同。它们会返回一个布尔值的 DataFrame 或 Series,表示每个元素是否为缺失值。
import pandas as pd# 创建一个包含缺失值的DataFrame
data = {'A': [1, 2, None, 4],'B': [5, None, None, 8],'C': [9, 10, 11, 12]}
df = pd.DataFrame(data)# 检测缺失值
print(df.isnull())
运行上述代码,输出结果如下:
A B C
0 False False False
1 False True False
2 True True False
3 False False False
可以看到,对于每个元素,如果是缺失值则返回 True,否则返回 False。
为了统计每列的缺失值数量,可以使用 sum () 方法:
print(df.isnull().sum())
输出结果为:
A 1
B 2
C 0
dtype: int64
这样我们就可以清楚地知道每列中缺失值的个数。
5.1.2 删除缺失值
当数据集中缺失值较少时,我们可以选择直接删除含有缺失值的行或列。在 Pandas 中,使用 dropna () 方法来实现这一操作。
# 删除包含缺失值的行
df_drop_rows = df.dropna()
print(df_drop_rows)# 删除包含缺失值的列
df_drop_cols = df.dropna(axis=1)
print(df_drop_cols)
在上述代码中,dropna () 方法默认删除含有缺失值的行(axis=0),通过设置 axis=1 可以删除含有缺失值的列。运行代码后,我们可以看到删除缺失值后的 DataFrame。
dropna () 方法还有其他参数可以设置,例如:
- how='any':只要有一个缺失值就删除(默认)。
- how='all':只有当所有值都是缺失值时才删除。
- thresh=n:至少有 n 个非缺失值才保留。
5.1.3 填充缺失值
除了删除缺失值,我们还可以使用指定值、统计量(如均值、中位数)等方法来填充缺失值,以保留数据集中的信息。在 Pandas 中,使用 fillna () 方法进行填充。
# 用指定的值填充缺失值
df_fill_value = df.fillna(0)
print(df_fill_value)# 用均值填充缺失值
df_fill_mean = df.fillna(df.mean())
print(df_fill_mean)# 用前一个非缺失值填充(前向填充)
df_ffill = df.fillna(method='ffill')
print(df_ffill)# 用后一个非缺失值填充(后向填充)
df_bfill = df.fillna(method='bfill')
print(df_bfill)
在上述代码中,首先使用 fillna (0) 将缺失值填充为 0;然后使用 df.mean () 计算每列的均值,并将缺失值填充为均值;接着使用 method='ffill' 进行前向填充,即使用前一个非缺失值填充当前缺失值;最后使用 method='bfill' 进行后向填充,即使用后一个非缺失值填充当前缺失值。运行代码后,可以看到不同填充方法得到的结果。
5.2 异常值处理
异常值是指数据集中与其他数据点显著不同的数据点,它们可能是由于数据录入错误、测量误差或其他原因导致的。异常值的存在可能会对数据分析和模型训练产生较大的影响,因此需要对其进行处理。
5.2.1 检测异常值
检测异常值的方法有很多种,下面介绍两种常用的统计方法:箱线图和 Z-Score。
- 箱线图:箱线图是一种基于统计的图形化方法,通过可视化数据的分布情况来识别异常值。它展示了数据的最小值、第一四分位数(Q1)、中位数(Q2)、第三四分位数(Q3)和最大值。异常值通常定义为超出 1.5 倍 IQR(四分位距,IQR = Q3 - Q1)范围的数据点。
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np# 生成示例数据
data = np.random.normal(100, 10, 100)
data = np.append(data, [150, 160, 200]) # 添加几个异常值
df = pd.DataFrame({'data': data})# 绘制箱线图
plt.figure(figsize=(10, 6))
sns.boxplot(data=df['data'])
plt.title('Boxplot for Outlier Detection')
plt.show()
运行上述代码,会生成一个箱线图,超出上下边界的数据点即为异常值,通过观察箱线图,我们可以直观地识别出异常值。
- Z-Score:Z-Score 是一种基于标准差的异常值检测方法。它通过计算每个数据点与均值的标准差偏离程度来判断是否为异常值。Z-Score 的计算公式为:Z = (X - μ) / σ,其中 X 是数据点,μ 是均值,σ 是标准差。通常情况下,Z-Score 的绝对值大于 3 的数据点被视为异常值。
import numpy as np
import pandas as pd# 示例数据
data = np.array([10, 12, 12, 13, 12, 13, 14, 14, 14, 15, 16, 18, 19, 20, 30])
df = pd.DataFrame({'data': data})# 计算均值和标准差
mean = df['data'].mean()
std_dev = df['data'].std()# 计算Z-Score
df['z_score'] = (df['data'] - mean) / std_dev# 识别异常值
threshold = 3
outliers = df[df['z_score'].abs() > threshold]
print(outliers)
在上述代码中,首先计算数据的均值和标准差,然后计算每个数据点的 Z-Score,最后通过设置阈值(这里为 3)来识别异常值。运行代码后,会输出检测到的异常值。
5.2.2 处理异常值
对于检测到的异常值,可以采取以下几种处理方式:
- 修正异常值:如果异常值是由于数据录入错误等原因导致的,可以根据实际情况进行修正。例如,将一个明显错误的年龄值(如 200 岁)修正为合理的值。
- 删除异常值:当异常值对分析结果影响较大且无法修正时,可以选择删除异常值。使用 drop () 方法可以删除 DataFrame 中指定的行。
# 删除异常值
df = df[df['z_score'].abs() <= threshold]
print(df)
在上述代码中,通过布尔索引删除了 Z-Score 绝对值大于阈值的行,即删除了异常值。
- 转换异常值:可以对异常值进行转换,使其对分析结果的影响减小。例如,对数据进行对数变换,将异常值的影响分散到整个数据集中。
import numpy as np
import pandas as pd# 示例数据
data = np.array([10, 12, 12, 13, 12, 13, 14, 14, 14, 15, 16, 18, 19, 20, 30])
df = pd.DataFrame({'data': data})# 对数据进行对数变换
df['log_data'] = np.log(df['data'])
print(df)
在上述代码中,使用 np.log () 函数对数据进行对数变换,得到了一个新的列 'log_data',这样可以在一定程度上减小异常值的影响。
5.3 重复值处理
重复值是指数据集中完全相同或部分相同的记录。重复值的存在会占用存储空间,影响数据分析的效率和准确性,因此需要对其进行处理。
在 Pandas 中,可以使用 duplicated () 方法检测数据集中的重复行,该方法会返回一个布尔值的 Series,表示每行是否为重复行(True 表示是重复行,False 表示不是重复行)。使用 drop_duplicates () 方法可以删除重复行。
import pandas as pd# 创建一个包含重复值的DataFrame
data = {'A': [1, 2, 2, 4],'B': [5, 6, 6, 8],'C': [9, 10, 10, 12]}
df = pd.DataFrame(data)# 检测重复值
print(df.duplicated())# 删除重复值
df = df.drop_duplicates()
print(df)
在上述代码中,首先使用 duplicated () 方法检测重复值,然后使用 drop_duplicates () 方法删除重复值。运行代码后,可以看到检测结果和删除重复值后的 DataFrame。
drop_duplicates () 方法也有一些参数可以设置,例如:
- subset:指定要检查的列,只检查指定列是否重复。
- keep:指定保留哪一行,'first' 表示保留第一次出现的行(默认),'last' 表示保留最后一次出现的行,False 表示删除所有重复行。
5.4 数据转换
数据转换是将数据从一种格式或表示形式转换为另一种格式或表示形式的过程,以满足数据分析和建模的需求。常见的数据转换操作包括数据类型转换、数据标准化与归一化等。
5.4.1 数据类型转换
在数据分析中,有时需要将数据从一种类型转换为另一种类型。例如,将字符串类型的数值转换为数值类型,以便进行数学运算。在 Pandas 中,可以使用 astype () 方法进行数据类型转换。
import pandas as pd# 创建一个包含字符串类型数值的DataFrame
data = {'A': ['1', '2', '3', '4'],'B': ['5', '6', '7', '8']}
df = pd.DataFrame(data)# 将列A转换为整数类型
df['A'] = df['A'].astype(int)
print(df.dtypes)
在上述代码中,使用 astype (int) 将列 'A' 的数据类型从字符串转换为整数。运行代码后,可以看到列 'A' 的数据类型已经变为 int64。
除了基本的数据类型转换,还可以进行日期时间类型的转换。例如,将字符串类型的日期转换为 Pandas 的日期时间类型,以便进行日期时间相关的操作。
import pandas as pd# 创建一个包含字符串类型日期的DataFrame
data = {'日期': ['2023-01-01', '2023-01-02', '2023-01-03']}
df = pd.DataFrame(data)# 将列'日期'转换为日期时间类型
df['日期'] = pd.to_datetime(df['日期'])
print(df.dtypes)
在上述代码中,使用 pd.to_datetime () 将列 ' 日期 ' 的字符串类型转换为日期时间类型。运行代码后,可以看到列 ' 日期 ' 的数据类型已经变为 datetime64 [ns]。
5.4.2 数据标准化与归一化
数据标准化和归一化是将数据转换为统一尺度的过程,有助于提高数据分析和机器学习模型的性能。
- 数据标准化(Z-Score 标准化):标准化是依照特征矩阵的列处理数据,通过特征的平均值和标准差,将特征缩放成一个标准的正态分布,缩放后均值为 0,方差为 1。标准化的公式为:\(x' = \frac{x - \mu}{\sigma}\),其中\(x\)是原始数据值,\(x'\)是标准化后的数据值,\(\mu\)是均值,\(\sigma\)是标准差。
import numpy as np
from sklearn.preprocessing import StandardScaler# 示例数据
data = np.array([[10, 10, 15, 10],[5, 1, 21, 5],[1, 2, 15, 12]])# 创建StandardScaler对象
scaler = StandardScaler()# 对数据进行标准化
scaled_data = scaler.fit_transform(data)
print(scaled_data)
在上述代码中,使用 scikit-learn 库中的 StandardScaler 对数据进行标准化。首先创建 StandardScaler 对象,然后使用 fit_transform () 方法对数据进行拟合和转换。运行代码后,可以看到标准化后的数据。
- 数据归一化(Min-Max 归一化):归一化是利用特征的最大值和最小值,将特征缩放到 [0, 1] 区间。归一化的公式为:\(x' = \frac{x - min}{max - min}\),其中\(x\)是原始数据值,\(x'\)是归一化后的数据值,\(min\)是最小值,\(max\)是最大值。
import numpy as np
from sklearn.preprocessing import MinMaxScaler# 示例数据
data = np.array([[10, 10, 15, 10],[5, 1, 21, 5],[1, 2, 15, 12]])# 创建MinMaxScaler对象
scaler = MinMaxScaler()# 对数据进行归一化
normalized_data = scaler.fit_transform(data)
print(normalized_data)
在上述代码中,使用 scikit-learn 库中的 MinMaxScaler 对数据进行归一化。首先创建 MinMaxScaler 对象,然后使用 fit_transform () 方法对数据进行拟合和转换。运行代码后,可以看到归一化后的数据。
标准化和归一化的选择取决于具体的应用场景。一般来说,当数据存在异常值或数据分布未知时,标准化更为合适,因为它对异常值不敏感;当数据的最大值和最小值已知,且需要将数据缩放到特定范围时,归一化更为适用。
六、数据分析与建模
6.1 描述性统计分析
描述性统计分析是数据分析的基础环节,它通过计算数据的一些基本统计量,帮助我们快速了解数据的整体特征和分布情况。在 Python 中,Pandas 库为我们提供了丰富的函数和方法来进行描述性统计分析。
计算均值是描述性统计中常用的操作之一,它可以反映数据的集中趋势。使用 Pandas 的mean()方法可以轻松计算 DataFrame 或 Series 的均值。假设我们有一个包含学生成绩的 DataFrame:
import pandas as pd# 创建示例数据
data = {'学生姓名': ['张三', '李四', '王五', '赵六'],'数学成绩': [85, 90, 78, 95],'语文成绩': [76, 88, 82, 90]
}
df = pd.DataFrame(data)# 计算数学成绩的均值
math_mean = df['数学成绩'].mean()
print(f'数学成绩的均值为: {math_mean}')# 计算所有成绩的均值
all_mean = df[['数学成绩', '语文成绩']].mean()
print(f'所有成绩的均值为:\n{all_mean}')
上述代码中,首先通过df['数学成绩'].mean()计算了 ' 数学成绩 ' 列的均值,然后通过df[['数学成绩', '语文成绩']].mean()计算了 ' 数学成绩 ' 和' 语文成绩 ' 两列的均值,并将结果打印输出。
中位数是将数据从小到大排序后,位于中间位置的数值(如果数据个数为奇数)或中间两个数的平均值(如果数据个数为偶数)。中位数可以避免极端值对数据集中趋势的影响。使用median()方法可以计算中位数:
# 计算数学成绩的中位数
math_median = df['数学成绩'].median()
print(f'数学成绩的中位数为: {math_median}')
运行上述代码,即可得到 ' 数学成绩 ' 列的中位数。
标准差用于衡量数据的离散程度,标准差越大,说明数据的离散程度越大,数据越分散;标准差越小,说明数据越集中。使用std()方法计算标准差:
# 计算数学成绩的标准差
math_std = df['数学成绩'].std()
print(f'数学成绩的标准差为: {math_std}')
通过上述代码,我们可以得到 ' 数学成绩 ' 列的标准差,从而了解该列数据的离散情况。
分位数是描述性统计中的重要概念,它可以帮助我们了解数据在不同位置的分布情况。常见的分位数有四分位数(25%、50%、75% 分位数)、百分位数等。使用quantile()方法可以计算分位数:
# 计算数学成绩的25%分位数
math_25_quantile = df['数学成绩'].quantile(0.25)
print(f'数学成绩的25%分位数为: {math_25_quantile}')# 计算数学成绩的75%分位数
math_75_quantile = df['数学成绩'].quantile(0.75)
print(f'数学成绩的75%分位数为: {math_75_quantile}')
上述代码分别计算了 ' 数学成绩 ' 列的 25% 分位数和 75% 分位数,通过这些分位数,我们可以更全面地了解数学成绩的分布情况。
除了上述单个统计量的计算,Pandas 还提供了describe()方法,该方法可以一次性计算出 DataFrame 中所有数值列的多个描述性统计量,包括计数、均值、标准差、最小值、25% 分位数、50% 分位数(中位数)、75% 分位数和最大值,非常方便快捷:
# 计算所有数值列的描述性统计量
desc_stats = df[['数学成绩', '语文成绩']].describe()
print(f'所有数值列的描述性统计量为:\n{desc_stats}')
运行上述代码,将会输出一个包含所有数值列描述性统计量的 DataFrame,我们可以直观地看到数据的各种特征。通过这些描述性统计分析,我们能够对数据有一个初步的了解,为后续更深入的数据分析和建模提供基础。
6.2 相关性分析
在数据分析中,了解数据特征之间的相关性是非常重要的,它可以帮助我们发现数据之间的潜在关系,为进一步的分析和决策提供依据。Python 中的 Pandas 和 Seaborn 库提供了强大的工具来计算和可视化数据特征之间的相关性。
使用 Pandas 计算相关性非常简单,通过corr()方法可以计算 DataFrame 中数值列之间的皮尔逊相关系数。皮尔逊相关系数是一种常用的度量两个变量之间线性相关程度的指标,其取值范围在 - 1 到 1 之间,值越接近 1 表示正相关性越强,值越接近 -1 表示负相关性越强,值接近 0 表示相关性较弱。
import pandas as pd# 创建示例数据
data = {'数学成绩': [85, 90, 78, 95, 88],'语文成绩': [76, 88, 82, 90, 85],'英语成绩': [80, 85, 70, 92, 86]
}
df = pd.DataFrame(data)# 计算相关性矩阵
corr_matrix = df.corr()
print(corr_matrix)
上述代码中,首先创建了一个包含 ' 数学成绩 '、' 语文成绩 ' 和' 英语成绩 ' 的 DataFrame,然后使用df.corr()计算了各成绩之间的相关性矩阵。输出的相关性矩阵中,对角线上的值都为 1,因为每个变量与自身的相关性是完全相关的;其他位置的值表示对应两个变量之间的相关系数。
为了更直观地展示相关性,我们可以使用 Seaborn 库绘制相关性热图。热图通过颜色的深浅来表示相关性的强弱,使我们能够一目了然地看出各个变量之间的关系。
import seaborn as sns
import matplotlib.pyplot as plt# 绘制相关性热图
plt.figure(figsize=(8, 6))
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm')
plt.title('成绩相关性热图')
plt.show()
在上述代码中,首先导入了 Seaborn 库和 Matplotlib 库的pyplot模块。然后使用plt.figure()设置图形大小,接着使用sns.heatmap()绘制相关性热图,其中annot=True表示在热图上显示相关系数的值,cmap='coolwarm'指定了颜色映射方案,使相关性强的区域颜色更深,相关性弱的区域颜色更浅。最后,使用plt.title()添加标题,并通过plt.show()显示图形。运行代码后,我们可以看到一个直观的相关性热图,通过颜色和数值可以清晰地了解各成绩之间的相关性强弱。例如,如果数学成绩和英语成绩的相关系数较高且颜色较深,说明这两门成绩之间存在较强的正相关关系;如果相关系数接近 0 且颜色较浅,说明它们之间的相关性较弱。通过这种方式,我们能够快速发现数据特征之间的潜在关系,为数据分析和决策提供有力支持。
6.3 数据分组与聚合
数据分组与聚合是数据分析中常用的操作,它可以帮助我们按照不同的维度对数据进行汇总分析,从而发现数据在不同分组下的特征和规律。在 Python 中,Pandas 库提供了强大的groupby功能来实现数据分组与聚合操作。
使用groupby方法可以根据一个或多个列对 DataFrame 进行分组,然后对每个组应用聚合函数。假设我们有一个包含销售数据的 DataFrame,其中包含 ' 地区 '、' 产品 ' 和' 销售额 ' 等列,我们想要按 ' 地区 ' 分组,计算每个地区的总销售额。
import pandas as pd# 创建示例数据
data = {'地区': ['华北', '华东', '华北', '华东', '华南'],'产品': ['A', 'B', 'A', 'C', 'B'],'销售额': [100, 150, 120, 90, 180]
}
df = pd.DataFrame(data)# 按地区分组,计算每个地区的总销售额
grouped_sales = df.groupby('地区')['销售额'].sum()
print(grouped_sales)
上述代码中,首先使用df.groupby('地区')按 ' 地区 ' 列对 DataFrame 进行分组,然后通过['销售额'].sum()对每个分组中的 ' 销售额 ' 列应用sum聚合函数,计算每个地区的总销售额。输出结果是一个以 ' 地区 ' 为索引,总销售额为值的 Series 对象,我们可以清晰地看到每个地区的销售总额情况。
我们还可以按多个列进行分组,例如,按 ' 地区 ' 和' 产品 ' 分组,计算每个地区每种产品的平均销售额。
# 按地区和产品分组,计算每个地区每种产品的平均销售额
grouped_avg_sales = df.groupby(['地区', '产品'])['销售额'].mean()
print(grouped_avg_sales)
在这段代码中,df.groupby(['地区', '产品'])按 ' 地区 ' 和' 产品 ' 两列进行分组,然后对每个分组中的 ' 销售额 ' 列应用mean聚合函数,计算平均销售额。输出结果是一个具有层次化索引的 Series 对象,第一级索引为 ' 地区 ',第二级索引为 ' 产品 ',对应的值为每个地区每种产品的平均销售额。这样,我们可以更细致地了解不同地区不同产品的销售情况。
除了常用的聚合函数如sum、mean外,Pandas 还支持其他聚合函数,如count(计数)、max(最大值)、min(最小值)等。我们可以同时应用多个聚合函数进行分析。
# 按地区分组,同时计算每个地区销售额的总和、平均值、最大值和最小值
grouped_multi_stats = df.groupby('地区')['销售额'].agg(['sum', 'mean','max','min'])
print(grouped_multi_stats)
上述代码中,df.groupby('地区')['销售额'].agg(['sum', 'mean','max','min'])按 ' 地区 ' 分组后,对 ' 销售额 ' 列同时应用了sum、mean、max和min四个聚合函数。agg方法接受一个函数列表,用于对每个分组的数据进行多个聚合操作。输出结果是一个 DataFrame 对象,列名为聚合函数名,行索引为 ' 地区 ',展示了每个地区销售额的多种统计信息,为我们提供了更全面的数据分析视角。通过数据分组与聚合操作,我们能够从不同维度深入分析数据,挖掘数据背后的信息和规律,为业务决策提供有力的数据支持。
6.4 机器学习基础与建模
6.4.1 机器学习简介
机器学习是一门多领域交叉学科,它涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科,旨在让计算机通过数据学习模式和规律,并利用这些模式和规律进行预测和决策。机器学习在当今数字化时代发挥着至关重要的作用,广泛应用于各个领域,如金融领域的风险评估与预测、医疗领域的疾病诊断与预测、电商领域的推荐系统、图像识别领域的人脸识别和物体检测等。
机器学习主要分为以下几类:
- 监督学习:监督学习是最常见的机器学习类型之一,它使用标记数据进行训练,即每个样本都有对应的标签或目标值。模型通过学习输入特征与标签之间的关系,来对新的未知数据进行预测。例如,在一个预测房价的任务中,我们可以使用房屋的面积、房间数量、地理位置等特征作为输入,房屋的实际价格作为标签,通过监督学习算法训练模型,使其能够根据新的房屋特征预测房价。常见的监督学习算法包括线性回归、逻辑回归、决策树、支持向量机、随机森林等。
- 无监督学习:无监督学习使用未标记的数据进行训练,数据中没有预先定义的标签。其目标是发现数据中的内在结构、模式或关系,例如聚类、降维、异常检测等。聚类算法可以将数据点划分为不同的组,使得同一组内的数据点具有较高的相似性,而不同组之间的数据点具有较大的差异性。降维算法则可以将高维数据转换为低维数据,在保留数据主要特征的同时,减少数据的维度,降低计算复杂度。例如,在客户细分中,我们可以使用无监督学习算法对客户的购买行为、偏好等数据进行分析,将客户划分为不同的群体,以便企业能够针对不同群体制定个性化的营销策略。常见的无监督学习算法有 K-Means 聚类、层次聚类、主成分分析(PCA)等。
- 半监督学习:半监督学习结合了监督学习和无监督学习的特点,使用少量的标记数据和大量的未标记数据进行训练。这种学习方式在标记数据获取成本较高时非常有用,通过利用未标记数据中的信息,可以提高模型的性能和泛化能力。例如,在图像分类任务中,可能只有少量的图像被人工标注了类别标签,而大量的图像没有标签,半监督学习算法可以利用这些未标记图像中的特征信息,结合少量的标记图像,训练出一个性能较好的图像分类模型。
- 强化学习:强化学习是一种基于环境反馈的学习方法,智能体(agent)在环境中采取行动,并根据环境返回的奖励或惩罚信号来学习最优的行为策略。智能体通过不断地尝试和探索,逐渐找到在不同状态下能够获得最大奖励的行动。强化学习在机器人控制、游戏、自动驾驶等领域有广泛的应用。例如,在训练一个自动驾驶汽车的模型时,汽车作为智能体,在行驶过程中根据路况、交通规则等环境信息采取加速、减速、转弯等行动,通过获得的奖励(如安全到达目的地、遵守交通规则等)和惩罚(如碰撞、违规等)来不断优化自己的驾驶策略,最终学会在各种复杂环境下安全、高效地行驶。
6.4.2 模型训练与评估
为了更直观地展示机器学习模型的训练与评估过程,我们以一个简单的线性回归问题为例,使用 Scikit-learn 库进行实现。线性回归是一种用于预测连续数值的监督学习算法,它试图找到一个线性关系,将输入特征映射到输出目标值。
首先,我们需要导入必要的库,包括用于数据处理的 Pandas 和 NumPy,用于数据分割的train_test_split函数,用于线性回归模型的LinearRegression类,以及用于评估模型性能的mean_squared_error函数。
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
接着,我们创建一个简单的数据集,这里假设我们有房屋面积和房价的数据。
# 创建示例数据
data = {'房屋面积': [100, 120, 80, 150, 90],'房价': [200, 250, 160, 300, 180]
}
df = pd.DataFrame(data)
然后,我们将数据集划分为特征矩阵X和目标变量y,并使用train_test_split函数将数据分割为训练集和测试集,其中测试集占比 20%。
# 划分特征矩阵和目标变量
X = df[['房屋面积']]
y = df['房价']# 分割训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
接下来,我们创建线性回归模型对象,并使用训练集数据对模型进行训练。
# 创建线性回归模型
model = LinearRegression()# 训练模型
model.fit(X_train, y_train)
模型训练完成后,我们使用测试集数据进行预测,并计算预测结果与真实值之间的均方误差(MSE)来评估模型的性能。均方误差是一种常用的回归模型评估指标,它衡量了预测值与真实值之间的平均误差平方,值越小表示模型的预测效果越好。
# 进行预测
y_pred = model.predict(X_test)# 计算均方误差
mse = mean_squared_error(y_test, y_pred)
print(f'均方误差: {mse}')
通过上述步骤,我们完成了一个简单的线性回归模型的训练与评估过程。在实际应用中,我们还可以对模型进行调优,如选择不同的算法、调整模型参数、进行特征工程等,以提高模型的性能和泛化能力。同时,还可以使用其他评估指标,如决定系数(R²)、平均绝对误差(MAE)等,从不同角度评估模型的表现。例如,决定系数可以衡量模型对数据的拟合优度,其值越接近 1 表示模型对数据的拟合效果越好;平均绝对误差则衡量了预测值与真实值之间的平均绝对误差,它对异常值的敏感度相对较低。通过综合使用多种评估指标,可以更全面、准确地评估模型的性能,为模型的选择和优化提供依据。
七、数据可视化进阶
7.1 Plotly 交互式可视化
在数据可视化的领域中,Plotly 库以其独特的交互式特性脱颖而出,为我们呈现了一种全新的数据展示方式。Plotly 支持多种图表类型,并且能够创建高度交互的可视化效果,让用户能够通过缩放、平移、悬停等操作,深入探索数据背后的细节信息。
Plotly Express 是 Plotly 的高级 API,它提供了一种简洁、直观的方式来创建各种交互式图表。下面,我们通过几个示例来展示如何使用 Plotly Express 创建常见的交互式图表。
首先,我们来创建一个交互式散点图,以展示两个变量之间的关系。假设我们有一组关于房屋面积和房价的数据,想要观察它们之间的分布情况:
import plotly.express as px
import pandas as pd# 创建示例数据
data = {'房屋面积': [100, 120, 80, 150, 90],'房价': [200, 250, 160, 300, 180]
}
df = pd.DataFrame(data)# 使用Plotly Express创建散点图
fig = px.scatter(df, x='房屋面积', y='房价', title='房屋面积与房价的关系')
fig.show()
运行上述代码后,会弹出一个交互式的散点图窗口。在这个窗口中,当我们将鼠标悬停在某个数据点上时,会显示该数据点对应的房屋面积和房价的具体数值;我们还可以通过鼠标滚轮进行缩放操作,以便更清晰地观察数据点的分布情况;拖动鼠标可以平移图表,查看不同区域的数据。
接下来,创建一个交互式折线图,展示时间序列数据的变化趋势。假设我们有某公司过去一年每个月的销售额数据:
import plotly.express as px
import pandas as pd# 创建示例数据
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
sales = [100, 120, 150, 130, 180, 200, 220, 250, 230, 280, 300, 350]
data = {'月份': months, '销售额': sales}
df = pd.DataFrame(data)# 使用Plotly Express创建折线图
fig = px.line(df, x='月份', y='销售额', title='某公司过去一年销售额变化趋势')
fig.show()
在生成的折线图中,我们不仅可以看到每个月销售额的变化趋势,还能通过交互操作,在鼠标悬停时获取每个月具体的销售额数值,并且可以缩放和平移图表,聚焦于我们感兴趣的时间段。
再来看一个交互式柱状图的例子,用于比较不同类别的数据。假设我们有不同城市的人口数据:
import plotly.express as px
import pandas as pd# 创建示例数据
cities = ['北京', '上海', '广州', '深圳']
populations = [2154, 2428, 1531, 1343]
data = {'城市': cities, '人口(万)': populations}
df = pd.DataFrame(data)# 使用Plotly Express创建柱状图
fig = px.bar(df, x='城市', y='人口(万)', title='不同城市人口对比')
fig.show()
在这个交互式柱状图中,当鼠标悬停在某个柱子上时,会显示该城市的具体人口数量。我们可以通过缩放操作,更清晰地比较不同城市人口之间的差异,也可以平移图表,查看整个数据的分布情况。通过这些简单的示例,我们可以看到 Plotly Express 创建的交互式图表,极大地增强了数据的可视化效果和用户与数据的交互性,使我们能够更深入、全面地理解数据。
7.2 高级图表定制
在使用 Plotly 进行数据可视化时,除了创建基本的交互式图表外,我们还可以对图表进行更高级的定制,以满足不同的展示需求和审美要求。这包括添加注释、调整布局、设置交互行为等方面,使图表更加丰富、专业和易于理解。
首先,我们来看如何添加注释。注释可以帮助我们在图表中标记重要的数据点、区域或添加额外的说明信息,从而更好地传达数据的含义。例如,在之前的房屋面积与房价散点图中,我们想要标记出某个具有代表性的房屋数据点:
import plotly.express as px
import pandas as pd# 创建示例数据
data = {'房屋面积': [100, 120, 80, 150, 90],'房价': [200, 250, 160, 300, 180]
}
df = pd.DataFrame(data)# 使用Plotly Express创建散点图
fig = px.scatter(df, x='房屋面积', y='房价', title='房屋面积与房价的关系')# 添加注释
fig.add_annotation(x=120, # 注释的x坐标y=250, # 注释的y坐标text='这是一个典型的房屋数据点', # 注释文本showarrow=True, # 显示箭头arrowhead=1 # 箭头形状
)
fig.show()
运行上述代码后,在散点图中,我们会看到一个带有箭头的注释指向坐标为 (120, 250) 的数据点,并显示注释文本 “这是一个典型的房屋数据点”。通过这种方式,我们可以突出重要的数据信息,帮助观众更好地理解图表。
布局调整是图表定制的另一个重要方面,它可以影响图表的整体外观和可读性。我们可以调整图表的标题、轴标签、图例位置、背景颜色等。例如,对之前的销售额变化趋势折线图进行布局调整:
import plotly.express as px
import pandas as pd# 创建示例数据
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
sales = [100, 120, 150, 130, 180, 200, 220, 250, 230, 280, 300, 350]
data = {'月份': months, '销售额': sales}
df = pd.DataFrame(data)# 使用Plotly Express创建折线图
fig = px.line(df, x='月份', y='销售额', title='某公司过去一年销售额变化趋势')# 调整布局
fig.update_layout(title_font_size=20, # 标题字体大小xaxis_title='月份', # x轴标签yaxis_title='销售额', # y轴标签legend_title='图例', # 图例标题legend=dict(orientation='h', # 图例水平显示yanchor='bottom',y=1.02,xanchor='right',x=1), # 图例位置plot_bgcolor='white', # 绘图区域背景颜色paper_bgcolor='lightgray' # 图表背景颜色
)
fig.show()
在这段代码中,我们通过update_layout方法对图表的布局进行了一系列调整。增大了标题字体大小,使其更加醒目;明确了 x 轴和 y 轴的标签,使坐标轴含义清晰;将图例设置为水平显示,并调整了其位置;同时,分别设置了绘图区域和图表的背景颜色,使图表整体看起来更加美观和专业。
设置交互行为可以进一步增强用户与图表的互动体验。例如,我们可以设置点击数据点时的操作,如显示更多详细信息、跳转到相关页面等。下面以散点图为例,设置点击数据点时显示弹窗信息:
import plotly.express as px
import pandas as pd# 创建示例数据
data = {'房屋面积': [100, 120, 80, 150, 90],'房价': [200, 250, 160, 300, 180],'房屋详情': ['两居室,精装修', '三居室,毛坯房', '一居室,简装修', '四居室,豪华装修', '两居室,普通装修']
}
df = pd.DataFrame(data)# 使用Plotly Express创建散点图
fig = px.scatter(df, x='房屋面积', y='房价', hover_name='房屋详情', title='房屋面积与房价的关系')# 设置点击数据点的交互行为
fig.update_traces(hovertemplate='房屋面积: %{x}<br>房价: %{y}<br>房屋详情: %{customdata[0]}',customdata=df[['房屋详情']]
)
fig.show()
在上述代码中,我们首先在创建散点图时,通过hover_name参数设置鼠标悬停时显示的信息为房屋详情。然后,使用update_traces方法设置点击数据点时的交互行为,hovertemplate定义了弹窗中显示的内容格式,customdata指定了要显示的额外数据。这样,当我们点击散点图中的数据点时,会弹出一个包含房屋面积、房价和房屋详情的弹窗,为用户提供更详细的数据信息。通过这些高级图表定制操作,我们可以创建出更加个性化、功能丰富的可视化图表,更好地展示数据的内涵和价值。
7.3 动态图表制作
在数据可视化中,动态图表能够展示数据随时间或其他变量的变化过程,为我们提供更加直观和丰富的信息。Python 提供了多种方法来制作动态图表,下面我们将介绍使用 Matplotlib 的动画模块(如 FuncAnimation)以及其他动态图表库来创建动态图表。
Matplotlib 是 Python 中常用的绘图库,其动画模块FuncAnimation可以帮助我们创建动态图表。以一个简单的动态折线图为例,展示随着时间变化,正弦函数的曲线动态变化:
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np# 创建图形和子图
fig, ax = plt.subplots()
x = np.linspace(0, 2 * np.pi, 100)
line, = ax.plot(x, np.sin(x))# 更新函数,用于每一帧的更新
def update(frame):line.set_ydata(np.sin(x + frame / 10.0)) # 更新y数据return line,# 创建动画
ani = FuncAnimation(fig, update, frames=100, interval=50, blit=True)# 显示图表
plt.show()
在上述代码中,首先创建了一个图形和子图,并绘制了初始的正弦函数曲线。update函数是动画的核心,它接受一个frame参数,表示当前的帧数。在每一帧中,通过修改曲线的 y 数据来实现动态效果。FuncAnimation函数用于创建动画,其中frames参数指定帧数,interval参数指定每帧之间的时间间隔(单位为毫秒),blit=True表示只更新变化的部分,以提高动画的绘制效率。运行代码后,我们可以看到正弦函数曲线随着时间动态变化,呈现出一个生动的动画效果。
除了 Matplotlib,还有其他一些动态图表库可以使用,例如pandas - alive,它完美结合了 Pandas 数据格式和 Matplotlib 的强大功能,使得制作动图变得更加容易。以下是使用pandas - alive创建动态条形图的示例:
import pandas as pd
import pandas_alive# 创建示例数据
data = {'年份': [2010, 2011, 2012, 2013, 2014],'苹果销量': [100, 120, 150, 130, 180],'香蕉销量': [80, 90, 110, 100, 140]
}
df = pd.DataFrame(data)
df.set_index('年份', inplace=True)# 使用pandas_alive创建动态条形图
df.plot_animated(filename='sales_animation.gif', kind='bar', period_label={'x': 0.1, 'y': 0.9})
在这段代码中,我们首先创建了一个包含不同年份苹果和香蕉销量的 DataFrame,并将年份设置为索引。然后,使用plot_animated方法创建动态条形图,filename参数指定生成的动画文件名,kind='bar'表示创建条形图,period_label参数用于设置时间标签的位置。运行代码后,会生成一个名为sales_animation.gif的动态条形图,展示了不同年份苹果和香蕉销量的变化情况。通过这些方法,我们可以根据具体需求选择合适的工具来制作动态图表,为数据可视化增添更多的魅力和表现力,让数据以更加生动的方式展现出来。
八、自动化与批量处理
8.1 使用循环批量处理数据
在数据分析过程中,经常会遇到需要对多个数据文件进行相同分析操作的情况。手动逐个处理不仅效率低下,还容易出错。Python 的循环机制为我们提供了一种高效的解决方案,通过循环可以自动对多个文件进行操作,并将结果整合起来。
假设我们有一个文件夹,里面包含多个 CSV 格式的销售数据文件,每个文件记录了不同月份的销售情况。我们的目标是读取每个文件,计算每个文件中的销售总额,并将所有文件的销售总额汇总。
首先,我们需要导入必要的库,这里用到os库来操作文件和目录,pandas库来处理数据:
import os
import pandas as pd# 定义数据文件夹路径
data_folder ='sales_data'
total_sales = 0# 获取文件夹中所有CSV文件的文件名
file_names = [file for file in os.listdir(data_folder) if file.endswith('.csv')]# 循环处理每个文件
for file_name in file_names:file_path = os.path.join(data_folder, file_name)df = pd.read_csv(file_path)# 假设销售金额列名为'sales_amount'monthly_sales = df['sales_amount'].sum()print(f'{file_name}的销售总额为: {monthly_sales}')total_sales += monthly_salesprint(f'所有文件的销售总额为: {total_sales}')
在上述代码中,我们首先使用os.listdir获取指定文件夹中的所有文件和目录名,通过列表推导式筛选出以.csv结尾的文件,得到包含所有 CSV 文件名的列表file_names。然后,使用for循环遍历这个列表,对于每个文件名,使用os.path.join函数拼接出完整的文件路径file_path,再使用pd.read_csv读取文件内容到 DataFrame 对象df中。接着,计算当前文件中销售金额列sales_amount的总和monthly_sales,并打印出来。最后,将每个文件的销售总额累加到total_sales中,循环结束后,打印出所有文件的销售总额。
通过这样的循环批量处理,我们可以快速、准确地对多个数据文件进行相同的分析操作,大大提高了工作效率。而且,这种方式具有很好的扩展性,如果后续有新的数据文件添加到文件夹中,只需要将新文件放入指定文件夹,代码无需修改即可自动处理。
8.2 使用函数封装重复性步骤
当我们在数据分析中存在一些重复性的步骤时,将这些步骤封装为函数是一个非常好的实践。通过函数封装,可以使代码更加简洁、易读,同时也提高了代码的可维护性和可复用性,方便在不同的数据集上重复使用。
继续以上述销售数据处理为例,假设我们除了计算销售总额,还需要计算每个文件中的平均销售金额、最大销售金额和最小销售金额,并且这些操作在多个数据分析任务中都会用到。我们可以将这些操作封装成一个函数:
import pandas as pddef analyze_sales_data(file_path):df = pd.read_csv(file_path)# 假设销售金额列名为'sales_amount'total_sales = df['sales_amount'].sum()average_sales = df['sales_amount'].mean()max_sales = df['sales_amount'].max()min_sales = df['sales_amount'].min()return total_sales, average_sales, max_sales, min_sales# 定义数据文件夹路径
data_folder ='sales_data'# 获取文件夹中所有CSV文件的文件名
file_names = [file for file in os.listdir(data_folder) if file.endswith('.csv')]# 循环处理每个文件
for file_name in file_names:file_path = os.path.join(data_folder, file_name)total, average, max_val, min_val = analyze_sales_data(file_path)print(f'{file_name}的销售总额为: {total}')print(f'{file_name}的平均销售金额为: {average}')print(f'{file_name}的最大销售金额为: {max_val}')print(f'{file_name}的最小销售金额为: {min_val}')print('-' * 30)
在这段代码中,我们定义了一个名为analyze_sales_data的函数,它接受一个文件路径file_path作为参数。在函数内部,首先读取指定路径的 CSV 文件到 DataFrame 对象df,然后计算销售总额、平均销售金额、最大销售金额和最小销售金额,最后将这些结果作为元组返回。在主程序中,通过循环遍历数据文件夹中的所有 CSV 文件,对于每个文件,调用analyze_sales_data函数进行分析,并打印出分析结果。
通过函数封装,我们将重复性的数据分析步骤整合到一个函数中,使得代码结构更加清晰。如果后续需要修改分析逻辑,只需要在函数内部进行修改,而不需要在每个使用到这些分析步骤的地方都进行修改,大大提高了代码的维护性。同时,这个函数可以在其他数据分析任务中被重复调用,提高了代码的复用性。
8.3 使用 Dask 或 Apache Spark 实现分布式计算
在处理大规模数据集时,单机的计算资源往往是有限的,传统的数据分析工具可能会面临内存不足或计算速度过慢的问题。这时,分布式计算框架就派上了用场。Dask 和 Apache Spark 是两个在 Python 中广泛使用的分布式计算框架,它们能够利用集群中多个节点的计算资源,高效地处理大规模数据集。
Dask
Dask 是一个灵活的并行计算库,它提供了与 NumPy 和 Pandas 类似的 API,使得从传统的单机数据分析过渡到分布式计算变得相对容易。Dask 可以处理比内存中可容纳的数据集更大的数据,通过将数据分割成多个小块(chunks),并在多个核心或计算机上并行处理这些小块,实现高效的计算。
首先,我们需要安装 Dask 库,可以使用pip install dask进行安装。如果需要使用 Dask 的分布式功能,还需要安装dask[distributed]。
假设我们有一个非常大的 CSV 文件,无法一次性加载到内存中,使用 Dask 进行处理的示例如下:
import dask.dataframe as dd# 读取超大CSV文件
df = dd.read_csv('large_sales_data.csv')# 假设销售金额列名为'sales_amount',计算销售总额
total_sales = df['sales_amount'].sum().compute()
print(f'销售总额为: {total_sales}')
在上述代码中,我们使用dask.dataframe中的read_csv函数读取超大的 CSV 文件,这个函数会返回一个 Dask DataFrame 对象,它并不会立即将整个文件加载到内存中,而是将数据分成多个小块进行管理。然后,我们像使用 Pandas DataFrame 一样,对 Dask DataFrame 进行操作,计算销售总额。需要注意的是,Dask 使用延迟执行策略,即操作不会立即执行,直到调用compute方法时,才会触发计算,并将结果返回。
Dask 还支持更复杂的数据操作,如分组、聚合、连接等,并且可以轻松地与现有的 Python 数据分析代码集成。例如,计算每个产品类别的销售总额:
import dask.dataframe as dd# 读取超大CSV文件
df = dd.read_csv('large_sales_data.csv')# 假设销售金额列名为'sales_amount',产品类别列名为'product_category'
category_total_sales = df.groupby('product_category')['sales_amount'].sum().compute()
print(category_total_sales)
在这段代码中,我们使用groupby方法对 Dask DataFrame 按product_category列进行分组,然后计算每个分组中sales_amount列的总和,最后调用compute方法得到结果。
Apache Spark
Apache Spark 是一个快速、通用的大数据处理引擎,它提供了丰富的功能和工具,用于大规模数据的处理、分析和机器学习。Spark 使用弹性分布式数据集(Resilient Distributed Dataset,RDD)作为核心抽象,能够在集群中进行分布式计算。
在 Python 中使用 Spark,需要安装pyspark库。安装完成后,我们可以通过以下示例了解如何使用 Spark 处理大规模数据。假设我们有一个包含用户行为数据的文本文件,每行数据包含用户 ID、行为类型和时间戳,我们想要统计每种行为类型的出现次数。
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, count# 创建SparkSession
spark = SparkSession.builder.appName('UserBehaviorAnalysis').getOrCreate()# 读取文本文件,假设文件路径为'user_behavior_data.txt'
df = spark.read.text('user_behavior_data.txt')# 将每行数据按空格分割成列
df = df.selectExpr('split(value, " ") as cols')
df = df.select(col('cols')[0].alias('user_id'), col('cols')[1].alias('behavior_type'), col('cols')[2].alias('timestamp'))# 统计每种行为类型的出现次数
behavior_count = df.groupBy('behavior_type').agg(count('*').alias('count')).show()
在上述代码中,首先通过SparkSession.builder.appName('UserBehaviorAnalysis').getOrCreate()创建一个 SparkSession 对象,它是与 Spark 交互的入口点。然后使用spark.read.text读取文本文件,并将其转换为 DataFrame。接着,通过selectExpr和select方法对数据进行处理,将每行数据按空格分割成三列,并分别命名为user_id、behavior_type和timestamp。最后,使用groupBy和agg方法统计每种行为类型的出现次数,并使用show方法显示结果。
Apache Spark 还支持多种数据源和数据格式,如 Hive、Parquet、JSON 等,并且提供了强大的机器学习库(MLlib)和流处理功能(Spark Streaming),能够满足各种大规模数据处理和分析的需求。通过使用 Dask 或 Apache Spark 这样的分布式计算框架,我们能够突破单机计算资源的限制,高效地处理大规模数据集,为数据分析和建模提供更强大的支持。
九、案例实战
9.1 案例背景与数据获取
在当今竞争激烈的商业环境中,销售数据分析对于企业的决策和发展至关重要。通过深入分析销售数据,企业能够了解市场趋势、客户需求以及产品的销售表现,从而制定更加精准的营销策略,优化产品组合,提高销售业绩。接下来,我们将以某电商公司的销售数据为例,进行一次完整的数据分析与可视化实践。
本次案例的数据来源于该电商公司过去一年的销售记录,数据存储在一个 CSV 文件中,文件名为sales_data.csv。该文件包含了丰富的销售信息,具体字段如下:
- order_id:订单 ID,唯一标识每一笔订单。
- product_name:产品名称。
- category:产品所属类别。
- quantity:销售数量。
- price:产品单价。
- order_date:订单日期。
- customer_id:客户 ID,用于标识不同的客户。
- city:客户所在城市。
首先,我们需要使用 Pandas 库读取 CSV 文件中的数据,并将其转换为 DataFrame 对象,以便后续进行处理和分析。
import pandas as pd# 读取销售数据
sales_data = pd.read_csv('sales_data.csv')
# 查看数据的前5行
sales_data.head()
运行上述代码后,我们可以看到 DataFrame 的前 5 行数据,初步了解数据的结构和内容。通过head()方法,我们能够快速检查数据是否正确读取,以及各列的数据类型是否符合预期。
9.2 数据清洗与预处理
原始数据往往存在各种问题,如缺失值、异常值、重复值等,这些问题会影响数据分析的准确性和可靠性。因此,在进行数据分析之前,我们需要对数据进行清洗和预处理。
9.2.1 检测与处理缺失值
使用isnull()方法检测数据集中的缺失值,并使用sum()方法统计每列的缺失值数量。
# 检测缺失值
missing_values = sales_data.isnull()
# 统计缺失值数量
missing_values_count = missing_values.sum()
print(missing_values_count)
假设输出结果显示category列有 50 个缺失值,price列有 10 个缺失值。对于category列的缺失值,我们可以采用填充众数的方法进行处理,因为category是分类数据,众数能够代表该列数据的集中趋势。对于price列的缺失值,由于价格是数值型数据,我们可以使用均值填充,以保持数据的统计特征。
# 填充category列的缺失值为众数
mode_category = sales_data['category'].mode()[0]
sales_data['category'] = sales_data['category'].fillna(mode_category)# 填充price列的缺失值为均值
mean_price = sales_data['price'].mean()
sales_data['price'] = sales_data['price'].fillna(mean_price)
再次检查缺失值,确保所有缺失值都已处理。
missing_values_count = sales_data.isnull().sum()
print(missing_values_count)
9.2.2 检测与处理异常值
使用箱线图检测quantity和price列的异常值。
import matplotlib.pyplot as plt
import seaborn as sns# 绘制quantity列的箱线图
plt.figure(figsize=(10, 6))
sns.boxplot(data=sales_data['quantity'])
plt.title('Boxplot of Quantity')
plt.show()# 绘制price列的箱线图
plt.figure(figsize=(10, 6))
sns.boxplot(data=sales_data['price'])
plt.title('Boxplot of Price')
plt.show()
从箱线图中可以观察到,quantity列存在一些明显的异常值(超出上下边界的数据点)。对于这些异常值,我们可以先进行调查,判断其是否是由于数据录入错误或其他原因导致的。如果是错误数据,可以进行修正;如果无法确定原因,且异常值对分析结果影响较大,可以选择删除这些异常值。假设经过调查,我们发现quantity列的异常值是由于数据录入错误导致的,我们将其修正为合理的值。
# 修正quantity列的异常值(假设异常值为负数,修正为1)
sales_data['quantity'] = sales_data['quantity'].apply(lambda x: 1 if x <= 0 else x)
再次绘制箱线图,检查异常值是否已处理。
plt.figure(figsize=(10, 6))
sns.boxplot(data=sales_data['quantity'])
plt.title('Boxplot of Quantity after handling outliers')
plt.show()
9.2.3 检测与处理重复值
使用duplicated()方法检测数据集中的重复行,并使用drop_duplicates()方法删除重复行。
# 检测重复值
duplicate_rows = sales_data.duplicated()
print(duplicate_rows.sum())# 删除重复值
sales_data = sales_data.drop_duplicates()
再次检查重复值,确保所有重复行都已删除。
duplicate_rows = sales_data.duplicated()
print(duplicate_rows.sum())
9.2.4 数据类型转换
检查数据类型,确保order_date列的数据类型为日期时间类型,以便进行日期时间相关的分析。
# 检查数据类型
print(sales_data.dtypes)
如果order_date列的数据类型不是日期时间类型,使用pd.to_datetime()方法进行转换。
# 将order_date列转换为日期时间类型
sales_data['order_date'] = pd.to_datetime(sales_data['order_date'])
再次检查数据类型,确认order_date列已成功转换。
print(sales_data.dtypes)
经过以上数据清洗与预处理步骤,我们得到了一个干净、整齐的数据集,为后续的数据分析和可视化奠定了坚实的基础。
9.3 数据分析与可视化
对预处理后的数据进行深入分析,提出一些有针对性的问题,并通过可视化的方式展示分析结果,以便更直观地理解数据背后的信息。
9.3.1 销售趋势分析
问题:过去一年中,每月的销售总额是如何变化的?
为了回答这个问题,我们需要先计算每月的销售总额,然后使用折线图展示销售趋势。
# 计算每月的销售总额
sales_data['month'] = sales_data['order_date'].dt.to_period('M')
monthly_sales = sales_data.groupby('month')['quantity', 'price'].agg({'quantity':'sum', 'price':'sum'})
monthly_sales['total_sales'] = monthly_sales['quantity'] * monthly_sales['price']# 绘制销售趋势折线图
plt.figure(figsize=(12, 6))
plt.plot(monthly_sales.index.astype(str), monthly_sales['total_sales'])
plt.xlabel('Month')
plt.ylabel('Total Sales')
plt.title('Monthly Sales Trend')
plt.xticks(rotation=45)
plt.show()
从折线图中可以清晰地看出,销售总额在过去一年中呈现出一定的季节性波动。其中,在某些月份(如 11 月和 12 月)销售总额明显较高,可能是由于节假日促销活动等原因导致的。而在其他月份,销售总额相对稳定,但也存在一些小幅度的波动。通过对销售趋势的分析,企业可以更好地了解市场需求的季节性变化,合理安排生产和库存,以及制定相应的营销策略。
9.3.2 产品销售分布分析
问题:不同产品类别的销售占比是怎样的?
计算各产品类别的销售数量和销售总额,然后使用饼图展示销售占比。
# 计算各产品类别的销售数量和销售总额
category_sales = sales_data.groupby('category')['quantity', 'price'].agg({'quantity':'sum', 'price':'sum'})
category_sales['total_sales'] = category_sales['quantity'] * category_sales['price']# 绘制产品类别销售占比饼图
plt.figure(figsize=(10, 10))
plt.pie(category_sales['total_sales'], labels=category_sales.index, autopct='%1.1f%%')
plt.title('Sales Distribution by Product Category')
plt.show()
从饼图中可以直观地看出,不同产品类别的销售占比存在较大差异。其中,某些产品类别(如电子产品)的销售占比较高,可能是该电商公司的核心产品;而其他产品类别(如家居用品)的销售占比相对较低。通过对产品销售分布的分析,企业可以了解市场对不同产品类别的需求程度,优化产品组合,加大对畅销产品的推广力度,同时对销售不佳的产品进行调整或淘汰。
9.3.3 客户购买行为分析
问题:不同城市的客户购买数量和购买金额有何差异?
计算各城市客户的购买数量和购买金额,然后使用柱状图进行对比展示。
# 计算各城市客户的购买数量和购买金额
city_sales = sales_data.groupby('city')['quantity', 'price'].agg({'quantity':'sum', 'price':'sum'})
city_sales['total_amount'] = city_sales['quantity'] * city_sales['price']# 绘制各城市客户购买数量和购买金额柱状图
plt.figure(figsize=(15, 8))
bar_width = 0.35ax1 = plt.subplot(1, 2, 1)
ax1.bar(city_sales.index, city_sales['quantity'], width=bar_width, label='Quantity')
ax1.set_xlabel('City')
ax1.set_ylabel('Total Quantity')
ax1.set_title('Quantity Purchased by City')
ax1.set_xticks(np.arange(len(city_sales.index)))
ax1.set_xticklabels(city_sales.index, rotation=45)
ax1.legend()ax2 = plt.subplot(1, 2, 2)
ax2.bar(city_sales.index, city_sales['total_amount'], width=bar_width, label='Total Amount')
ax2.set_xlabel('City')
ax2.set_ylabel('Total Amount')
ax2.set_title('Total Amount Purchased by City')
ax2.set_xticks(np.arange(len(city_sales.index)))
ax2.set_xticklabels(city_sales.index, rotation=45)
ax2.legend()plt.tight_layout()
plt.show()
从柱状图中可以明显看出,不同城市的客户购买数量和购买金额存在显著差异。一些大城市(如北京、上海、广州)的客户购买数量和购买金额明显高于其他城市,这可能与这些城市的人口密度、经济发展水平以及消费能力等因素有关。通过对客户购买行为的分析,企业可以根据不同城市的市场特点,制定差异化的市场营销策略,提高市场占有率和销售业绩。
通过以上数据分析与可视化,我们从不同角度深入了解了销售数据的特征和规律,为企业提供了有价值的决策依据。企业可以根据这些分析结果,优化产品策略、营销策略和市场布局,以适应市场变化,提高竞争力,实现可持续发展。
十、总结与展望
通过本次对 Python 数据分析与可视化全流程的探索,我们从基础的库介绍,到数据的获取、清洗、分析以及可视化展示,再到自动化与批量处理,最后通过实际案例进行了全面的实践。在这个过程中,我们深刻体会到了 Python 在数据分析与可视化领域的强大功能和广泛应用。
回顾整个流程,数据获取是基础,我们从文件、数据库、网络等多种渠道获取数据,为后续分析提供原材料。数据清洗与预处理是关键步骤,它能够去除数据中的杂质和异常,使数据更加准确和可用,为分析结果的可靠性奠定基础。数据分析与建模环节,我们运用描述性统计分析、相关性分析、数据分组与聚合等方法,深入挖掘数据背后的信息和规律,还通过机器学习进行预测和建模,为决策提供有力支持。数据可视化则是将数据分析结果以直观、形象的方式呈现出来,帮助我们更好地理解数据,其中 Plotly 的交互式可视化和高级图表定制为我们提供了丰富的展示方式,动态图表制作更是为数据展示增添了生动性。自动化与批量处理提高了工作效率,让我们能够更高效地处理大量数据。
在实际操作中,需要注意数据的质量和准确性,确保数据清洗和预处理的彻底性。在选择分析方法和模型时,要根据数据特点和分析目标进行合理选择,避免盲目套用。可视化图表的设计要注重简洁明了,突出重点,以达到良好的展示效果。
展望未来,随着数据量的不断增长和数据类型的日益丰富,Python 数据分析与可视化领域有望迎来更多的发展机遇和挑战。在技术方面,机器学习和深度学习将与数据分析更加紧密地结合,实现更智能的数据分析和预测。自动化可视化技术将不断发展,能够根据数据特征和用户需求自动生成合适的可视化图表,大大提高工作效率。在应用领域,数据分析与可视化将在更多行业得到深入应用,如医疗、金融、教育、交通等,为各行业的决策和发展提供有力支持。同时,随着人们对数据隐私和安全的关注度不断提高,如何在数据分析过程中保障数据的安全和隐私将成为重要的研究方向。总之,Python 数据分析与可视化领域前景广阔,我们需要不断学习和探索,以适应技术的发展和应用的需求。
相关文章推荐:
1、Python详细安装教程(大妈看了都会)
2、02-pycharm详细安装教程(大妈看了都会)
3、如何系统地自学Python?
4、Alibaba Cloud Linux 3.2104 LTS 64位 怎么安装python3.10.12和pip3.10
5、职场新技能:Python数据分析,你掌握了吗?
6、Python爬虫图片:从入门到精通
串联文章:
1、Python小白的蜕变之旅:从环境搭建到代码规范(1/10)
2、Python面向对象编程实战:从类定义到高级特性的进阶之旅(2/10)
3、Python 异常处理与文件 IO 操作:构建健壮的数据处理体系(3/10)
4、从0到1:用Lask/Django框架搭建个人博客系统(4/10)