树莓派数据科学教程-一-

154 阅读1小时+

树莓派数据科学教程(一)

原文:Data Science with Raspberry Pi

协议:CC BY-NC-SA 4.0

一、数据科学导论

数据是关于主题的文字、数字和描述形式的信息的集合。考虑下面的陈述:“狗有四条腿,1.5 米高,有棕色的毛。”这一陈述具有关于狗的三种不同类型的信息(即,数据)。数据“四”和“1.5m”是数值数据,“棕发”是描述性的。了解各种数据类型有助于理解数据、执行有效的分析以及更好地从数据中提取知识。基本上,数据可以分为两种类型。

  • 数据

  • 质量数据

定量数据只能借助测量而不是通过观察来获得。这可以用数值的形式来表示。定量数据可以进一步分为连续数据和离散数据。精确的整数值是离散数据,而连续数据可以是一个范围内的任何值。定性数据是对受试者特征的描述。通常定性数据可以从观察中获得,无法测量。换句话说,定性数据可以被描述为分类数据,而定量数据可以被称为数值数据。

例如,在前面的陈述中,“棕色毛发”描述了狗的特征,是定性数据,而“四条腿”和“1.5m”是定量数据,分别被归类为离散和连续数据。

数据可以以结构化和非结构化的形式提供。当数据被组织在预定义的数据模型/结构中时,它被称为结构化数据。借助查询语言,结构化数据可以存储在表格格式或关系数据库中。我们也可以将这类数据以 Excel 文件格式存储,如表 1-1 中给出的学生数据库。

表 1-1

结构化数据的一个例子

|

学生点名

|

马克斯

|

出席

|

一批

|

| | --- | --- | --- | --- | --- | | One hundred and eleven thousand four hundred and one | 492/500 | 98% | 2011-2014 | 男性的 | | One hundred and eleven thousand four hundred and two | 442/500 | 72% | 2011-2014 | 男性的 | | One hundred and twenty-one thousand five hundred and one | 465/500 | 82% | 2012-2015 | 女性的 | | One hundred and twenty-one thousand five hundred and two | 452/500 | 87% | 2012-2015 | 男性的 |

大多数人类生成和机器生成的数据都是非结构化数据,例如电子邮件、文档、文本文件、日志文件、文本消息、图像、视频和音频文件、网络和社交媒体上的消息以及来自传感器的数据。这些数据只能通过人工或机器干预才能转换成结构化格式。图 1-1 显示了非结构化数据的各种来源。

img/496535_1_En_1_Fig1_HTML.jpg

图 1-1

非结构化数据的来源

数据类型在数据科学中的重要性

在开始分析数据之前,了解数据类型非常重要,这样您就可以选择合适的分析方法。连续数据的分析不同于分类数据的分析;因此,对两者使用相同的分析方法可能会导致不正确的分析。

例如,在涉及连续数据的统计分析中,确切事件的概率为零,而离散数据的结果可能不同。

您还可以根据数据类型选择可视化工具。例如,连续数据通常用直方图表示,而离散数据可以借助条形图可视化。

数据科学:概述

正如本章开头所讨论的,数据科学只不过是从数据中提取知识或信息。不幸的是,并不是所有的数据都能提供有用的信息。它基于客户需求、假设、数据类型的本质以及用于分析和建模的方法。因此,在对数据进行分析或建模以进行智能决策之前,需要进行一些处理。图 1-2 描述了这些数据科学流程。

img/496535_1_En_1_Fig2_HTML.jpg

图 1-2

数据科学过程

数据要求

为了开发一个数据科学项目,数据科学家首先根据客户/业务需求理解问题,然后定义分析问题的目标。例如,假设一个客户想要分析人们对政府政策的情绪。首先,问题的目标可以设定为“收集人民对政府政策的意见”然后,数据科学家决定支持目标的数据类型和数据资源。对于示例问题,可能的数据是社交媒体数据,包括各种类别的人的文本消息和民意调查,以及关于他们的教育水平、年龄、职业等的信息。在开始数据收集之前,一个好的工作计划对于从各种来源收集数据至关重要。设定目标和工作计划可以减少收集数据所花费的时间,并有助于准备报告。

数据采集

互联网上有许多类型的结构化开放数据,我们称之为二级数据,因为这种数据是由某人收集并构建成某种表格格式的。如果用户想直接从一个来源收集数据,那就叫做原始数据。最初,非结构化数据是通过许多资源收集的,例如移动设备、电子邮件、传感器、摄像头、与人的直接交互、视频文件、音频文件、文本消息、博客等。

数据准备

数据准备是数据科学过程中最重要的部分。准备数据会将数据转换成适当的形式,以便进行知识提取。数据准备阶段有三个步骤。

  1. 数据处理

  2. 数据清理

  3. 数据转换

数据处理

这一步很重要,因为当我们从各种来源导入数据时,需要检查数据的质量。进行这种质量检查是为了确保数据具有正确的数据类型和标准格式,并且变量中没有打字错误或错误。这一步将减少进行分析时的数据问题。此外,在这个阶段,收集的非结构化数据可以以结构化数据的形式进行组织,以便进行分析和可视化。

数据清理

数据处理完成后,需要清理数据,因为数据可能仍有一些错误。这些误差会影响数据中的实际信息。可能的错误如下:

  • 复制

  • 人为或机器错误

  • 缺少值

  • 极端值

  • 不适当的价值观

复制

在数据库中,一些数据重复多次,导致重复。最好检查并删除重复项,以减少数据分析期间的计算开销。

人为或机器错误

数据由人类或机器从数据源收集。在这个过程中,由于人的疏忽或机器故障,一些错误是不可避免的。避免这类错误的可能解决方案是将变量和值与标准变量和值相匹配。

缺少值

在将非结构化数据转换成结构化形式时,一些行和列可能没有任何值(即,空)。这种误差将导致信息的不连续性,并使其难以可视化。编程语言中有许多内置函数,我们可以用它们来检查数据是否有任何缺失值。

极端值

在统计学中,异常值是与其他观察值显著不同的数据点。异常值可能是因为测量中的可变性,或者它可能表明实验误差;离群值有时会被排除在数据集之外。图 1-3 显示了一个异常数据的例子。异常数据会导致某些类型的模型出现问题,进而影响决策。

img/496535_1_En_1_Fig3_HTML.jpg

图 1-3

异常数据

转换数据

数据转换可以通过使用标准化、最小-最大运算、相关信息等多种方法来完成。

数据可视化

根据用户的要求,可以借助图表、图形等可视化工具对数据进行分析。这些可视化工具帮助人们理解数据集中特定变量的趋势、变化和偏差。可视化技术可以作为探索性数据分析的一部分。

数据分析

借助于数学技术,如统计技术,可以进一步分析这些数据。改进、偏差和变化以数字形式确定。我们还可以通过结合可视化工具和分析技术的结果来生成分析报告。

建模和算法

今天,许多机器学习算法被用来从原始数据中预测有用的信息。例如,神经网络可以用于根据用户之前的行为来识别愿意向孤儿捐赠资金的用户。在这种场景下,可以基于用户的教育、活动、职业、性别等来收集用户之前的行为数据。可以用这些收集的数据来训练神经网络。每当一个新用户的数据被馈入这个模型,它就可以预测这个新用户是否会给出资金。但是,预测的准确性取决于可靠性和训练时使用的数据量。

有许多可用的机器学习算法,例如回归技术、支持向量机(SVM)、神经网络、深度神经网络、递归神经网络等。,可以应用于数据建模。在数据建模之后,可以通过提供来自新用户的数据并开发预测报告来分析模型。

报告生成/决策制定

最后,在可视化工具、数学或统计技术以及模型的帮助下,可以基于分析开发报告。这种报告在许多情况下是有用的,例如预测一个组织、行业、政府等的优势和劣势。报告中的事实和发现可以使决策变得相当容易和明智。此外,分析报告可以根据客户需求使用一些自动化工具自动生成。

数据科学的最新趋势

数据科学中的某些领域正在呈指数增长,因此对数据科学家来说很有吸引力。下面几节将对它们进行讨论。

数据科学中的自动化

在当前的场景中,数据科学仍然需要大量的手动工作,例如数据处理、数据清理和数据转换。这些步骤消耗大量的时间和计算。现代世界需要数据科学流程的自动化,如数据处理、数据清理、数据转换、分析、可视化和报告生成。因此,自动化领域将是数据科学行业的最大需求。

基于人工智能的数据分析师

可以有效地实施人工智能技术和机器学习算法来对数据进行建模。特别地,使用深度神经网络的强化学习来基于数据的变化升级模型的学习。此外,机器学习技术可以用于自动化数据科学项目。

云计算

如今人们使用的数据量呈指数级增长。一些行业每天收集大量数据,因此很难在本地服务器的帮助下进行存储和分析。这使得它在计算和维护方面很昂贵。因此,他们更喜欢云计算,在云计算中,数据可以存储在云服务器上,并可以随时随地进行检索和分析。许多云计算公司在其云服务器上提供数据分析平台。数据处理的发展越快,这个领域就越受关注。

边缘计算

许多小规模行业不需要分析云服务器上的数据,而是需要即时的分析报告。对于这些类型的应用,边缘设备可以是一种可能的解决方案来获取数据,分析数据,并以视觉形式或数字形式立即向用户呈现报告。未来,边缘计算的需求将显著增加。

自然语言处理

自然语言处理(NLP)可用于从网站、电子邮件、服务器、日志文件等中提取非结构化数据。此外,NLP 对于将文本转换成单一数据格式也很有用。例如,我们可以将人们在社交媒体上的信息转换成数据格式。这将是从许多来源收集数据的有力工具,其需求将继续增加。

为什么要在树莓派上使用数据科学?

许多书籍解释了与云计算相关的数据科学中涉及的不同过程。但是在本书中,数据科学的概念将作为使用 Raspberry Pi 的实时应用程序的一部分进行讨论。Raspberry Pi 板可以通过使用通用输入/输出(GPIO)引脚连接到各种传感器,与实时世界进行交互,从而更容易收集实时数据。由于它们的小尺寸和低成本,这些 Raspberry Pi 板的多个节点可以连接成网络,从而实现本地化操作。换句话说,Raspberry Pi 可以用作数据处理和存储的边缘计算设备,更接近用于获取信息的设备,从而克服与云计算相关的缺点。因此,许多数据处理应用程序可以使用这些设备的分布来实施,这些设备可以管理实时数据并在本地运行分析。这本书将帮助你使用 Raspberry Pi 实现实时数据科学应用。

二、Python 编程基础

Python 是一种通用动态编程语言,由荷兰程序员吉多·范·罗苏姆于 1989 年创建。它是数据科学领域最常用的编程语言。因为 Python 比其他语言更容易学习和编写代码,所以它是初学者的最佳选择。Python 的广泛使用也归功于它是免费和开源的。Python 社区开发的大量科学库和包允许数据科学家使用数据密集型实时应用程序。一些领先的组织,如谷歌、Dropbox 和网飞,都在不同程度上使用 Python 来增强他们的软件。在本章中,我们将讨论 Python 在 Windows 操作系统上的安装、不同的 Python IDEs、Python 可用的基本数据类型、控制流语句、Python 函数以及用于数据科学的不同 Python 库。

为什么是 Python?

Python 是数据科学家最喜欢的编程语言,原因如下:

  • 它是一种开源编程语言,拥有强大且不断增长的贡献者和用户社区。

  • 它的语法比 C、C++和 Java 等其他编程语言更简单。

  • 它允许用户执行面向对象的编程。

  • 它有一个很大的库集,可用于执行各种任务,如开发网站、构建机器学习应用程序等。

  • 它可以用于嵌入式小型硬件设备,如 Raspberry Pi,支持各种应用的实时实施。

Python 安装

Linux 操作系统的大多数发行版都预装了 Python 包,但是在 Windows 操作系统的情况下,它必须单独安装。在 Windows 操作系统上安装 Python 的步骤如下:

img/496535_1_En_2_Fig1_HTML.jpg

图 2-1

Python 的安装向导

  1. 打开浏览器,进入 Python.org,Python 的官方网站。

  2. 在该页面上,单击“下载”选项卡,并在出现的页面上下载软件的最新版本。

  3. 下载完成后,打开安装包。在安装向导中,如图 2-1 所示,选择将 Python 添加到 path 中,这将确保 Python 自动添加到您的系统变量 PATH 中;否则,必须在系统的环境变量设置中手动添加该路径。

  4. 单击“立即安装”安装软件包。

安装完成后,您可以通过在命令提示符下键入python --version来验证安装,这将显示系统上安装的 Python 版本。如果它没有显示版本,那么可能是安装或系统路径变量有问题。

请参考官方网站上提供的 Python 文档,以了解下载该软件的附加模块和包的过程。您可以在命令提示符下开始使用 Python,也可以在下一节讨论的各种 ide 中安装一个。

Python IDEs

集成开发环境 (IDE)是一个软件套件,它将开发人员的工具组合到一个图形用户界面(GUI)中,其中包括用于编辑代码以及构建、执行和调试程序的选项。Python 可以使用许多 ide,每种 ide 都有自己的优势。这里讨论一些常用的 ide。

