原文:
www.kdnuggets.com/2018/05/jupyter-notebook-beginners-tutorial.html/2
每个笔记本的背后都运行着一个内核。当你运行一个代码单元格时,该代码在内核中执行,任何输出会返回到单元格中显示。内核的状态会随着时间的推移和单元格之间持续存在——它涉及整个文档而不是单个单元格。
例如,如果你在一个单元格中导入库或声明变量,它们将在另一个单元格中可用。通过这种方式,你可以把笔记本文件看作有点类似于脚本文件,只不过它是多媒体的。让我们试一下以感受一下。首先,我们将导入一个 Python 包并定义一个函数。
import numpy as np
def square(x):
return x * x
一旦我们执行了上面的单元格,我们可以在任何其他单元格中引用np
和square
。
x = np.random.randint(1, 10)
y = square(x)
print('%d squared is %d' % (x, y))
1 squared is 1
这将无论笔记本中的单元格顺序如何都有效。你可以自己尝试一下,让我们再次打印出我们的变量。
print('Is %d squared is %d?' % (x, y))
Is 1 squared is 1?
这里没有什么意外!但现在让我们改变y
。
y = 10
如果我们再次运行包含print
语句的单元格,你认为会发生什么?我们会得到输出Is 4 squared is 10?
!
大多数情况下,你的笔记本流程将是自上而下的,但通常会返回进行更改。在这种情况下,单元格左侧标示的执行顺序,比如In [6]
,会告诉你是否有任何单元格的输出过时。如果你想重置所有内容,可以从内核菜单中选择几个非常有用的选项:
-
重新启动:重新启动内核,从而清除所有已定义的变量等。
-
重新启动并清除输出:与上面相同,但还会清除你代码单元格下方显示的输出。
-
重新启动并运行所有:与上面相同,但还会按顺序从第一个到最后一个运行所有单元格。
如果你的内核在计算中卡住了,并且你希望停止它,你可以选择中断选项。
选择内核
你可能已经注意到,Jupyter 允许你更改内核,实际上有很多不同的选项可供选择。当你从仪表板创建一个新笔记本时,选择一个 Python 版本,实际上是选择了要使用的内核。
不仅有针对不同版本的 Python 的内核,还有针对100 多种语言的内核,包括 Java、C,甚至 Fortran。数据科学家可能特别感兴趣于R和Julia的内核,以及imatlab和Calysto MATLAB 内核的内核。 SoS 内核提供了在单个笔记本中支持多种语言的功能。每个内核都有自己的安装说明,但可能需要你在计算机上运行一些命令。
现在我们已经了解了什么是 Jupyter Notebook,是时候看看如何在实践中使用它们了,这将帮助你更清楚地理解为什么它们如此受欢迎。现在终于可以开始使用之前提到的《财富 500 强》数据集了。记住,我们的目标是了解美国最大公司历史上利润的变化情况。
值得注意的是,每个人都会形成自己的偏好和风格,但一般原则仍然适用。如果你愿意,可以在自己的笔记本中跟随本节内容,这样你可以进行一些实验。
在你开始编写项目之前,你可能会想给它一个有意义的名字。也许有点令人困惑的是,你不能直接在笔记本应用中命名或重命名笔记本,而是必须使用仪表板或文件浏览器来重命名.ipynb
文件。我们将返回仪表板来重命名你之前创建的文件,它将有一个默认的笔记本文件名Untitled.ipynb
。
你不能在笔记本运行时重命名它,所以你需要先将其关闭。最简单的方法是从笔记本菜单中选择“文件 > 关闭并停止”。然而,你也可以通过在笔记本应用中选择“内核 > 关闭”来关闭内核,或者通过在仪表板中选择笔记本并点击“关闭”(见下图)来关闭内核。
然后,你可以选择你的笔记本,并点击仪表板控制中的“重命名”。
请注意,关闭浏览器中的笔记本标签页不会像在传统应用中关闭文档那样“关闭”笔记本。笔记本的内核将继续在后台运行,需要在真正“关闭”之前手动关闭——不过如果你不小心关闭了标签页或浏览器,这一点非常方便!如果内核已经关闭,你可以关闭标签页而无需担心是否仍在运行。
一旦你给笔记本命名,重新打开它,我们就可以开始了。
通常,首先会有一个专门用于导入和设置的代码单元,这样如果你选择添加或更改任何内容,你可以简单地编辑并重新运行该单元,而不会造成任何副作用。
%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="darkgrid")
我们导入了pandas以处理数据, Matplotlib以绘制图表, 和Seaborn以使图表更加美观。 通常也会导入NumPy但在这种情况下,虽然我们通过 pandas 使用它,但不需要显式导入。而且那第一行不是 Python 命令,而是使用了称为行魔法的东西来指示 Jupyter 捕获 Matplotlib 图表并在单元格输出中呈现;这是一系列高级功能中的一个,超出了本文的范围。
让我们继续加载数据。
df = pd.read_csv('fortune500.csv')
这样做也是明智的,以防我们需要在任何时候重新加载它。
现在我们已经开始,最好的做法是定期保存。按Ctrl + S
将通过调用“保存和检查点”命令来保存你的笔记本,但这个检查点是什么呢?
每次你创建一个新的笔记本时,都会创建一个检查点文件以及你的笔记本文件;它将位于你保存位置的一个名为.ipynb_checkpoints
的隐藏子目录中,并且也是一个.ipynb
文件。默认情况下,Jupyter 会每 120 秒自动保存你的笔记本到这个检查点文件中,而不会更改你的主要笔记本文件。当你“保存和检查点”时,笔记本和检查点文件都会更新。因此,检查点使你能够在遇到意外问题时恢复未保存的工作。你可以通过菜单中的“文件 > 恢复到检查点”来恢复到检查点。
现在我们真的开始了!我们的笔记本已经安全保存,我们已经将数据集df
加载到最常用的 pandas 数据结构中,它叫做DataFrame
,基本上看起来像一个表格。我们的数据集看起来怎么样呢?
df.head()
年份 | 排名 | 公司 | 收入(百万) | 利润(百万) | |
---|---|---|---|---|---|
0 | 1955 | 1 | 通用汽车 | 9823.5 | 806 |
1 | 1955 | 2 | 埃克森美孚 | 5661.4 | 584.8 |
2 | 1955 | 3 | 美国钢铁公司 | 3250.4 | 195.4 |
3 | 1955 | 4 | 通用电气 | 2959.1 | 212.6 |
4 | 1955 | 5 | Esmark | 2510.8 | 19.1 |
df.tail()
年份 | 排名 | 公司 | 收入(百万) | 利润(百万) | |
---|---|---|---|---|---|
25495 | 2005 | 496 | Wm. Wrigley Jr. | 3648.6 | 493 |
25496 | 2005 | 497 | 皮博迪能源公司 | 3631.6 | 175.4 |
25497 | 2005 | 498 | 温迪国际 | 3630.4 | 57.8 |
25498 | 2005 | 499 | Kindred Healthcare | 3616.6 | 70.6 |
25499 | 2005 | 500 | 辛辛那提金融公司 | 3614.0 | 584 |
看起来不错。我们有了需要的列,每一行都对应一个公司在一个特定年份的数据。
我们只是重命名这些列,以便以后可以引用它们。
df.columns = ['year', 'rank', 'company', 'revenue', 'profit']
接下来,我们需要探索一下我们的数据集。数据集是否完整?pandas 是否按预期读取了数据?是否有缺失值?
len(df)
25500
好的,这看起来不错——从 1955 年到 2005 年,每年有 500 行数据。
让我们检查一下我们的数据集是否已按预期导入。一个简单的检查方法是查看数据类型(或 dtypes)是否被正确解释。
df.dtypes
year int64
rank int64
company object
revenue float64
profit object
dtype: object
哎呀。看起来利润列有问题——我们希望它像收入列一样是float64
类型。这表明它可能包含一些非整数值,因此让我们来看看。
non_numberic_profits = df.profit.str.contains('[⁰-9.-]')
df.loc[non_numberic_profits].head()
年份 | 排名 | 公司 | 收入 | 利润 | |
---|---|---|---|---|---|
228 | 1955 | 229 | Norton | 135.0 | N.A. |
290 | 1955 | 291 | Schlitz Brewing | 100.0 | N.A. |
294 | 1955 | 295 | Pacific Vegetable Oil | 97.9 | N.A. |
296 | 1955 | 297 | Liebmann Breweries | 96.0 | N.A. |
352 | 1955 | 353 | Minneapolis-Moline | 77.4 | N.A. |
正如我们所怀疑的那样!一些值是字符串,用于表示缺失数据。是否还有其他值混入了?
set(df.profit[non_numberic_profits])
{'N.A.'}
这使得解释变得容易,但我们应该怎么做呢?这取决于缺失值的数量。
len(df.profit[non_numberic_profits])
369
这是我们数据集的一小部分,但并不是完全无关紧要,因为它仍然约占 1.5%。如果包含N.A.
的行大致上在各个年份中均匀分布,最简单的解决方案就是删除这些行。所以让我们快速查看一下分布情况。
bin_sizes, _, _ = plt.hist(df.year[non_numberic_profits], bins=range(1955, 2006))
一眼看去,我们可以看到单一年份中无效值的数量不到 25,而每年有 500 个数据点,删除这些值在最坏的情况下占数据的不到 4%。实际上,除了 90 年代的激增,大多数年份的缺失值数量不到峰值的一半。就我们的目的而言,我们可以认为这是可以接受的,接着删除这些行。
df = df.loc[~non_numberic_profits]
df.profit = df.profit.apply(pd.to_numeric)
我们应该检查一下是否成功。
len(df)
25131
df.dtypes
year int64
rank int64
company object
revenue float64
profit float64
dtype: object
太棒了!我们已经完成了数据集的设置。
如果你打算将你的笔记本作为报告呈现,你可以删除我们创建的调查性单元格,这些单元格在这里作为工作流演示,合并相关单元格(有关更多信息,请参见下面的高级功能部分)以创建一个单一的数据集设置单元格。这意味着如果我们在其他地方搞砸了数据集,我们只需重新运行设置单元格即可恢复。
接下来,我们可以通过绘制每年的平均利润来解决手头的问题。我们也可以绘制收入,所以首先我们可以定义一些变量和方法来简化我们的代码。
group_by_year = df.loc[:, ['year', 'revenue', 'profit']].groupby('year')
avgs = group_by_year.mean()
x = avgs.index
y1 = avgs.profit
def plot(x, y, ax, title, y_label):
ax.set_title(title)
ax.set_ylabel(y_label)
ax.plot(x, y)
ax.margins(x=0, y=0)
现在让我们绘图吧!
fig, ax = plt.subplots()
plot(x, y1, ax, 'Increase in mean Fortune 500 company profits from 1955 to 2005', 'Profit (millions)')
哇,这看起来像是一个指数曲线,但有一些巨大的波动。它们一定对应于1990 年代初期的衰退和互联网泡沫。在数据中看到这些现象相当有趣。但为什么每次衰退后,利润会恢复到更高的水平呢?
也许收入能告诉我们更多信息。
y2 = avgs.revenue
fig, ax = plt.subplots()
plot(x, y2, ax, 'Increase in mean Fortune 500 company revenues from 1955 to 2005', 'Revenue (millions)')
这为故事增添了另一面。收入并没有受到如此严重的打击,这得归功于财务部门的出色会计工作。
在Stack Overflow的帮助下,我们可以在这些图上叠加其标准差的正负范围。
def plot_with_std(x, y, stds, ax, title, y_label):
ax.fill_between(x, y - stds, y + stds, alpha=0.2)
plot(x, y, ax, title, y_label)
fig, (ax1, ax2) = plt.subplots(ncols=2)
title = 'Increase in mean and std Fortune 500 company %s from 1955 to 2005'
stds1 = group_by_year.std().profit.as_matrix()
stds2 = group_by_year.std().revenue.as_matrix()
plot_with_std(x, y1.as_matrix(), stds1, ax1, title % 'profits', 'Profit (millions)')
plot_with_std(x, y2.as_matrix(), stds2, ax2, title % 'revenues', 'Revenue (millions)')
fig.set_size_inches(14, 4)
fig.tight_layout()
这令人吃惊,标准差非常大。一些财富 500 强公司赚取数十亿,而其他公司则亏损数十亿,多年来风险随着利润的增长而增加。也许有些公司表现优于其他公司;排名前 10%的公司利润是否比排名后 10%的公司更稳定?
接下来我们还有许多问题可以探讨,而且很容易看出在笔记本中工作的流程如何与个人的思维过程相匹配,所以现在是时候结束这个例子了。这种流程帮助我们在一个地方轻松调查数据集,而无需在应用程序之间切换上下文,并且我们的工作可以立即共享和复现。如果我们希望为特定的受众创建更简洁的报告,我们可以通过合并单元格和删除中间代码来快速重构我们的工作。
当人们谈论共享他们的笔记本时,他们通常考虑两种模式。大多数情况下,个人分享的是他们工作的最终结果,就像这篇文章本身一样,这意味着分享非交互式的、预渲染版本的笔记本;然而,也可以借助版本控制系统如Git进行协作。
也就是说,网上出现了一些新兴的公司,提供在云端运行交互式 Jupyter 笔记本的能力。
共享笔记本将以你导出或保存时的状态出现,包括任何代码单元格的输出。因此,为了确保你的笔记本在共享时准备好,你应该在分享之前采取一些步骤:
-
点击“单元格 > 全部输出 > 清除”
-
点击“内核 > 重新启动并运行全部”
-
等待你的代码单元格执行完毕,并检查它们是否按预期完成
这将确保你的笔记本不包含中间输出,状态不过时,并且在分享时按照顺序执行。
Jupyter 内置了导出到 HTML 和 PDF 以及其他几种格式的支持,你可以从“文件 > 另存为”菜单中找到这些选项。如果你希望将笔记本分享给一个小的私人组,这个功能可能已经足够。事实上,由于许多学术机构的研究人员会有一些公共或内部的网页空间,并且因为你可以将笔记本导出为 HTML 文件,Jupyter 笔记本可以是他们与同行分享研究结果的特别便捷的方式。
但如果分享导出的文件对你来说不够直接,还有一些非常流行的方法可以更直接地在网上分享.ipynb
文件。
到 2018 年初,GitHub 上的公开笔记本数量超过 180 万,这无疑是分享 Jupyter 项目给全世界的最受欢迎的独立平台。GitHub 已经集成了对.ipynb
文件的直接渲染支持,无论是在其网站上的代码库还是 gists。如果你还不知情,GitHub是一个用于版本控制和协作的代码托管平台,支持使用Git创建的代码库。你需要一个账户来使用他们的服务,但标准账户是免费的。
一旦你有了 GitHub 账户,最简单的在 GitHub 上分享笔记本的方式其实根本不需要 Git。自 2008 年以来,GitHub 提供了其 Gist 服务,用于托管和分享代码片段,每个片段都有自己的仓库。要使用 Gists 分享笔记本:
-
登录并浏览到gist.github.com。
-
在文本编辑器中打开你的
.ipynb
文件,选择全部并复制其中的 JSON 内容。 -
将笔记本的 JSON 粘贴到 gist 中。
-
给你的 Gist 起一个文件名,记得添加
.iypnb
,否则无法使用。 -
点击“创建秘密 gist”或“创建公开 gist”。
这应该看起来像下面这样:
如果你创建了一个公开的 Gist,你现在可以与任何人分享其 URL,其他人也可以fork 和克隆你的工作。
创建你自己的 Git 仓库并在 GitHub 上分享超出了本教程的范围,但GitHub 提供了大量的指南来帮助你自行入门。
对于使用 git 的用户,一个额外的提示是为那些 Jupyter 创建的隐藏.ipynb_checkpoints
目录在你的.gitignore
中添加一个例外,以避免不必要地将检查点文件提交到你的代码库。
到 2015 年,NBViewer 已经每天渲染成千上万的笔记本,成为网络上最受欢迎的笔记本渲染器。如果你已经有地方来在线托管你的 Jupyter 笔记本,无论是 GitHub 还是其他地方,NBViewer 会渲染你的笔记本,并提供一个可分享的 URL。作为 Project Jupyter 的一部分,它作为免费服务提供,网址是nbviewer.jupyter.org。
最初在 GitHub 的 Jupyter Notebook 集成之前开发的,NBViewer 允许任何人输入 URL、Gist ID 或 GitHub 用户名/仓库/文件,它将把笔记本渲染为网页。Gist 的 ID 是其 URL 末尾的唯一数字;例如,在https://gist.github.com/username/50896401c23e0bf417e89cd57e89e1de
中最后一个反斜杠后的字符。如果你输入 GitHub 用户名或用户名/仓库,你将看到一个最简文件浏览器,让你浏览用户的仓库及其内容。
NBViewer 在显示笔记本时显示的 URL 是一个基于正在渲染的笔记本的 URL 的常量,因此你可以与任何人分享,只要原始文件保持在线,链接就会有效——NBViewer 不会长时间缓存文件。
从基础知识入手,我们已经掌握了 Jupyter 笔记本的自然工作流程,深入探讨了 IPython 的高级功能,最后学会了如何与朋友、同事和全世界分享我们的工作。所有这些都是在笔记本本身完成的!
应该清楚笔记本如何通过减少上下文切换和模拟项目中的自然思维发展来促进高效工作体验。Jupyter 笔记本的强大功能也应该显而易见,我们提供了许多线索,以便你开始探索在自己的项目中更高级的功能。
如果你希望获取更多关于自己笔记本的灵感,Jupyter 已经整理了a gallery of interesting Jupyter Notebooks,你可能会发现有帮助,此外,Nbviewer 主页链接到一些真正精美的高质量笔记本示例。也查看一下我们的Jupyter Notebook 技巧列表。
想了解更多关于 Jupyter 笔记本的内容?我们有一个a guided project你可能会感兴趣。
个人简介: Benjamin Pryke 是一名 Python 和网页开发人员,拥有计算机科学和机器学习背景。FinTech 公司 Machina Capital 的联合创始人。兼职体操运动员和数字波希米亚。
原文。转载已获许可。
相关:
-
前 5 名最佳 Jupyter Notebook 扩展
-
了解机器学习的 5 件事
-
Fast.ai 第 1 课在 Google Colab 上(免费 GPU)
1. Google 网络安全证书 - 快速进入网络安全职业生涯
2. Google 数据分析专业证书 - 提升你的数据分析技能
3. Google IT 支持专业证书 - 支持你的组织进行 IT 工作