皮查姆

PyCharm IDE 由捷克公司 JetBrains 开发。它是一个跨平台的 IDE,可以在 Windows、macOS 和 Linux 上使用。它提供了代码分析和图形调试器。它还支持使用 Django 进行 web 开发,以及使用 Anaconda 进行数据科学。PyCharm 的一些吸引人的特性是智能代码完成、简单的包管理界面和重构选项,它提供了跨代码中的多行进行更改的能力。

斯派德

Spyder 是用 Python 语言进行科学编程的跨平台 IDE。Spyder 集成了许多科学软件包,包括 NumPy、SciPy、Matplotlib、Pandas、IPython 和其他开源软件。它是在麻省理工学院许可下发布的。

Jupyter 笔记型电脑

Jupyter Notebook 是一个基于网络的交互式计算环境。该笔记本将代码及其输出集成在一个文档中,该文档结合了可视化、文本、数学方程和其他媒体,从而使其适合数据科学应用。

用 IDLE 进行 Python 编程

IDLE 是一个简单的跨平台 IDE,适合教育环境中的初学者。它具有多窗口文本编辑器、带语法高亮显示的 Python shell 和集成调试器等特性。由于这是 Python 自带的默认编辑器,所以让我们看看如何使用 IDLE 执行 Python 代码。

在这种空闲状态下,有两种执行 Python 代码的方法。第一种方式是交互模式,可以直接在 Python shell 中的符号>>>旁边键入代码,如图 2-2 所示。每一行代码都将在你按下回车键后被执行。使用交互模式的缺点是,当您保存代码时,它会与结果一起保存,这意味着您不能将保存的代码用于以后的执行。

img/496535_1_En_2_Fig2_HTML.jpg

图 2-2

在交互模式下运行 Python 代码

第二种方法是在脚本模式下运行代码,您可以打开一个脚本窗口并在那里键入完整的代码,然后可以用一个.py扩展名保存以供以后使用。要打开脚本文件窗口,请转到顶部的文件菜单,然后单击新建文件。在脚本窗口中,键入同样的两行代码,如图 2-2 所示。图 2-3 显示了带有代码的脚本文件窗口。然后转到文件菜单,单击保存,然后通过指定一个正确的文件名保存程序。确保文件名不以数字开头或与现有 Python 关键字同名。

img/496535_1_En_2_Fig3_HTML.jpg

图 2-3

脚本文件窗口

文件保存后,可以通过转到顶部的运行菜单并单击运行模块来执行脚本。这将执行脚本并在 Python shell 中打印输出,如图 2-4 所示。

img/496535_1_En_2_Fig4_HTML.jpg

图 2-4

脚本文件的输出

Python 注释

在我们开始讨论 Python 数据类型之前,有必要了解一下 Python 中的注释行,因为我们会在代码中经常用到它们。根据您的注释目的,有两种方式来编写注释行。

如果你打算为自己写一个简短的注释,关于代码中的某一行,那么单行注释是最好的选择。这些单行注释可以通过简单地以一个散列字符(#)开始来创建,并且它们在行尾自动终止。执行代码时,Python 编译器将忽略散列符号之后直到行尾的所有内容。

多行注释旨在向他人解释代码的某个特定方面,可以通过在注释的开头和结尾添加三个单引号(''')来创建。Python 编译器不会忽略这些注释,如果您的脚本除了注释之外没有其他内容,它们将出现在输出中。这两个注释使用空闲 Python shell 格式进行说明,如下所示:

>>> # This is a comment
>>> "'This is a comment"'
'This is a comment'

Python 数据类型

在编程语言中,数据类型是由变量可以取值的类型定义的。Python 数据类型主要可以分为数值和序列数据类型。属于这两个类别的数据类型将在本节中讨论,并为每个类别提供相关的图示。

数字数据类型

数字数据类型是可以接受数值的标量变量。数字数据类型的类别有intfloatcomplex。此外,我们将讨论使用布尔变量的bool数据类型。

(同 Internationalorganizations)国际组织

int数据类型表示不带小数点的有符号整数。清单 2-1 中的代码显示了整数的数据类型。

a=5
"'print the data type of variable a using type() funcion"'
print("a is of type",type(a))

Output:
a is of type <class 'int'>

Listing 2-1Integer

Data Type

漂浮物

float数据类型表示浮点数,用小数点分隔整数和小数部分。清单 2-2 中的代码打印浮点值的数据类型。

a = 5.0
print('a is of type',type(a))

Output:
a is of type <class 'float'>

Listing 2-2float Data Type

复杂的

complex数据类型表示形式为 a + bj 的复数,其中 ab 分别是实部和虚部。数字 ab 可以是整数,也可以是浮点数。清单 2-3 中的代码打印复数的数据类型。

a=3.5+4j
print('a is of type',type(a))

Output :
 a is of type <class 'complex'>

Listing 2-3complex Data Type

弯曲件

在 Python 中,布尔变量由TrueFalse关键字定义。因为 Python 是区分大小写的,所以关键字TrueFalse的首字母必须大写。清单 2-4 展示了bool数据类型。

a= 8>9
print('a is of type',type(a))
print(a)

Output:
a is of type <class 'bool'>
False

Listing 2-4bool Data Type

布尔值可以用布尔运算符操作,包括andornot,如清单 2-5 所示。

a = True
b = False
print(a or b)

Output:
True

Listing 2-5Manipulation of boolean Data Type

数字运算符

表 2-1 总结了 Python 中可应用于数值数据类型的数值运算。

表 2-1

Python 中的数值运算符

|

操作员

|

操作

| | --- | --- | | ( ) | 圆括号 | | ** | 指数运算 | | * | 增加 | | / | 分开 | | + | 添加 | | - | 减法 | | % | 模运算 |

表 2-1 中的操作符按其优先顺序列出。当在代码的特定行中执行多个操作时,执行顺序将根据表 2-1 中的优先顺序。考虑示例 23* + 5 ,其中涉及乘法和加法。由于乘法的优先级高于加法,从表 2-1 中可以看出,乘法运算符(*)将首先被执行,给出2**3*=6,然后是加法运算符(+),这将给出 6 + 5 = 11 的最终结果。

序列数据类型

序列数据类型允许在一个变量中存储多个值。五类序列数据类型分别是listtuplestrsetdict

目录

列表是数据科学家在 Python 中最常用的数据类型。列表是元素的有序序列。列表中的元素不必是相同的数据类型。列表可以声明为用方括号[]括起来的逗号分隔的项目。列表是可变的;即列表中元素的值可以改变。列表中的元素从零开始索引,因此列表中的任何元素都可以通过其对应的索引来访问,如清单 2-6 所示。索引应该是整数,索引使用任何其他数据类型都会导致TypeError。类似地,试图访问列表范围之外的索引将导致IndexError

a = [1, 2.5, 5, 3+4j, 3, -2]
print("a is of type",type(a))
"'print the first value in the list"'
print("a[0]=",a[0])
"'print the third value in the list"'
print("a[2]=",a[2])
"' print the values from index 0 to 2"'
print("a[0:3]=",a[0:3])
"'print the values from index 4 till the end of the list"'
print("a[4:]=",a[4:])
"'Change the value at the index 3 to 4"'
a[3]=4
print("a=",a)
"'fractional index leads to TypeError"'
print(a[1.5])
"out of range index leads to IndexError"'
print(a[8])

Output of line 2: a is of type <class 'list'>
Output of line 4: a[0]= 1
Output of line 6: a[2]= 5
Output of line 8: a[0:3]= [1, 2.5, 5]
Output of line 10: a[4:]= [3, -2]
Output of line 13: a= [1, 2.5, 5, 4, 3, -2]
Otuput of line 15: TypeError: list indices must be integers or slices, not float
Output of line 17: IndexError: list index out of range

Listing 2-6Operations in a List

考虑分别存储在变量ab中的两个列表。表 2-2 显示了 Python 提供的一些附加操作,这些操作可以在列表ab上执行。其中一些函数也适用于元组、字符串和集合。

表 2-2

Python 中的列表操作

|

功能

|

描述

| | --- | --- | | a+b | 连接两个列表ab | | a*n | 将列表a重复n次,其中n是一个整数 | | len(a) | 计算列表a中元素的数量 | | a.append() | 将一个元素添加到列表的末尾a | | a.remove() | 从列表a中删除项目 | | a.pop() | 移除并返回列表a中给定索引处的元素 | | a.index() | 返回列表a中第一个匹配项的索引 | | a.count() | 返回列表a中作为参数传递的项目数 | | a.sort() | 按升序排列列表a中的项目 | | a.reverse() | 颠倒列表a中项目的顺序 |

元组

元组也是像列表一样的有序元素序列,但区别在于元组是不可变的;即,元组中的值不能改变。试图改变元组中某个元素的值会导致TypeError。通过将不会改变的数据存储为元组,可以确保它们保持写保护。元组可以声明为用圆括号括起来的逗号分隔的项,()。元组也可以像列表一样被索引,如列表 2-7 中所述。

a = (1, 3, -2, 4, 6)
print("a is of type",type(a))
print("a[3]=",a[3])
a[2] = 5

Output of line 2: a is of type <class 'tuple'>
Output of line 3: a[3]= 4
Output of line 4: TypeError: 'tuple' object does not support item assignment

Listing 2-7Operations in a Tuple

潜艇用热中子反应堆(submarine thermal reactor 的缩写)

str数据类型代表一个字符串。字符串可以声明为双引号(" ")内的字符。单引号(' ')也可以使用,但是由于它们在一些单词中以撇号的形式出现,所以使用双引号可以避免混淆。字符串中的字符的索引方式与列表和元组相同。字符串中两个单词之间的空格也被视为字符。像元组一样,字符串也是不可变的,如清单 2-8 所述。

a = "Hello World!"
print("a is of type",type(a))
print("a[3:7]=",a[3:7]
a[2] = "r"

Output of line 2: a is of type <class 'str'>
Output of line 3: a[3:7]= lo W
Output of line 4: TypeError: 'str' object does not support item assignment

Listing 2-8Operations in a String

设置

集合是项目的无序集合,因此不支持索引。集合由集合大括号{}内逗号分隔的值定义。集合可用于从序列中删除重复项。清单 2-9 显示了集合中的操作。

a = {1, 2, 3, 2, 4, 1, 3}
print("a is of type",type(a))
print("a=",a)

Output of line 2: a is of type <class 'set'>
Output of line 3: a= {1, 2, 3, 4}

Listing 2-9Operations in a Set

考虑分别存储在变量ab中的两个集合。表 2-3 说明了 Python 支持的可以应用于这两个集合的各种集合操作。

表 2-3

Python 中的集合运算

|

功能

|

描述

| | --- | --- | | a.union(b) | 返回新集合中两个集合ab的并集 | | a.difference(b) | 将两个集合ab的差作为新集合返回 | | a.intersection(b) | 返回两个集合ab的交集作为新集合 | | a.isdisjoint(b) | 如果两个集合ab有空交集,则返回True | | a.issubset(b) | 如果ab的子集,则返回True;即集合a的所有元素都出现在集合b中 | | a.symmetric_difference(b) | 将两个集合ab之间的对称差作为新集合返回 |

词典

一个dict表示字典数据类型,这是一个由键值对表示的无序数据集合。字典可以在大括号{}中定义,每个条目都是一对,形式为{key:value}。字典针对检索数据进行了优化,其中字典中的特定值可以通过使用其对应的键来检索。换句话说,该键充当该值的索引。键和值可以是任何数据类型。键通常是不可变的,不能在字典中重复,而值可能有重复的条目。试图访问字典中不存在的键将导致KeyError,如清单 2-10 中所述。

a = {1: 'Hello', 4: 3.6}
print("a is of type", type(a))
print(a[4])
print(a[2])

Output of line 2: a is of type <class 'dict'>
Output of line 3: 3.6
Output of line 4: KeyError: 2

Listing 2-10Operations in a Dictionary

类型变换

类型转换是将任何数据类型的值转换为另一种数据类型的过程。Python 为类型转换提供的函数如下:

  • int():将任意数据类型更改为int数据类型

  • float():将任意数据类型更改为float数据类型

  • tuple():将任何数据类型更改为元组

  • list():将任何数据类型更改为列表

  • set():将任何数据类型更改为集合

  • dict():将任何数据类型更改为字典

清单 2-11 展示了其中的一些功能。

a = 2
print(a)
float(a)
b = [2 , 3, -1, 2, 4, 3]
print(tuple(b))
print(set(b))

Output of line 2: 2.0
Output of line 4: (2, 3, -1, 2, 4, 3)
Output of line 5: (2, 3, 4, -1)

Listing 2-11Type Conversion Operations

控制流语句

控制流语句允许根据表达式的值执行一条或一组语句。控制流语句可以分为三类:顺序控制流语句,按照语句出现的顺序执行程序中的语句;决策控制流语句,根据条件是True还是False来执行或跳过语句块;以及循环控制流语句,允许多次执行语句块,直到满足终止条件。

如果语句

决策控制流语句类别中的if控制语句以if关键字开始,后跟一个条件语句,以冒号结束。条件语句评估一个布尔表达式,只有当布尔表达式评估为True时,才会执行if语句中的语句体。if block 语句以缩进开始,第一条没有缩进的语句标志结束。if语句的语法如下,清单 2-12 展示了它是如何工作的:

if <expression>:
     <statement(s)>

x = 12
y=8
if x > y:
   out = "x is greater than y"
   print(out)

Output: x is greater than y

Listing 2-12if Statement Operations

if-else 语句

if语句后面可以跟一个可选的else语句。如果if语句中条件语句对应的布尔表达式为True,则执行if块中的语句,如果布尔表达式为False,则执行else块中的语句。换句话说,if-else语句提供了一个双向决策过程。if-else语句的语法如下:

if <expression>:
     <statement(s)>

else:
     <statement(s)>

清单 2-13 显示了if-else语句的示例代码。

x = 7
y=9
if x > y:
   out = "x is greater than y"
else:
   out = "x is less than y"
print(out)

Output:
x is less than y

Listing 2-13if-else Statement Operations

如果... 否则如果...else 语句

if...elif...else语句可以提供多路决策过程。关键词elifelse-if的简称。如果需要从几个可能的选项中进行选择,elif语句可以和if语句一起使用。else语句将最后出现,作为默认动作。以下是if...elif...else语句的语法,清单 2-14 显示了示例代码:

if <expression>:
     <statement(s)>
elif <expression>:
     <statement(s)>
elif <expression>:
     <statement(s)>
...
else:
     <statement(s)>

x = 4
y=4
if x > y:
   out = "x is greater than y"
elif x<y:
   out = "x is less than y"
else:
   out = "x is equal to y"
print(out)

Output:
x is equal to y

Listing 2-14if...elif...else Statement Operations

while 循环

whilefor循环是循环控制流语句。在一个while循环中,条件语句中的布尔表达式被求值。只有当布尔表达式为True时,才会执行while循环中的语句块。循环块的每次重复被称为循环的一次迭代。每次迭代后检查while语句中的布尔表达式。循环继续执行,直到表达式变为False,此时while循环退出。while循环的语法如下,清单 2-15 显示了它是如何工作的:

while <expression>:
<statement(s)>

x=0
while x < 4:
      print("Hello World!")
      x=x+1

Output:
Hello World!
Hello World!
Hello World!
Hello World!

Listing 2-15while Loop Operations

for 循环

for循环使用一个迭代变量运行,该变量随着每次迭代而递增,并且这种递增一直持续到变量到达循环操作序列的末尾。在每一次迭代中,将获取与迭代变量给定的位置相对应的序列中的项,并使用这些项执行循环中的语句。for循环的语法如下:

for <iteration_variable> in <sequence>:
    <statement(s)>

range()函数在for循环中很有用,因为它可以生成一个数字序列,这个序列可以使用for循环进行迭代。range()函数的语法是range([start,] stop [,step]),其中start表示序列的开始(如果没有指定,从零开始),stop表示必须生成的数字的最大值(不包括数字本身),而step表示生成的序列中每两个连续数字之间的差值。起始值和步长值是可选的。range 参数生成的值应该总是整数。清单 2-16 显示了一个for循环,用于逐个打印字符串中的元素。

x = "Hello"
for i in x:
    print(i)

Output:
H
e
l
l
o

Listing 2-16for Loop Operations

清单 2-17 展示了如何使用range()函数打印一个整数序列。

for i in range(4):
    print(i)

Output:
0
1
2
3

Listing 2-17for Loop Operations with range Function

异常处理

异常只是在执行过程中检测到的错误。当程序中出现异常时,执行被终止,从而中断程序的正常流程。通过异常处理,可以向用户提供关于错误的有意义的信息,而不是系统生成的消息。例外可以是内置的,也可以是用户定义的。用户定义的异常是由用户创建的自定义异常,可以使用try...except语句来完成,如清单 2-18 所示。

while True:
try:
    n=int(input("Enter a number"))
print("The number you entered is",n)
     break
except ValueError:
    print("The number you entered is not
          the correct data type")
    print("Enter a different number")

Output:
Enter a number 5
The number you have entered is 5
Enter a number3.6
The number you entered is not the correct data type
Enter a different number

Listing 2-18Exception Handling

在清单 2-18 中,当一个变量接收到一个不合适的数据类型的值时,就会出现一个ValueError异常。如果没有异常发生,即输入的数字是一个整数,则跳过except程序块,只执行try程序块。如果在输入不同数据类型的数字时出现异常,则跳过try块中的其余语句,执行except块,程序返回到try块。

功能

函数是 Python 编程中的基本块,当需要在一个程序中多次执行一个语句块时,可以使用函数。可以通过对这一组语句进行分组并给它一个名称来创建函数,这样只需通过这个名称就可以在程序的任何部分调用这些语句,而不是重复整个块。因此,函数可以通过消除冗余代码来减少程序的大小。这些功能可以是内置的,也可以是用户定义的。

Python 解释器有许多内置函数,其中一些我们已经见过,比如print()range()len()等。另一方面,Python 使用户能够定义自己的函数,并根据需要使用它们。函数定义的语法如下:

def function_name(parameter1, ....  parameter n):
        statement(s)

函数名可以包含字母、数字或下划线,但不能以数字开头,也不能与关键字重名。让我们考虑一个简单的函数,它将单个参数作为输入,并计算其平方;参见清单 2-19 。

def sq(a):
    b = a * a
    print(b)
sq(36)

Output:1296

Listing 2-19Square Functions

让我们来看一个稍微复杂的函数,它计算给定十进制数的二进制表示。

如清单 2-20 所示,计算十进制数的二进制表示所需的五行代码可以用一行用户定义的函数来代替。

    import math as mt
    def dec2bin(a):
        b=' '
        while a!=0:
            b=b+str(a%2)#concatenation operation
            a=math.floor(a/2)
            return b[:-1]# reverse the string b
    print(int(dec2bin(19))

Output: 10011

Listing 2-20Square Functions

用于数据科学的 Python 库

Python 社区积极参与了许多面向各种应用程序的工具箱的开发。数据科学应用中最常用的一些工具箱有 NumPy、SciPy、Pandas 和 Scikit-Learn。

科学计算的 NumPy 和 SciPy

NumPy 是 Python 中可用的科学计算包。NumPy 支持多维数组、线性代数函数和矩阵。NumPy 数组表示为数据科学家提供了一种有效的数据结构。一个 NumPy 数组被称为一个 ndarray ,它可以使用array()函数创建。清单 2-21 展示了如何创建 1D 和 2D 数组以及如何索引它们的元素。

'''import the NumPy library'''
import numpy as np
'''creates an 1D array'''
a=np.array([1,2,3,4])
'''print the data type of variable a'''
print(type(a))
'''creates a 2D array'''
a=np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print(a)
'''print the dimension of the array'''
print(a.ndim)
'''print the number of rows and columns in the array'''
print(a.shape)
'''print the third element in the first row'''
print(a[0,2])
'''print the sliced matrix as per given index'''
print(a[0:2,1:3])
a=np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
'''reshape the 1 x 9 array into a 3 x 3 array'''
b=a.reshape(3,3))
print(b)

Output of line 6: <class 'numpy.ndarray'>
Output of line 9:
[[1 2 3 4]
 [5 6 7 8]]
Output of line 11: 2
Output of line 13: (2, 4)
Output of line 15:3
Output of line 17
[[2 3]
 [6 7]]
Output of line 21:
[[1 2 3]
 [4 5 6]
 [7 8 9]]

Listing 2-21Array Using NumPy

使用sum()可以计算任意维度数组中元素的总和。可以为数组中的所有元素计算总和,也可以沿着清单 2-22 中所示的一个维度为之前创建的数组b计算总和。

'''print the sum of elements in array b'''
print(b.sum())
'''print the sum of elements along each column'''
print(b.sum(axis=0))
'''print the sum of elements along each row'''
print(b.sum(axis=1))

Output:
Output of line 2: 45
Output of line 4: array([12,15,18])
Output of line 6: array([6, 15, 18])

Listing 2-22Array Using NumPy

关于数组的另一个重要操作是多维数组的展平。这个过程在许多基于机器学习的应用程序中更常见,可以通过使用flatten()函数来完成,如下所示:

b.flatten()
Output:
       array([1, 2, 3, 4, 5, 6, 7, 8, 9]

flatten()函数将任意维度的数组转换成一维数组。这也可以使用reshape()来实现,但是与flatten()函数不同,在这种情况下,必须指定一维数组的大小。表 2-4 描述了在使用数据分析应用程序时可能会派上用场的其他一些数组操作。

表 2-4

数据分析的 NumPy 函数

|

句法

|

描述

| | --- | --- | | np.ones() | 在括号内指定的维度中创建一个 1 的数组。 | | np.zeros() | 在括号内指定的维度中创建一个零数组。 | | np.flip(a,axis) | 沿给定轴反转数组a。如果未指定 axis,数组将沿两个维度反转。 | | np.concatenate(a,b,axis) | 沿指定轴串联两个数组ab(=01对应垂直和水平方向)。 | | np.split(a,n) | 将数组a分割成n个更小的数组。这里的n可以是任意正整数。 | | np.where(a==n) | 给出数组a中数字n的索引值。 | | np.sort(a,axis) | 沿给定轴对数组a中的数字进行排序。 | | np.random.randint(n,size) | 使用从 0 到数字n的整数生成给定大小的数组。 |

SciPy 生态系统是基于 Python 的 NumPy 扩展构建的科学计算开源软件集合。它提供了操作和可视化数据的高级命令。这个生态系统的两个主要组件是 SciPy 库和 Matplotlib,前者是数值算法和特定领域工具箱的集合,后者是提供 2D 和 3D 绘图的绘图包。以下语法可用于在代码中导入和使用 SciPy 模块中的任何函数:

from scipy import some_module
some_module.some_function()

根据官方 SciPy 文档,该库被组织成覆盖不同领域的不同子类型,如表 2-5 中所总结的。

表 2-5

SciPY 中的子包

|

分装

|

描述

| | --- | --- | | cluster | 聚类算法 | | constants | 物理和数学常数 | | fftpack | 快速傅立叶变换例程 | | integrate | 积分和常微分方程解算器 | | interpolate | 插值和平滑样条 | | io | 输入和输出 | | linalg | 线性代数 | | ndimage | n 维图像处理 | | odr | 正交距离回归 | | optimize | 优化和求根例程 | | signal | 信号处理 | | sparse | 稀疏矩阵和相关例程 | | spatial | 空间数据结构和算法 | | special | 特殊功能 | | stats | 统计分布和函数 |

sci kit-为机器学习而学习

Scikit-Learn 是一个用于 Python 编程的开源机器学习库,具有各种分类、回归和聚类算法。它旨在与其他 Python 库(如 NumPy 和 SciPy)进行互操作。

用于数据分析的 Pandas

Pandas 是一个快速而强大的开源库,用于 Python 编程中的数据分析和操作。它有一个快速有效的DataFrame对象,用于集成索引的数据操作。它具有在内存数据结构和不同文件格式(如 CSV、Microsoft Excel 等)之间读写数据的工具。考虑一个名为data.csv的 CSV 文件,其中包含三名学生在三个科目上的成绩,如图 2-5 所示。清单 2-23 显示了使用 Pandas 读取和访问这些数据的过程。

img/496535_1_En_2_Fig5_HTML.png

图 2-5

包含学生成绩数据的 CSV 文件

import pandas as pd
'''reads the file data.csv with read_csv package and the header=None option allows pandas to assign default names to the colums
Consider the data in the above table is typed in a excel sheet and saved as csv file in the following path C:\Python_book\data.csv
'''
d = pd.read_csv("C:\Python_book\data.csv",header=None)
print(type(d))
print(d)
"'print the element common to row1-column2"'
print(d.loc[1,2])
"'print the elements common to rows 1,2 and
  columns 1,2"'
d.loc[1:2, 1:2]

Output of line 4:
<class 'pandas.core.frame.DataFrame'>
Output of line 5:
     0           1       2           3
0  Roll No    Science  Maths   English
1    RN001       70        76          85
2    RN002       86        98          88
3    RN003       76        65          74
Output of line 7: 76
Output of line 9:
    1      2
1   70   76
2   86   98

Listing 2-23Data Modification Using Pandas Functions

同样,还有其他的读取功能如read_excelread_sqlread_html等。,读取其他格式的文件,每一个读取函数都带有相应的写入函数,如to_csvto_excelto_sqlto_html等。,它允许你把 Pandas 数据帧写成不同的格式。

从传感器收集的大部分实时数据是时间序列数据的形式,即按时间顺序索引的一系列数据。让我们考虑一个数据集,它由澳大利亚墨尔本 10 年(1981 年到 1990 年)的最低日气温(摄氏度)组成。数据来源是澳大利亚气象局。尽管这也是一个 CSV 文件,但与上图中的DataFrame不同,它是时间序列数据。清单 2-24 展示了探索时序数据的不同方法。

Series=pd.read_csv('daily-min-
             temperatures.csv',header=0, index_col=0)
"'prints first 5 data from the top of the series"'
print(series.head(5))
"'prints the number of entries in the series"'
print(series.size)
print(series.describe())
"'describe() function creates 7 descriptive   statistics of the time series data including mean, standard deviation, median, minimum, and maximum of the observations"'

      Output of line 3:
   Date                  Temp
1981-01-01            20.7
1981-01-02            17.9
1981-01-03            18.8
1981-01-04            14.6
1981-01-05            15.8
Output of line 5: 3650
Output of line 6:
            Temp
count  3650.000000
mean     11.177753
std       4.071837
min       0.000000
25%       8.300000
50%      11.000000
75%      14.000000
max      26.300000

Listing 2-24Data Modification in Pandas

用于机器学习的张量流

TensorFlow 是 Google Brain 团队打造的机器学习端到端开源平台。TensorFlow 有很多机器学习模型和算法。它使用 Python 提供一个前端 API,用框架构建应用程序。Keras 是一个运行在 TensorFlow 之上的高级神经网络 API。Keras 允许简单快速的原型制作,并支持卷积网络和递归神经网络。

三、树莓派简介

Raspberry Pi,简称 Pi,是由英国 Raspberry Pi 基金会发明的一系列小型、低成本、单板计算机,旨在向世界各地的学生推广基础计算机科学和电子技术。学生和技术爱好者使用 Raspberry Pi 学习编程概念,构建硬件项目和机器人,以及制作人工智能项目。它也用于工业应用。

你能用覆盆子酱做什么?

一个 Raspberry Pi 板可以做几乎所有台式电脑可以做的事情:上网冲浪,观看高清视频,听音乐,查看和编辑图片,进行文字处理,制作电子表格和演示文稿,编写和编译代码,参加视频会议,甚至玩游戏。

使用 Raspberry Pi 进行物理计算

树莓皮也可以用来与物理世界互动。这是通过 Raspberry Pi 板上的通用输入/输出(GPIO)引脚实现的。这使得 Raspberry Pi 功能强大,因为它可以与传感器和其他电气和电子组件连接,如 led、伺服和步进电机、继电器等。

树莓派怎么编程?

Raspberry Pi 附带了两种预装语言(Scratch 和 Python),但它也支持其他语言。Scratch 是面向儿童的可视化编程语言,而 Python 是高级通用编程语言;这两种语言都很容易学。如果你学习用 Python 编程,那么你可以用 Raspberry Pi 做任何可能的事情。

Raspberry Pi 硬件

树莓派基金会于 2012 年发布了首款树莓派——树莓派 B 型。在那之后发布了许多改进的版本,我们将在后面查看所有这些版本。最新版本是 2019 年 6 月发布的树莓 Pi 4 model B。图 3-1 显示了带有许多 I/O 端口的 Raspberry Pi 板的俯视图。我们先来看看它的硬件规格和其他特性。

img/496535_1_En_3_Fig1_HTML.jpg

图 3-1

Raspberry Pi 硬件

片上系统

图 3-2 所示的片上系统 (SoC),是树莓派的大脑。这个小芯片由许多重要部分组成:中央处理器(CPU)、图形处理器(GPU)和数字信号处理器。

img/496535_1_En_3_Fig2_HTML.jpg

图 3-2

片上系统

树莓 Pi 4 model B 拥有强大的 Broadcom BCM2711 (1.5 GHz 64 位四核)SoC。Pi 的 CPU 执行基本算术、逻辑、控制和输入/输出等操作,而 Pi 的 GPU 用于处理多媒体任务,如数字图像处理、绘制 3D 图形和玩游戏。

树莓皮公羊

随机存取存储器(RAM)是树莓 Pi 4 model B 中位于 SoC 旁边的黑色矩形,如图 3-3 所示。在以前版本的 Raspberry Pi 中,RAM 封装在 SoC 内部。Pi 4 提供了三种 LPDDR4 RAM 选择:1GB、2GB 和 4GB。

img/496535_1_En_3_Fig3_HTML.jpg

图 3-3

树莓皮公羊

RAM 存储应用程序使用的短期数据,当 Raspberry Pi 关闭时,这些数据将被删除。RAM 由中央处理单元和图形处理单元共享。

连通性

树莓 Pi 4 型号 B 具有板载 Wi-Fi、蓝牙和千兆以太网。这些功能对于远程访问 Raspberry Pi 非常方便,使其成为物联网(IoT)项目的理想硬件选择。这也释放了 USB 端口和 GPIO 引脚,用于连接外部 Wi-Fi 和蓝牙模块。

设置树莓 Pi

本节解释如何设置树莓 Pi。

微型存储卡

与台式机和笔记本电脑不同,Raspberry Pi 使用 microSD 存储卡来存储文件、应用程序甚至操作系统。与硬盘相比,microSD 存储卡体积较小,易于使用。Pi 至少需要 8GB 的内存。对于数据科学项目,建议使用 16GB 或 32GB 的 microSD 存储卡。建议使用 10 级超高速(UHS)存储卡,以便更快地读取/写入数据。

安装操作系统

Raspbian 是树莓 Pi 基金会发布的树莓 Pi 的官方和最常用的操作系统。使用 Raspberry Pi Imager 软件可以很容易地将其安装在 microSD 卡上,如图 3-4 所示。树莓派还支持其他操作系统,如 Ubuntu 和 Windows 10 IOT 核心。

img/496535_1_En_3_Fig4_HTML.jpg

图 3-4

Raspberry Pi 成像仪软件的界面

按照以下说明在您的 Raspberry Pi 中安装 Raspbian 操作系统:

  1. 访问 Raspberry Pi 网站的下载页面,并在您的操作系统上下载 Raspberry Pi 成像仪软件。

  2. 下载完成后,通过单击启动安装程序。

  3. 将 microSD 存储卡插入电脑。请务必备份卡中的任何重要数据,因为存储在卡中的任何数据都将被格式化。

  4. 选择您想要安装的 Raspbian 或其他所需的操作系统,以及您想要安装的 microSD 卡。

  5. 最后,单击 Write 按钮,等待操作完成。

插入 microSD 存储卡

树莓 Pi 底面的细金属槽,如图 3-5 所示,是 microSD 存储卡槽。一旦操作系统安装在 microSD 存储卡上,将其插入 Raspberry Pi 的存储卡插槽。

img/496535_1_En_3_Fig5_HTML.jpg

图 3-5

MicroSD 卡插槽

由于操作系统与其他文件一起存储在 microSD 存储卡上,这使得 Pi 的存储器可移植。microSD 存储卡可以插入新的 Raspberry Pi,它会像魔咒一样工作。

连接键盘和鼠标

图 3-6 显示了 Raspberry Pi 引脚的 USB 端口。树莓 Pi 4 型号 B 有两个 USB 2.0 端口(黑色)和两个通用串行总线(USB) 3.0 端口(蓝色)。USB 可用于连接键盘、鼠标、网络摄像头和其他 USB 外围设备。USB 3.0 端口比 USB 2.0 端口快大约 10 倍。通常,键盘和鼠标等外围设备连接到 USB 2.0 端口,而更快的 USB 3.0 端口则用于硬盘和网络摄像头等设备。

img/496535_1_En_3_Fig6_HTML.jpg

图 3-6

USB 连接埠

如果您有无线键盘和鼠标而不是有线组合,可以通过将 USB 加密狗连接到两个黑色端口中的一个来将它们连接到 Raspberry Pi。这也释放了一个 USB 端口,可用于连接其他设备。

连接显示器

Raspberry Pi 可以通过图 3-7 所示的 micro-HDMI 端口连接到显示器。HDMI 代表高清多媒体接口,Raspberry Pi 从该端口提供组合音频和视频输出。Raspberry Pi model 4 带有两个支持 4K 的微型 HDMI 端口,这意味着您可以同时将两个 4K 显示器连接到 Raspberry Pi。

img/496535_1_En_3_Fig7_HTML.jpg

图 3-7

HDMI 端口

如果您的电视或显示器支持 HDMI 输入,那么您将需要一根微型 HDMI 转 HDMI 电缆来将 Raspberry Pi 连接到您的电视或显示器。旧版本的 Raspberry Pi 带有一个 HDMI 端口。如果您的电视或显示器有 VGA 输入,那么您需要使用微型 HDMI-VGA 适配器将其连接到 Raspberry Pi。同样,您可以将 HDMI 转 DVI 电缆用于带有 DVI 输入的显示器。

为树莓派供电

树莓派 4 B 需要通过 5.1V DC USB-C 型连接器供电,如图 3-8 所示,最小电流输入为 3A。它也可以通过 GPIO 接头供电。USB-C 型电源端口位于树莓派的一角附近。没有一款 Raspberry Pi 机型有开/关开关;一旦你将树莓派连接到电源,它就会打开。

img/496535_1_En_3_Fig8_HTML.jpg

图 3-8

USB-C 型连接器

提供不正确的电压或不足的电流会导致树莓皮损坏;因此,建议使用官方的 Raspberry Pi 电源。

树莓皮围栏

Raspberry Pi 需要封装在一个盒子里,以防止裸露的连接和 GPIO 头。树莓派有多种外壳案例可供选择,或者您可以自己制作案例,但建议使用树莓派基金会发布的官方案例。还提供带冷却风扇的机箱。它们可用于防止 Pi 在运行重型应用程序时过热。

树莓 Pi 版本

本节解释了不同的版本。

树莓 Pi 1

树莓 Pi B 是树莓 Pi 基金会在 2012 年推出的第一款机型,随后在 2013 年推出了 Pi A。它们有 26 个 GPIO 引脚,700MHz 处理器,256MB/512MB 内存,没有任何内置 Wi-Fi 或蓝牙。2014 年发布了 40 个 GPIO 引脚的紧凑型 Pi A+和改进的 B+型号。

树莓 Pi 2

树莓 Pi 2 于 2015 年发布,采用改进的 900MHz 四核处理器和 1GB RAM。这款机型有 40 个 GPIO 引脚,没有内置 Wi-Fi 或蓝牙。它有四个 USB 2.0 端口、一个以太网端口和一个 HDMI 端口。

树莓 Pi 3

2016 年,树莓 Pi 3 发布。它有一个 1.2GHz 的四核处理器和 1GB 内存。这个型号有 40 个 GPIO 引脚,这是第一个内置 Wi-Fi 和蓝牙的 Raspberry Pi 型号。类似于 Raspberry Pi 2,它有四个 USB 2.0 端口,一个以太网端口和一个 HDMI 端口。2018 年晚些时候,推出了紧凑型 Pi 3 A+和改进的 Pi 3 B+车型。

树莓派零度(W/WH)

2015 年推出了小尺寸、低成本、GPIO 引脚更少的 Raspberry Pi Zero。Pi Zero W 于 2017 年发布,内置 Wi-Fi 和蓝牙。接下来是预焊 GPIO 头附带的 Pi 零 WH。

树莓 Pi 4

树莓 Pi 4 model B 于 2019 年发布,拥有强大的 1.5GHz 四核处理器和 1GB/2GB/4GB RAM 选项。这是第一款带有双 4K 显示输出、USB-C 型电源输入和两个 USB 3.0 端口的型号。

推荐树莓 Pi 版本

有不同版本的 Raspberry Pi 可用,但建议数据科学项目使用 Raspberry Pi 4,因为它比其他版本更强大,并且还提供高达 4GB 的 RAM 选项。

Raspberry Pi Zero WH 是可用的 Raspberry Pi 的最小变体,当单板计算机的尺寸需要很小时,建议使用它。但它配备了相对较慢的处理器、更少的 RAM 和更少的 GPIO 引脚。

Raspberry Pi 与传感器的接口

本节重点介绍如何将 Raspberry Pi 与传感器连接起来。

GPIO 引脚

图 3-9 所示的 GPIO 引脚是 Raspberry Pi 最强大的功能之一。GPIO 引脚是沿着电路板边缘的一排小引脚。最近发布的所有 Raspberry Pi 版本都有一个 40 引脚 GPIO 头。这些图钉是树莓派和现实世界之间的联系。GPIO 引脚可以在软件中指定为输入或输出,并可用于各种目的,如打开/关闭 led、控制伺服电机以及从传感器获取数据。它们可以用 Python 或任何其他语言编程,如 Scratch 或 C/C++。

img/496535_1_En_3_Fig9_HTML.jpg

图 3-9

Raspberry Pi GPIO 引脚

GPO 皮诺曹

在连接到 Raspberry Pi GPIO 引脚之前,我们需要知道 GPIO 引脚参考。引脚排列配置不打印在 Raspberry Pi 上,但是我们可以通过打开终端窗口并键入命令pinout来获取任何 Raspberry Pi 的引脚排列参考。这个工具是由gpiozero库提供的,预装在 Raspbian OS 上。

GPIO 输出

树莓 Pi 有两个 5V 管脚和两个 3V3 管脚;它还有 8 个无法配置的接地引脚(0V)。其余 28 个引脚都是通用 3V3 引脚。这些引脚的输出设置为 3V3,或者可以接收最高 3V3 的输入。指定为输出引脚的 GPIO 引脚可以设置为高电平(3V3)或低电平(0V)。

用 Python 控制 GPIO 输出

使用 Python 的gpiozero库可以轻松控制 GPIO 引脚。让我们看一个简单的 Python 例子,演示如何打开/关闭连接到 GPIO 引脚的 led。led 总是需要通过一个电阻连接到 GPIO 引脚。电阻器将确保只有小电流在电路中流动;因此,树莓派或 LED 将受到保护免受损坏。

我们将通过一个 330ω的电阻将一个 LED 连接到 GPIO 引脚 17,如图 3-10 所示。现在,可以使用清单 3-1 中给出的 Python 代码让 LED 持续打开和关闭。led.on()功能打开 LED,led.off()功能关闭 LED。

img/496535_1_En_3_Fig10_HTML.jpg

图 3-10

将 LED 连接到 GPIO 引脚

from gpiozero import LED
from time import sleep
led = LED(17)
while True:
      led.on()
      sleep(1)
      led.off()
      sleep(1)

Listing 3-1LED Function Using GPIO

GPIO 输入信号

指定为输入引脚的 GPIO 引脚可以读取为高电平(3V3)或低电平(0V)。这意味着 GPIO 引脚不支持模拟输入,只能接收数字输入。虽然 Raspberry Pi 中没有模数转换器硬件,但我们可以使用 MCP3008 等外部 ADC 从传感器读取模拟数据。

用 Python 读取 GPIO 输入

通过将传感器连接到 GPIO 引脚,可以轻松地与 Raspberry Pi 接口。通过将传感器的 VCC 连接到树莓 Pi 的 3.3V/5V,并将传感器的 GND 连接到树莓 Pi 的 GND,可以为传感器供电。传感器的数字输出可以直接连接到 GPIO 引脚并读取。但在读取模拟输出时,模数转换器需要将模拟传感器与 Raspberry Pi 接口。

来自传感器的数字信号

Raspberry Pi 将任何低于 1.8V 的输入视为低电平(0),将任何高于 1.8V 的输入视为高电平(1),如图 3-11 所示。使用InputDevice.value功能可以轻松读取任何传感器的数字输出数据。该函数返回给定 GPIO 引脚的当前状态。

img/496535_1_En_3_Fig11_HTML.jpg

图 3-11

低和高输入

清单 3-2 中的代码每秒打印一次 GPIO 管脚 17 的状态。

from gpiozero import InputDevice
from time import sleep
sensor = InputDevice(17, pull_up=True)
while True:
      print(sensor.value)
      sleep(1)

Listing 3-2State of GPIO

来自传感器的模拟信号

图 3-12 显示了一个模拟信号。要从传感器或其它器件读取模拟信号,我们应该使用一个模数转换器,如用于 Raspberry Pi 的 MCP3008。ADC 将模拟信号转换成数字信号。串行外设接口(SPI)协议用于将 ADC 的输出传输至 Raspberry Pi。

img/496535_1_En_3_Fig12_HTML.jpg

图 3-12

模拟信号

要启用 SPI 通信,请从主菜单打开 Raspberry Pi 配置,并在接口选项卡上启用 SPI。MCP3008 是一款 10 位 ADC,有 8 个输入通道(0–7)。让我们将模拟输入连接到 MCP3008 的第一个通道(0)和 MCP3008 的其他引脚,如图 3-13 所示。

img/496535_1_En_3_Fig13_HTML.jpg

图 3-13

10 位模数转换器 MCP3008

清单 3-3 中的代码每秒打印连接到 MCP3008 第一通道(0)的传感器的模拟值。由于 MCP3008 是一个 10 位 ADC,输出值范围为 0 至 1023。

from gpiozero import MCP3008
from time import sleep
sensor = MCP3008(0)
while True:
      print(sensor.value)
      sleep(1)

Listing 3-3Implement the MCP3008

将超声波传感器与 Raspberry Pi 接口

超声波传感器通过发现声波的时间来测量物体的距离。HC-SR04 超声波传感器可用于测量 2 厘米至 400 厘米的距离,精度为 3 毫米。超声波传感器通过发出频率为 40kHz 的声波来工作,这一频率高于人类的听觉范围,并通过空气传播。如果有障碍物或物体,声波会反弹回传感器。物体的距离可以通过传播时间的一半乘以声速来计算。图 3-14 显示了超声波传感器及其引脚,其中 VCC 引脚需要连接到树莓 Pi 的正极端子,GND 引脚可以连接到树莓 Pi 的 GND 引脚,Trig 引脚用于触发超声波脉冲,Echo 引脚在接收到反射声波时产生脉冲。

img/496535_1_En_3_Fig14_HTML.jpg

图 3-14

超声波传感器引脚

将超声波距离传感器连接到树莓皮上,如图 3-15 所示。

img/496535_1_En_3_Fig15_HTML.jpg

图 3-15

带 Raspberry Pi GPIO 引脚的超声波传感器

gpiozero库中有一个名为DistanceSensor的对象,可以使用 Python 中的超声波传感器来测量距离。距离函数返回超声波距离传感器测量的距离,单位为米。让我们将该值乘以 100,将其转换为厘米。清单 3-4 中的代码连续打印超声波距离传感器每秒测量的距离,单位为厘米。

from gpiozero import DistanceSensor
from time import sleep

sensor = DistanceSensor(echo=17, trigger=4)

while True:
    print(sensor.distance * 100)
    sleep(1)

Listing 3-4Code for calculting distance measured by the Ultrasonic Sensor

当代码运行时,移动放置在超声波传感器前面的物体的位置以获得不同的值。

将温度和湿度传感器与 Raspberry Pi 接口

顾名思义,这些传感器可以用来测量温度和湿度。它们由一个电容式湿度感测元件和一个用于感测温度的热敏电阻组成。温度和湿度传感器有一个专用的电阻式湿度测量组件,称为负温度系数 (NTC)温度测量组件,以及一个 8 位微控制器,以串行数据的形式输出温度和湿度值。单总线数据格式用于 Raspberry Pi 和 DHT11 传感器之间的通信和同步。

DHT 11 和 DHT 22 是常用的温度和湿度传感器。图 3-16 显示了温度和湿度传感器(THD ),图 3-17 解释了 THD 与 Raspberry Pi 的接口,其中 VCC 引脚需要连接到 Raspberry Pi 的正极端子,GND 引脚可以连接到 Raspberry Pi 的 GND,信号/数据引脚用于串行通信,需要连接到 GPIO 引脚。

img/496535_1_En_3_Fig16_HTML.jpg

图 3-16

温度和湿度传感器

将 DHT 11/22 传感器模块连接到 Raspberry Pi,如图 3-17 所示。

img/496535_1_En_3_Fig17_HTML.jpg

图 3-17

带 Raspberry Pi GPIO 引脚的温度和湿度传感器

让我们使用Adafruit_DHT库从传感器获取温度和湿度值。清单 3-5 中的代码连续打印摄氏温度和湿度百分比。

import Adafruit_DHT
import time

DHT_SENSOR = Adafruit_DHT.DHT11
DHT_PIN = 17

while True:
    humidity, temperature =
        Adafruit_DHT.read(DHT_SENSOR, DHT_PIN)
    if humidity is not None and temperature is not None:
        print("Temperature="{0:0.1f}C)
      humidity={1:0.1f}%".format(temperature, humidity))
    else:
        print("Sensor not connected.");
    time.sleep(3);

Listing 3-5Code for Temperature and Humidity Sensor

可以使用以下代码将 Adafruit 模块安装在 Raspberry Pi 中。

对于 Python 2:

sudo pip install Adafruit_DHT

对于 Python 3:

sudo pip3 install Adafruit_DHT

将土壤湿度传感器与树莓接口

土壤湿度传感器用于检测土壤中的湿度。土壤湿度传感器由两个探头组成,用于测量土壤中的湿度。该传感器使用电容来测量土壤的介电常数,它是土壤含水量的函数。该传感器配有模拟和数字输出,因此它可以在模拟和数字模式下使用。但是,让我们从传感器获取模拟信号,并使用 Python 读取它。图 3-18 所示为土壤湿度传感器。这里,VCC 引脚需要连接到 Raspberry Pi 的正端,模拟输出(AO)产生一个与介电常数成比例的电压,从而与土壤含水量成比例,当土壤湿度高于阈值时,数字输出(DO)产生一个脉冲。阈值使用传感器模块中的电位计设置,GND 引脚可以连接到 Raspberry Pi 的 GND。

img/496535_1_En_3_Fig18_HTML.jpg

图 3-18

土壤湿度传感器

通过 MCP3008 ADC 将土壤湿度传感器模块连接到 Raspberry Pi,如图 3-19 所示。

img/496535_1_En_3_Fig19_HTML.jpg

图 3-19

带 Raspberry Pi GPIO 引脚的温度和湿度传感器

让我们使用gpiozero库中的 MCP3008 模块从 MCP3008 中获取值。清单 3-6 中的代码每秒连续打印土壤湿度传感器的模拟值。

from gpiozero import MCP3008
from time import sleep

soil_sensor = MCP3008(0)

while True:
    print(soil_sensor.value)
    sleep(1)

Listing 3-6Code for interfacing soil moisture sensor

将相机与树莓 Pi 接口

相机是使用图像传感器记录图像的光学仪器。图像传感器检测并传送用于生成图像的信息。相机可以很容易地与 Raspberry Pi 接口,以获取图像或视频数据。有两个选项可用于将摄像机与 Raspberry Pi 接口。

方法 1: 第一种方法是使用 USB 端口将 USB 网络摄像头连接到 Raspberry Pi。图 3-20 显示了一个 USB 网络摄像头。一旦 USB 网络摄像头连接正确,就可以使用OpenCV库在 Python 中访问它。OpenCV是一个用于图像处理和实时计算机视觉的 Python 库。清单 3-7 中的代码可用于将 USB 网络摄像头连接到 Raspberry Pi。

img/496535_1_En_3_Fig20_HTML.jpg

图 3-20

USB 网络摄像头

import cv2

videoCaptureObject = cv2.VideoCapture(0)
result = True

while(result):
    ret,frame = videoCaptureObject.read()
    cv2.imwrite("/home/pi/Desktop/webcam_image.jpg ",frame)
    result = False

videoCaptureObject.release()
cv2.destroyAllWindows()

Listing 3-7Code for Connecting USB Web Cameras with the Raspberry Pi

方法 2: 另一种方法是通过摄像头串行接口(CSI)端口连接 Raspberry Pi 摄像头模块。图 3-21 为树莓派相机。有两个 Raspberry Pi 相机模块可供选择:一个标准模块和一个黑色相机模块,用于在黑暗中拍照。要启用 Raspberry Pi 摄像头,请从主菜单打开 Raspberry Pi 配置,并在接口选项卡上启用摄像头。

img/496535_1_En_3_Fig21_HTML.jpg

图 3-21

带 CSI 的 Raspberry Pi 摄像机

清单 3-8 中的代码从 Raspberry Pi 相机模块中获取一张图片,并将图片存储在指定的位置。

from picamera import PiCamera
from time import sleep

camera = PiCamera()

camera.start_preview()
sleep(5)
camera.capture('/home/pi/Desktop/cammodule_img.jpg')
camera.stop_preview()

Listing 3-8Code for Connecting Raspberry Pi Camera with the Raspberry Pi

作为边缘设备的树莓皮

在数据源或其附近进行的计算被称为边缘计算。在需要即时或实时计算的领域,以及无法连接到中央云或连接受限的远程位置,边缘计算优于云计算。边缘计算的最大优势是其减少延迟的能力,因为传感器收集的数据在边缘设备中处理,不需要传输到数据中心。见图 3-22 。

img/496535_1_En_3_Fig22_HTML.jpg

图 3-22

树莓皮作为边缘装置

无人驾驶汽车中的边缘计算

自动驾驶汽车将依赖边缘计算,因为在路上行驶时,每一毫秒都非常重要。从他们的传感器和相机收集的大量数据不能被发送到云中进行分析,因为这将花费相当多的时间,并且还需要不间断的网络。因此,边缘计算因其更快的速度和高可靠性而成为这类应用的首选。

什么是边缘设备?

边缘计算在边缘设备中完成。边缘设备能够实时收集、存储和处理数据。因此,边缘设备提供了更快的响应并具有更好的可靠性。传感器和其他设备通过有线电缆或无线连接(如 Wi-Fi 或蓝牙)连接到边缘设备,如图 3-22 所示。有时,边缘设备连接到一个集中式云,用于大数据处理和数据仓库。

使用 Raspberry Pi 进行边缘计算

Raspberry Pi 具有良好的计算能力,能够通过有线和无线连接来连接传感器和设备。Raspberry Pi 还支持许多计算机编程语言,如 Python、C/C++和 Java。这使得 Raspberry Pi 成为边缘计算的绝佳选择。

作为本地化云的 Raspberry Pi

在这一章中,我们将讨论使用 Raspberry Pi 作为本地化的云。

云计算

云计算是使用互联网上的远程服务器网络来存储、管理和处理数据的实践。这些远程服务器被称为云服务器,位于世界各地的数据中心。从这类服务器访问数据需要强大的互联网连接。

树莓 Pi 作为本地化云

如今,物联网设备高速生成海量数据。通常,这些数据需要实时处理才能做出快速决策,而这可以由本地化云提供支持。此外,一些物联网传感器网络部署在互联网连接稀疏的偏远地区,这对本地化云的概念提出了挑战。Raspberry Pi 可以作为本地化的云来支持更接近物联网网络的实时数据处理。它需要通过以太网或 Wi-Fi 连接到网络。作为本地化云的 Raspberry Pi 可用于存储和处理从传感器或其他设备(如电脑和手机)收集的数据,如图 3-23 所示。

img/496535_1_En_3_Fig23_HTML.jpg

图 3-23

作为本地化云的 Raspberry Pi

连接外部硬盘

外部硬盘驱动器可以连接到 Raspberry Pi 以增加其存储容量。这些硬盘需要使用外部电源供电。如果没有电源,它们可以通过通电的 USB 集线器连接。这种增强的存储可以让 Raspberry Pi 收集和处理来自物联网网络的大量实时数据。

连接 USB 加速器

Coral USB Accelerator 是一个超快速的开发板,用于深度学习从业者在不需要互联网的情况下部署他们的模型,从而实现边缘计算。它为树莓派带来了机器学习界面。它由一个边缘 TPU 协处理器组成,每秒能够执行 4 万亿次运算(万亿次运算)。这使得实时运行 ML 模型成为可能。例如,该设备可以帮助 Raspberry Pi 以 400 FPS 的速度运行 MobileNet v2 模型。

四、传感器和信号

本章包括传感器和信号。

信号

通常,信号代表关于时间或空间的一些信息。例如,汽车速度随时间的变化就是一种信号。信息可以以信号的形式传递。在电气工程中,信号是一个携带时间或空间信息的函数。电气设备以电压、电流或电磁波的形式显示信号。根据 IEEE 信号处理汇刊,信号可以是音频、视频、语音、图像、声纳、雷达相关等等【1】。同样,从数学上讲,信号是一个或多个独立变量的函数。自变量就是那些不会被你试图测量的其他变量改变的变量。例如,考虑温度随时间的变化。这里,时间是独立变量,因为时间不会因为温度的变化而改变。

本章讨论如何通过 Raspberry Pi 使用传感器从实时环境中获取信息,然后将这些信息转换为结构化数据。传感器输出是电信号的形式。本章首先描述关于信号及其各种类型。信号有许多分类,我们集中描述以下电信号:

  • 模拟和数字信号

  • 连续时间和离散时间信号

  • 确定性和非确定性信号

  • 一维信号、二维信号、多维信号

模拟和数字信号

a 模拟信号表示相对于独立变量(即时间)连续变化的物理量的瞬时值。简单来说,模拟信号在时间和幅度上都是连续的。物理量可以是温度、压力、速度等。传感器可以将物理量的变化转换成电信号,如电压或电流。这样,可以使用传感器以电信号的形式收集实时环境数据。

数字信号是用于将数据表示为离散值序列的信号。独立变量(即时间)是离散的,并且具有量化的振幅。通过对模拟信号进行采样和量化,可以获得数字信号。在任何给定时间,数字信号只能呈现有限数量的值中的一个。

连续时间和离散时间信号

连续时间信号连续信号是在其域(通常是时间)的连续体上定义的信号。任何模拟信号本质上都是连续的。

离散时间信号离散信号是自变量(时间)只有离散值的信号。它是由一系列数量组成的时间序列。数字信号处理中使用的离散时间信号可以通过对连续信号进行采样和量化来获得。

确定性和非确定性信号

确定性信号是相对于其在任何时刻的值没有不确定性的信号。换句话说,可以使用数学公式精确定义的信号是确定性信号。

非确定性信号随机信号是在某一时刻其值具有不确定性的信号。由于其随机性,该信号也被称为随机信号,并且该信号不能用数学方程来描述。

一维、二维和多维信号

一个一维信号仅仅是一个独立变量的函数。语音信号是一维信号的一个很好的例子,因为语音的幅度只取决于一个自变量(即时间)。

同样,如果信号是两个因变量的函数,则该信号称为二维信号。灰度图像是二维信号的一个例子。空间坐标(x,y)是图像中的两个独立变量。多维信号是两个以上变量的函数。电影(即视频)是多维信号的最佳例子。

收集实时数据

收集数据有两种方式:手动和自动。在手动方法中,可以从现有文件和文档中收集数据。然后,可以手动将收集的数据组织成结构化的方式(即,表格格式)。在自动化领域,可以使用一些叫做传感器的设备来收集数据。温度、压力、图像等物理量的实时信息。,可以使用传感器收集。本章重点描述使用传感器的自动数据收集。为了使数据收集自动化,需要数据采集系统。本节说明如何使用传感器收集数据,如超声波传感器、湿度、温度和来自摄像机的图像数据。此外,还讨论了以结构化格式存储收集的数据。

数据采集

对测量真实世界物理条件的信号进行采样,并将结果样本转换为可由计算机处理的数字数值的过程称为数据采集。数据采集系统(DAS 或 DAQ)通常将模拟信号转换为数字值进行处理。数据采集系统包括以下三个部分:

  • 传感器

  • 信号调理电路

  • 模数转换器

传感器

通常,传感器产生与环境变化相对应的电信号。传感器是一种转换温度、湿度、距离等物理参数的装置。转换成电信号。传感器可以是能够检测环境中的事件或变化并将信息发送到其他电子设备(通常是计算机处理器)的设备、模块、机器或子系统。例如,热电偶是一种温度传感器,它根据输入温度变化产生输出电压。根据其输出信号类型,有两种类型的传感器:模拟和数字。

模拟传感器

模拟传感器产生连续的输出信号或电压,通常与被测量的量成比例。这些传感器通常产生随时间平滑连续变化的输出信号。见图 4-1 。

img/496535_1_En_4_Fig1_HTML.jpg

图 4-1

模拟信号

以下代码每秒连续打印连接到 MCP3008 第一个通道(0)的传感器的模拟值。由于 MCP3008 是一个 10 位 ADC,输出值范围为 0 至 1023。

from gpiozero import MCP3008
from time import sleep

sensor = MCP3008(0)

while True:
    print(sensor.value)

数字传感器

数字传感器产生数字输出信号或电压,这些信号或电压是被测量量的数字表示。在这些传感器中,数据转换和数据传输以数字方式进行。见图 4-2 。

img/496535_1_En_4_Fig2_HTML.jpg

图 4-2

数字信号

以下代码连续打印 GPIO 引脚 17 的数字状态:

from gpiozero import InputDevice
from time import sleep

sensor = InputDevice(17, pull_up=True)

while True:
    print(sensor.value)]

下面列出了电子行业中一些常见的传感器:

  • 温度传感器

  • 红外传感器

  • 超声波传感器

  • 压力传感器

  • 近程传感器

  • 触摸传感器

  • 液位传感器

  • 烟雾和气体传感器

什么是实时数据?

实时数据(RTD) 是收集后立即传递给最终用户的信息。实时数据可以是静态的,也可以是动态的,通常使用实时计算进行处理。

实时数据分析

实时分析是指在收集数据后立即对收集的数据进行分析。实时数据分析使我们能够毫不延迟地做出决策,并能够防患于未然。

在这里,我们将讨论如何从摄像机获取关于距离、湿度、温度和图像数据的实时数据。

从超声波传感器获取实时距离数据

超声波传感器的基本原理是发射和接收声波。物理变量(如距离、水平、高度、流量等。)可以基于发射波和接收回波声波之间的持续时间来计算。

将超声波传感器与 Raspberry Pi 接口

第三章已经讨论了超声波传感器与 Raspberry Pi 的接口。我们将从 HC-SR04 超声波传感器收集数据,该传感器可用于测量 2 厘米至 400 厘米的距离,精度为 3 毫米。这里,我们的目标是将超声波距离传感器与 Raspberry Pi 接口,并将收集的数据保存为 CSV 格式。为此,可以将超声波距离传感器连接到 Raspberry Pi GPIO 引脚,如图 4-3 所示。

img/496535_1_En_4_Fig3_HTML.jpg

图 4-3

超声波传感器与 Raspberry Pi GPIO 引脚连接

正如在第三章中所提到的,我们将使用gpiozero库中的DistanceSensor对象。distance函数返回超声波距离传感器测量的距离,单位为米。为了以厘米为单位显示,我们需要将该值乘以 100。下面的代码以厘米为单位打印超声波距离传感器每秒测量的距离,并在 100 秒后保存收集的数据。

from gpiozero import DistanceSensor
from time import sleep

sensor = DistanceSensor(echo=17, trigger=4)

n = 100
for i in range(n):
    print(sensor.distance * 100)
    sleep(1)

当代码运行时,移动放置在超声波传感器前面的物体的位置以获得不同的值。测量的距离(单位 cm)连续打印 n 秒;在我们的例子中,是 100。

从摄像机获取实时图像数据

本节说明如何从网络摄像头获取实时视频。

从网络摄像头获取实时视频

通过 USB 端口将 USB 网络摄像头连接到 Raspberry Pi。使用OpenCV Python 库,我们可以访问网络摄像头并从中捕捉图像和视频。以下代码可用于从网络摄像头获取实时视频。可以实时分析收集的帧。

import cv2
vid = cv2.VideoCapture(0)

while(True):

    ret, frame = vid.read()
    cv2.imshow('frame', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

vid.release()
cv2.destroyAllWindows()

从 Pi-cam 获取实时视频

通过摄像头串行接口(CSI)端口将 Raspberry Pi 摄像头模块连接到 Raspberry Pi。要启用 Raspberry Pi 摄像头,请从主菜单打开 Raspberry Pi 配置,并在接口选项卡上启用摄像头。以下代码可用于使用 Raspberry Pi 摄像头模块捕捉图像,并将捕捉到的图像存储在指定位置:/home/pi/Desktop/cammodule_img.jpg

from picamera import PiCamera
from time import sleep

camera = PiCamera()

camera.start_preview()
sleep(5)
camera.capture('/home/pi/Desktop/cammodule_img.jpg')
camera.stop_preview()

数据传送

数据传输或数据传送是指在两个或多个数字设备之间传送数据的过程。数据以模拟或数字格式传输,数据传输过程使设备或设备内的组件能够相互通信。

串行和并行通信

串行通信是通过通信信道或计算机总线一次一位地顺序发送数据的过程。并行通信是一种同时传送多个二进制数字(位)的方法。

Arduino 与 Raspberry Pi 的接口

我们可以将 Arduino 连接到 Raspberry Pi,并将数据从 Arduino 传输到 Raspberry Pi,反之亦然。传感器、电机和致动器可以连接到 Arduino,并使 Arduino 向/从 Raspberry Pi 传输值。通过这样做,我们可以使用 Arduino 作为节点,并通过这些节点获取传感器数据。

Arduino 可以通过两种方式连接到 Raspberry Pi。

  • 通过 USB 进行串行通信

  • 通过 GPIO 引脚进行串行通信

通过 USB 串行

使用 Arduino USB 电缆连接两块电路板是在 Arduino 和 Raspberry Pi 电路板之间建立通信的最简单方法。

在 Raspberry Pi 上,选择板上可用的四个 USB 端口中的任意一个,并连接 USB 连接器。将 Arduino USB 电缆的另一端连接到 Arduino。不同版本的 Arduino 的连接器电缆会有所不同。

通过 GPIOs 串行

也可以使用普通导线在 Raspberry Pi GPIOs 和 Arduino 引脚之间建立串行连接。根据你的 Arduino 板,可能需要一个电压电平转换器。

Raspberry Pi 的工作电压为 3.3V,而诸如 Uno、Mega、Leonardo、Nano 等 Arduino 板的工作电压为 3.3V。工作电压为 5V。因此,在连接 RX 和 TX 引脚时,需要使用 3.3V/5V 电平转换器来保护 Raspberry Pi,如图 4-4 所示。

img/496535_1_En_4_Fig4_HTML.jpg

图 4-4

通过 GPIO 引脚连接 Arduino 和 Raspberry Pi

一般来说,建议使用 Arduino USB 电缆而不是 GPIOs 进行串行通信。

Arduino 和 Raspberry Pi 之间的数据传输

当通过 USB 电缆将 Arduino 连接到 Raspberry Pi 时,在 Raspberry Pi 终端窗口中运行命令ls /dev/tty*来查找 Arduino 设备的名称。它应该返回类似于/dev/ttyACM0/dev/ttyUSB0的东西。

pySerial Python 库用于制作与 Python 的串行接口,封装了对串口的访问。

以下代码可用于在 Arduino 和 Raspberry Pi 之间进行双向通信。

Arduino 伫列

以下是 Arduino 代码:

void setup() {
Serial.begin(9600);
}
void loop() {
  if (Serial.available() > 0) {
    String data = Serial.readStringUntil('\n');
    Serial.print("Received Data: ");
    Serial.println(data);
  }
}

Serial.available()将给出已经到达并存储在接收缓冲区中的字节数。这可用于检查 Arduino 是否已接收到数据。

如果一些数据已经到达,Serial.readStringUntil()与换行符\n一起使用来获得下一行。在换行符\n之前收到的所有字节都被自动转换并添加到 Arduino String对象中。

然后,我们只返回包含接收到的数据和一些附加文本的字符串。

Raspberry Pi Python 代码

下面是显示串行数据的 Raspberry Pi Python 代码:

#!/usr/bin/env python3
import serial
import time

if __name__ == '__main__':
    ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
    ser.flush()
    while True:
        ser.write(b"Data from Raspberry Pi!\n")
        line = ser.readline().decode('utf-8').rstrip()
        print(line)
        time.sleep(1)

pySerial功能write()用于向 Arduino 发送数据。在发送字符串之前,它会将字符串编码成字节,因为你只能通过Serial发送字节。任何不是字节或字节数组的数据都必须在通过Serial发送之前进行转换。

此外,我们添加了一个换行符\n,因为 Arduino 在使用Serial.readStringUntil('\n')读取时希望它出现在字符串的末尾。

然后我们从Serial读取一行,解码成一个字符串,最后打印接收到的字符串并等待一秒钟,然后通过Serial发送下一个字符串。

时间序列数据

时间序列是按时间顺序索引的一系列数据点。最常见的是,它是在连续的等距时间点上拍摄的序列。因此,时间序列可以定义为一系列离散时间数据。在时间序列数据中,时间往往是自变量,目标一般是对未来做出预测。

时间序列经常通过折线图绘制。时间序列用于统计学、信号处理、通信工程、模式识别、天气预报、地震预测、控制工程、天文学等。

时间序列分析和预测

时序分析包括分析时序数据以提取有意义的统计数据和数据的其他特征的方法。时间序列分析还包括对未来序列的预测、从噪声数据中提取隐藏信号、发现数据生成机制等。时间序列预测是基于历史数据使用模型预测未来值。

内存要求

本节讨论内存需求。

更多存储空间

有时,microSD 卡的内存可能不够,可能需要更多内存。更多的存储空间对于存储收集的数据和重模型非常有益。为了增加存储容量,可以将外部硬盘驱动器连接到 Raspberry Pi。

更多内存

RAM 是数据科学项目的另一个重要因素。RAM 越大,它可以处理的数据量就越大,从而导致处理速度更快。虽然 1GB RAM 的基本版本可以完成这项工作,但对于大多数深度学习任务,推荐使用 4GB RAM 版本的 Raspberry Pi。

案例研究:收集实时行业数据

我们来看一个案例研究。

使用 Pandas 存储收集的数据

收集的数据也可以保存以备后用。Pandas 是一个用 Python 构建的开源数据分析和操作工具。我们将使用 Pandas 将收集的数据转换成结构化的数据格式。Pandas 库可以使用以下命令通过pip安装:

pip install pandas

数据帧

数据帧是二维数据结构。数据以表格的形式排列成行和列,它通常是最常用的 Pandas 对象。一旦我们将数据转换成数据帧,我们就可以轻松地将数据转换成其他格式,如 CSV 和 Microsoft Excel。

将数据保存为 CSV 文件

逗号分隔值文件是使用逗号分隔值的分隔文本文件。文件的每一行都是一条数据记录。每个记录由一个或多个字段组成,用逗号分隔。Pandas 数据帧的to_csv()函数将数据帧导出为 CSV 格式。

df.to_csv('file path\File Name.csv')

另存为 Excel 文件

要将单个对象写入 Excel .xlsx文件,只需指定一个目标文件名。要写入多个工作表,需要创建一个带有目标文件名的ExcelWriter对象,并在文件中指定要写入的工作表。Pandas 数据帧的to_excel()函数将数据帧导出为.xlsx格式。

df.to_excel("output.xlsx")

读取保存的数据文件

数据保存后,可使用read_csv()read_excel()功能读取。read_excel()函数将一个 Excel 文件读入 Pandas 数据帧,它支持从本地文件系统或 URL 读取的.xls.xlsx.xlsm.xlsb.odf文件扩展名。它有一个选项来读取单个表或表的列表。read_csv()函数将一个 CSV 文件读入一个数据帧,并且还支持可选的迭代或者将文件分成块。

向实时数据添加日期和时间

在收集数据的同时,我们还可以在数据中添加数据和时间。我们将使用datetime Python 库。datetime.datetime.now()可用于获取当前日期和时间。

from datetime import datetime

now = datetime.now()

print("now =", now)

# dd/mm/YY H:M:S
dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
print("date and time =", dt_string)

来自温度和湿度传感器的行业数据

我们将使用温度和湿度传感器来测量温度和湿度。如第三章所示,将 DHT 11/22 传感器模块连接到 Raspberry Pi。

以下代码收集 100 秒的温度和湿度值,并将收集的数据存储为 CSV 文件:

import Adafruit_DHT
import time
from datetime import datetime

DHT_SENSOR = Adafruit_DHT.DHT11
DHT_PIN = 17

data = []

while _ in range(100):

    humidity, temperature = Adafruit_DHT.read(DHT_SENSOR, DHT_PIN)

    if humidity is not None and temperature is not None:

      now = datetime.now()
      dt_string = now.strftime("%d/%m/%Y %H:%M:%S")

      data.append(dt_string,humidity,temperature)

    time.sleep(60*5)

df = pd.DataFrame(data)
df.to_csv('data.csv',index=None,header=None)

CSV 文件将如下所示:

| 17/05/2020 01:05:14 | Twenty-six point two four | Sixty-nine point nine one | | 17/05/2020 01:10:14 | Twenty-six point two four | Seventy point six five | | 17/05/2020 01:15:14 | Twenty-six point two two | Sixty-eight point eight seven | | 17/05/2020 01:20:14 | Twenty-six point one five | Seventy point one one | | 17/05/2020 01:25:14 | Twenty-six point one one | Sixty-nine point zero two |

五、准备数据

数据科学最重要的一步是准备数据。数据准备是清理、处理和转换用于分析的原始数据的过程。从这个阶段开始,可以通过清理、识别缺失值、处理异常值等方式有效地处理数据中的错误。因此,本章讨论了使用 Python 中的 Pandas 包准备数据的方法。

Pandas 和数据结构

Pandas 是一个为 Python 编程语言编写的软件库,主要用于数据操作和分析。

简而言之,Pandas 就像 Python 的 Excel,表格(在 Pandas 中称为 dataframes )由行和列组成(在 Pandas 中称为系列)。Pandas 有许多功能,使它成为一个数据处理、检查和操作的极好的库。

安装和使用 Pandas

在您的系统上安装 Pandas 需要安装 NumPy,如果从源代码构建库,则需要适当的工具来编译构建 Pandas 的 C 和 Cython 源代码。

您可以在 Pandas 文档中找到关于此安装的详细信息。Pandas 可以安装使用 pip 功能:pip 安装 Pandas。安装 Pandas 后,您可以导入它并检查版本,如下所示:

import pandas
pandas.__version__

正如我们通常以别名np导入 NumPy 一样,我们将以别名pd导入 Pandas,这种导入约定将贯穿本书的其余部分。

import pandas as pd

Pandas 数据结构

数据结构是一种数据组织、管理和存储格式,支持高效的访问和修改。更准确地说,数据结构是数据值、数据值之间的关系以及可应用于数据的功能或操作的集合。Pandas 向 Python 引入了两个新的数据结构,SeriesDataFrame,这两个数据结构都是建立在 NumPy 之上的(这意味着它们很快)。

系列

系列是一个一维对象,类似于表格中的数组、列表或列。它将为序列中的每个项目分配一个带标签的索引。默认情况下,每个项目将收到一个从 0 到 N 的索引标签,其中 N 是序列的长度减 1,如下所示:

s = pd.Series([1, 'Raspberry Pi', 3.14, -500, 'Data'])
print(s)
Output:
0          1
1   Raspberry Pi
2    3.14
3    -500
4    Data
dtype: object

我们可以不提供默认索引,而是在创建序列时为每个条目指定一个索引,如下所示:

s = pd.Series([1, 'Raspberry Pi', 3.14, -500, 'Data'],
               index=['M', 'A', 'X', 'I', 'E'])
print(s)
Output:
M          1
A   Raspberry Pi
X    3.14
I    -500
E    Data
dtype: object

Series构造函数也可以将字典转换成序列,使用字典的键作为索引,如下所示:

d = {'English': 95, 'Math': 100, 'Science': 98, 'Social Science': 93}
marks = pd.Series(d)
print(marks)
Output:
English           95
Math             100
Science           98
Social Science    93
dtype: float64

该索引可用于从系列中选择特定项目。例如,可以通过指定索引Math来选择数学的标记。类似地,可以通过在列表中提供以逗号分隔的相应索引来打印一组项目,如下所示:

print (marks['Math'])
print(marks[['English', 'Science', 'Social Science']])

Output :
100.0
English           95
Science           98
Social Science    93
dtype: float64

也可以使用过滤值的布尔索引。例如,使用索引marks < 96返回一系列布尔值,然后我们将这些值传递给我们的序列marks,返回相应的True项,如下所示:

marks[marks < 96]
Output:
Math             100
Science           98
dtype: float64

通过访问项目的相应索引,可以随时更改系列中特定项目的值,如下所示:

print('Old value:', marks['Math'])
marks['Math'] = 99
print('New value:', marks['Math'])
Output:
('Old value:', 100.0)
('New value:', 99.0)

我们还可以使用以下代码检查某个项目是否存在于序列中:

print('Math' in marks)
print('French' in marks)
Output:
True
False

也可以对一系列数值进行数学运算,如下所示:

marks * 10
Output:
English           950
Math              990
Science           980
Social Science    930
dtype: float64

np.square(marks)
Output:
English           9025
Math              9801
Science           9604
Social Science    8649
dtype: float64

数据帧

表格DataFrame数据结构由行和列组成,类似于电子表格或数据库表。您也可以将一个DataFrame看作一组共享一个索引(列名)的Series对象。

阅读日期

为了从常见的 Python 数据结构中创建一个DataFrame数据结构,我们可以将一个列表字典传递给DataFrame构造函数。

a={'Name':['Augustus', 'Hazel', 'Esther', 'Cavas'],
      'Gender':['Male','Female','Female','Male'],
      'Age':[19, 18, 22, 21]}
b=pd.DataFrame.from_dict(a)
            print(b)

Output:
   Name      Gender   Age
0  Augustus    Male   19
1     Hazel  Female   18
2    Esther  Female   22
3     Cavas    Male   21

读取 CSV 数据

读取 CSV 文件就像调用read_csv函数一样简单。默认情况下,read_csv函数希望列分隔符是逗号,但是您可以使用sep参数来更改它。以下代码显示了将 CSV 文件读入DataFrame 'df'并使用head()函数打印df的前五行的语法:

df = pd.read_csv('data.csv')
print(df.head())

还有一组 writer 函数,用于将DataFrame对象写成各种格式,如 CSV 文件、HTML 表格、JSON 等。以下代码行显示了将DataFrame对象写入 CSV 文件的语法:

df.to_csv('path_to_file.csv')

读取 Excel 数据

Pandas 允许我们读写 Excel 文件,所以我们可以很容易地用 Python 从 Excel 中读取数据,然后将数据写回 Excel。读取 Excel 文件需要使用pip命令安装的xlrd库,如下所示:

pip install xlrd.

下面的代码说明了从 Excel 文件读取一个工作表到DataFrame df *的语法。*用 Excel 文件的路径/文件名替换data.xlsx来运行代码。

df = pd.read_excel('data.xlsx', 'Sheet1')
print(df.head())

类似地,来自DataFrame对象的数据可以写入 Excel 文件,如下所示:

dataframe.to_excel('path_to_file.xlsx', index=False)

正在读取 URL 数据

read_table函数可以用来直接从一个 URL 读取。以下代码说明了使用来自给定 URL 的原始数据创建的DataFrame:

url = 'https://raw.github.com/gjreda/best-sandwiches/master/data/best-sandwiches-geocode.tsv'
from_url = pd.read_table(url, sep='\t')
from_url.head(3)
Output:
      rank         sandwich  ...   lat        lng
0     1                 BLT  ...   41.895734  -87.679960
1     2       Fried Bologna  ...   41.884672  -87.647754
2     3   Woodland Mushroom  ...   41.890602  -87.630925

清理数据

在大多数数据分析项目中,可用数据并不总是完美的。除了有用的数据之外,原始数据总是容易被损坏或不准确的数据弄乱。因此,数据科学家必须处理这些杂乱的数据样本,以便将原始数据转换成可以工作的形式,并且他们要花相当长的时间来这样做。

数据清理是识别数据中不准确、不正确或不完整的部分,并通过替换、删除或修改数据来处理它们的过程。换句话说,它是通过处理原始数据中的所有不规则性来为分析准备数据的过程。在接下来的部分中,我们将讨论如何处理缺失值和异常值,填充不合适的值,以及删除重复的条目。

处理缺失值

缺失值在原始数据中很常见。假设输入数据由使用调查表收集的成千上万客户的产品反馈组成。客户在填写调查表时跳过一些条目是很常见的行为。例如,一些客户可能不会分享他们对该产品的体验,一些客户可能不会分享他们使用该产品的持续时间,还有一些客户可能不会填写他们的联系信息。在编辑这些调查表并将其转换成表格时,表格中肯定会有大量缺失值。

由于各种原因,如传感器节点临时断电、硬件故障、通信干扰等,来自传感器的数据也可能丢失数据。因此,处理这些缺失值是数据科学家在处理原始数据时的首要任务。以下代码说明了如何使用 NumPy 库中的random.randn函数创建随机数数据库:

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(6,4),
index = ['1','3','4','6','7','9'],
 columns = ['a','b','c','d'])

从前面的代码中可以看出,行和列的索引是手动分配的。从分配给行的索引中可以看出,缺少索引 2、5 和 8。使用 Pandas 库中的reindex函数,这些索引是用缺失的“非数字”(NaN)值创建的,如下所示:

df=df.reindex(['1','2','3','4','5','6','7','8','9'])
print(df)
Output:
         a         b         c         d
1  0.099344  0.293956  1.002970  0.516942
2       NaN       NaN       NaN       NaN
3  1.608906 -1.748396 -1.013634 -0.651055
4  3.211263 -2.555312 -1.036068 -0.728020
5       NaN       NaN       NaN       NaN
6 -0.101766 -0.205572  1.369707 -1.133026
7  0.062344  1.483505  0.026995  1.560656
8       NaN       NaN       NaN       NaN
9 -0.324347 -0.342040  0.107224  0.272153

既然已经创建了包含缺失值的数据库,下一步就是处理这些值。在考虑处理这些值的选项之前,最重要的任务是检测丢失值的位置。Pandas 库中的isnull()函数可用于检测包含缺失值的行,如下所示:

df1=df[df.isna().any(axis=1)]
print(df1)
Output:
      a   b   c   d
2   NaN NaN NaN NaN
5   NaN NaN NaN NaN
8   NaN NaN NaN NaN

前面的过程让我们大致了解了数据库中丢失的数据量。一旦检测到丢失的数据,下一步就是处理丢失的数据。有两种方法可以做到这一点:一种是用值填充缺失的数据,第二种是简单地删除缺失的数据。

Pandas 库中的fillna()函数可以用来用用户指定的标量值填充缺失的值,如下所示。如图所示,第 2 行和第 5 行中缺少的值被替换为 0.000000。

df2=df.fillna(0)
print(df2.head())
Output:
          a         b         c         d
1  0.099344  0.293956  1.002970  0.516942
2  0.000000  0.000000  0.000000  0.000000
3  1.608906 -1.748396 -1.013634 -0.651055
4  3.211263 -2.555312 -1.036068 -0.728020
5  0.000000  0.000000  0.000000  0.000000

替换缺失值的另一种方法是使用 Pandas 库中的ffillbfill函数。ffill代表“向前填充”,通过重复出现在它们之前的值来填充缺失的值,bfill代表“向后填充”,通过重复出现在它们之后的值来填充缺失的值。以下代码说明了填充缺失值的正向填充方法:

df3= df.fillna(method='ffill')
print(df3.head())
Output:
          a         b         c         d
1  0.099344  0.293956  1.002970  0.516942
2  0.099344  0.293956  1.002970  0.516942
3  1.608906 -1.748396 -1.013634 -0.651055
4  3.211263 -2.555312 -1.036068 -0.728020
5  3.211263 -2.555312 -1.036068 -0.728020

处理缺失值的第二种可能方式是使用 Pandas 库中的dropna函数删除它们,如下所示:

df4=df.dropna()
print(df4)
Output:
          a         b         c         d
1  0.099344  0.293956  1.002970  0.516942
3  1.608906 -1.748396 -1.013634 -0.651055
4  3.211263 -2.555312 -1.036068 -0.728020
6 -0.101766 -0.205572  1.369707 -1.133026
7  0.062344  1.483505  0.026995  1.560656
9 -0.324347 -0.342040  0.107224  0.272153

我们创建了一个带有缺失值的简单数据集,以理解处理缺失值的概念。实际上,分析项目中使用的数据集很大,可能包含 500 到 1,000 行,甚至更多。我们鼓励您将从该示例中获得的知识应用到真实数据集上。处理缺失值的方法可能取决于应用的性质以及数据集中缺失值的数量或频率。

处理异常值

在数据集中,离群值是从所有其他观察值中脱颖而出的观察值(即数据)。换句话说,离群值是远离数据集中所有其他数据的数据点。异常值可能是由于测量/数据输入中的错误或由于数据中真正的极端值造成的。例如,考虑 112、123、120、132、106、26、118、140 和 125 这一系列数字。在这个数列中,除了 26 以外,所有的数字都接近 100。因此,26 是一个异常值,因为它与其他数字相距甚远。

可以通过两种方式检测异常值:使用可视化技术和使用数学方法。在本节中,我们将介绍两种识别数据中异常值的数学方法,即四分位数间距(IQR)和 Z 值。

四分位范围是对数据集中数据的可变性或分布的度量。数据首先被排序并分成四个季度。将总范围分成四个四分位数的值称为四分位数。因此,将有三个四分位数用于将数据分成四个四分位数。四分位数是 Q 1 ,Q 2 和 Q 3 ,其中 Q 2 是整个数据的中值,Q 1 是上半部分数据的中值,Q 3 是下半部分数据的中值。IQR 是第三个四分位数和第一个四分位数之差,即 Q3–Q1

为了说明使用 IQR 移除离群值的过程,让我们首先创建一个包含离群值的 15 个条目的DataFrame

  import pandas as pd
  a={'Name':['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O'],
     'Weight':[56,62,48,72,15,80,76,64,68,180,75,47,58,63,71]}
  df=pd.DataFrame.from_dict(a)
  print(df.head())
Output:
   Name  Weight
0    A      56
1    B      62
2    C      48
3    D      72
4    E      25

在前面的代码中,我们创建了一个包含 15 个成年人体重(公斤)的数据库。为了方便起见,我们用字母 AM 来给成年人命名。15 公斤和 180 公斤的体重被列为异常值,因为健康成年人体重不太可能太轻或太重。为了检测这些异常值,我们需要分别计算 25%和 75%的四分位值,Q1 和 Q3。从这些值中,可以通过确定 Q3-Q1 的差值来计算 IQR 值。此过程如下所示:

Q1=df.Weight.quantile(0.25)
Q3=df.Weight.quantile(0.75)
IQR=Q3-Q1
print('Q1=',Q1,'Q3=',Q3,'IQR=',IQR)
Output:
Q1= 57.0 Q3= 73.5 IQR= 16.5

通过将DataFrame对象中的条目与之前计算的四分位数进行比较,可以看到有四个值低于 Q1,七个值在 Q1 和 Q3 之间,四个值高于 Q3。但是我们知道只有一个异常值低于 Q1,一个异常值高于 Q3。为了检测这些异常值,我们需要形成一个区间,其下限远低于 Q1,上限远高于 Q3。一旦确定了这些限制,就可以放心地认为低于下限的值和高于上限的值将是异常值。下面的代码说明了这一点:

lower_limit = Q1 - 1.5 * IQR
upper_limit = Q3 + 1.5 * IQR
df1=df[(df.Weight < lower_limit) | (df.Weight > upper_limit)]
print(df1)
Output:
   Name  Weight
4    E      25
9    J     180

可以看出,使用 IQR 值创建的限制已经准确地检测到了我们数据中的异常值。现在,可以使用以下代码轻松过滤掉这些异常值:

df2=df.drop(df1.index)
   print(df2)
Output:
   Name  Weight
0     A      56
1     B      62
2     C      48
3     D      72
5     F      80
6     G      76
7     H      64
8     I      68
10    K      75
11    L      47
12    M      58
13    N      63
14    o      71

z 分数

Z 分数,也称为标准分数,给出了一个数据点离平均值有多远的概念。从技术上来说,Z 得分符合正态分布的数据,并测量数据点相对于整个数据集平均值的标准偏差数,如图 5-1 所示。

img/496535_1_En_5_Fig1_HTML.jpg

图 5-1

基于 Z 得分的异常值检测数据的正态分布

图 5-1 显示每个数据点沿着以零均值为中心的正态分布绘制。离零均值太远的数据点被视为异常值。在大多数情况下,阈值固定为 3,任何超过 3σ或-3σ的数据点都被视为异常值。让我们使用上一节中使用的同一数据库,并使用 Z 分数来识别异常值。

  import pandas as pd
  from scipy import stats
  import numpy as np
  a={'Name':['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O'],
     'Weight':[56,62,48,72,15,80,76,64,68,180,75,47,58,63,71,]}
  df=pd.DataFrame.from_dict(a)
  z = np.abs(stats.zscore(df.Weight))
  print(z)
  df1=df[z>3]
  print(df1)
Output:
   Name  Weight
9    J     180

从前面的代码可以看出,对应于权重值 180 的 Z 分数超过了阈值 3,因此它被显示为异常值。不幸的是,权重值 15 没有被检测为异常值。其原因可以通过比较平均值和标准偏差来理解,这可以通过np.meannp.std函数来实现,如下所示:

print(np.mean(df.Weight))
print(np.std(df.Weight))
Output:
67.0
33.448467827390836

让我们把标准差的值近似为 33.45。可以看出,权重值 180 和平均值之间的差为 111,大于标准偏差的三倍(> 3σ),而权重值 15 和平均值之间的差仅为 54,小于标准偏差的两倍(< 2σ)。克服这个问题的一种方法是降低阈值。让我们假设Threshold值为 1。

df1=df[z>1]
     print(df1)
Output:
     Name  Weight
4    E      15
9    J     180

从上图中可以看出,理想的阈值 3 可能并不适用于每个数据集,因此应该根据数据的分布来选择阈值。现在,与 IQR 的情况类似,可以使用以下代码简单地过滤掉这些异常值:

df2=df.drop(df.Name[z>1].index)
print(df2)
Output:
    Name  Weight
0     A      56
1     B      62
2     C      48
3     D      72
5     F      80
6     G      76
7     H      64
8     I      68
10    K      75
11    L      47
12    M      58
13    N      63
14    o      71

过滤掉不合适的值

在某些情况下,数据集可能包含一些与数据完全无关的不适当的值。在传感器数据的情况下尤其如此。传感器记录的数据通常是时间序列数据,每个数据点都有唯一的时间戳。在许多情况下,分析不需要这些时间戳,因此可以将其视为不适当的值。为了说明这个概念,我们创建了一个类似于传感器数据的时间序列温度数据,如下所示:

import pandas as pd
data={'Time':['12:00:05','12:08:33','12:25:12','12:37:53','12:59:08'],
      'Temperature':['T=22','T=22','T=23','T=23','T=24']}
df=pd.DataFrame.from_dict(data)
print(df)
Output:
       Time Temperature
0  12:00:05        T=22
1  12:08:33        T=22
2  12:25:12        T=23
3  12:37:53        T=23
4  12:59:08        T=24

现在每个数据点对应的时间戳和每个数据点中的头'T='都要去掉。时间戳可以使用 Pandas 库中的drop函数删除,而报头可以使用str.replace函数删除。因为每个数据点中都有一个标题,所以数据最初存储为字符串数据类型。因此,在删除这些头之后,数据类型必须更改为intfloat。这些程序说明如下:

df.drop('Time',inplace=True,axis=1)
df=df.Temperature.str.replace('T=','')
df=df.astype(float)
print(df)
Output:
0    22.0
1    22.0
2    23.0
3    23.0
4    24.0
Name: Temperature, dtype: float64

删除重复项

重复条目在数据科学中很常见,尤其是当我们从各种来源收集数据并整合它们进行处理时。根据我们分析的性质,这些重复可能会造成问题。因此,最好在分析数据之前删除这些重复项,如下所示:

import pandas as pd
a={'Name':['Alan','Joe','Jim','Tom','Alan','Anna','Elle','Rachel','Mindy'],
   'Age':[22,24,25,24,22,23,21,22,23]}
df=pd.DataFrame.from_dict(a)
print('DATA\n',df)
print('DUPLICATES\n',df[df.duplicated()])
df1=df.drop_duplicates()
print('DATA AFTER REMOVING DUPLICATES\n',df1)

Output:
DATA
     Name  Age
0    Alan   22
1     Joe   24
2     Jim   25
3     Tom   24
4    Alan   22
5    Anna   23
6   Ellen   21
7  Rachel   22
8   Mindy   23
DUPLICATES
   Name  Age
4  Alan   22
DATA AFTER REMOVING DUPLICATES
     Name  Age
0    Alan   22
1     Joe   24
2     Jim   25
3     Tom   24
5    Anna   23
6   Ellen   21
7  Rachel   22
8   Mindy   23

如代码所示,从由几个人的姓名和年龄组成的字典中创建了一个DataFrame,我们特意为姓名 Alan 创建了一个重复的条目。可以看出,Pandas 库中的复制函数清楚地标识了该名称的第二个条目。然后使用 Pandas 库中的drop_duplicates函数删除这个重复的条目。