TowardsDataScience-博客中文翻译-2020-九十六-

TowardsDataScience 博客中文翻译 2020(九十六)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

PyCaret 2.2 已经发布了,有什么新消息吗?

原文:https://towardsdatascience.com/pycaret-2-2-is-here-whats-new-ad7612ca63b?source=collection_archive---------3-----------------------

PyCaret 2.2 现在可以使用 pip 下载。https://www.pycaret.org

我们很高兴宣布 py caret 2.2—2020 年 10 月的更新。

PyCaret 是一个用 Python 编写的开源、低代码机器学习库,可以自动化机器学习工作流。它是一个端到端的机器学习和模型管理工具,可以加快机器学习实验周期,让你更有效率。

与其他开源机器学习库相比,PyCaret 是一个替代的低代码库,可以用来替换数百行代码。这使得实验快速有效。

发行说明:【https://github.com/pycaret/pycaret/releases

文档:https://pycaret.readthedocs.io/en/latest/

正在安装 PyCaret

安装 PyCaret 非常容易,只需要几分钟。我们强烈建议使用虚拟环境来避免与其他库的潜在冲突。参见下面的示例代码,创建一个 conda 环境并在该 conda 环境中安装 pycaret:

**# create a conda environment** 
conda create --name yourenvname python=3.6 **# activate environment** 
conda activate yourenvname **# install pycaret** 
pip install pycaret**# create notebook kernel linked with the conda environment** python -mipykernel install --user --name yourenvname --display-name "display-name"

PyCaret 的默认安装是 pycaret 的精简版本,它只安装这里列出的硬依赖项。要安装 pycaret 的完整版本,请使用以下代码:

**# install the full version**
pip install pycaret[full]

当您安装 pycaret 的完整版本时,这里列出的所有可选依赖项也会被安装。

安装每夜构建

PyCaret 进化非常快。通常,您希望获得最新的特性,但是希望避免从源代码编译 PyCaret 或者等待下一个版本。幸运的是,您现在可以使用 pip 安装 pycaret-nightly。

**# install the nightly build** pip install pycaret-nightly

**# or install the full version of the nightly build** pip install pycaret-nightly[full]

PyCaret 2.2 功能概述

👉支持 GPU 的培训

PyCaret 2.2 提供了使用 GPU 进行选择模型训练和超参数调整的选项。API 的使用没有变化,但是,在某些情况下,必须安装额外的库,因为它们没有安装默认的精简版本或完整版本。以下模型现在可以在 GPU 上训练。

要在 GPU 上启用光照梯度增强机器,您必须安装 LightGBM 的 GPU 启用版本。官方的分步指南是这里的。

如果你使用 Google Colab,你可以为 GPU 安装 Light Gradient Boosting Machine,但首先,你必须卸载 Light GBM-CPU 版本。在此之前,请确保在您的 Colab 会话中启用了 GPU。使用以下代码安装支持 GPU 的 LightGBM:

**# uninstall lightgbm CPU**
pip uninstall lightgbm -y**# install lightgbm GPU**
pip install lightgbm --install-option=--gpu --install-option="--opencl-include-dir=/usr/local/cuda/include/" --install-option="--opencl-library=/usr/local/cuda/lib64/libOpenCL.so"

截至今天,谷歌 Colab 上还不支持 cuML 0.15。这在未来可能会改变,但现在,你可以免费使用预装了 cuML 0.15 的 blazingSQL 笔记本。

https://blazingsql.com/

登录到您的帐户后,启动 Python 3 笔记本并使用以下代码安装 pycaret:

**# install pycaret on blazingSQL**
!/opt/conda-environments/rapids-stable/bin/python -m pip install --upgrade pycaret

或者,如果你在本地机器上有 GPU,或者你计划使用任何其他带有 GPU 的云服务,你可以遵循 cuML 的官方安装指南

假设安装成功,在 GPU 上训练模型唯一需要做的就是在初始化设置函数时启用 GPU。

**# import dataset** from pycaret.datasets import get_data
data = get_data('poker')**# initialize the setup** from pycaret.classification import *clf = setup(data, target = 'CLASS', use_gpu = True)

就是这样。您现在可以像在 CPU 上一样使用 pycaret 了。它会自动使用 GPU 进行模型训练,如果可能的话,还会使用 CPU 等效算法。甚至在开始训练之前,您可以通过使用以下命令来检查 GPU 上启用了哪些模型:

models(internal=True)[['Name', 'GPU Enabled']]

模型输出(内部=真)

CPU 与 GPU 的性能指标评测比较(以秒为单位)

基准比较 CPU 与 GPU,数据集:扑克(100K x 88)

👉超参数调谐

现在有了新的超参数调谐方法。在 PyCaret 2.1 之前,在 PyCaret 中调整模型的超参数的唯一方法是使用 scikit-learn 中的随机网格搜索。2.2 中添加的新方法有:

  • scikit-learn(网格)
  • sci kit-优化(贝叶斯)
  • tune-sklearn(随机、网格、贝叶斯、超点、bohb)
  • optuna(随机,热塑性弹性体)

为了使用这些新方法,增加了两个新参数‘搜索 _ 库’‘搜索 _ 算法’

**# train dt using default hyperparameters**
dt = create_model('dt')**# tune hyperparameters with scikit-learn (default)**
tuned_dt_sklearn = tune_model(dt)**# tune hyperparameters with scikit-optimize**
tuned_dt_skopt = tune_model(dt, search_library = 'scikit-optimize')**# tune hyperparameters with optuna**
tuned_dt_optuna = tune_model(dt, search_library = 'optuna')**# tune hyperparameters with tune-sklearn**
tuned_dt_tuneskl = tune_model(dt, search_library = 'tune-sklearn')

tune_model 输出(dt,默认超参数 AUC = 0.7401

搜索 _ 算法依赖于搜索 _ 库。以下搜索算法可用于相应的搜索库:

  • scikit-learn → random(默认),网格
  • sci kit-优化→贝叶斯(默认)
  • tune-sklearn →随机(默认),网格,贝叶斯,超点,bohb
  • optuna →随机,tpe(默认)

具有 partial_fit 属性的估计器也支持提前停止。在发行说明中阅读更多关于它的

不同调谐器的基准比较

PyCaret 数据集:糖尿病中可用搜索库/搜索算法的基准比较

👉内存和性能改进

PyCaret 2.2 关注的是性能和功能。大量代码被重构,以在不影响用户体验的情况下改善内存占用和优化性能。

一个例子是所有的数字数据从以前的 64 位动态转换为 32 位,大大减少了内存占用。性能提升的另一个例子是跨所有功能的交叉验证,与以前按折叠顺序训练相比,现在跨多个内核自动并行化。

我们在著名的纽约出租车数据集的 500 万个样本行上比较了 PyCaret 所有发布版本的性能。下图比较了完成设置初始化所需的时间:

来自纽约出租车数据集的 5M 行的基准性能比较

所有的比较都是在具有 8 个 CPU 内核的 AMD64 机器上进行的。

👉添加自定义指标

现在,您可以完全自定义(添加或删除)在交叉验证期间评估的指标。这意味着您不再局限于 PyCaret 的默认模型评估指标。增加了三个新功能获取指标、添加指标、移除指标。用法超级简单。参见示例代码:

**# import dataset** from pycaret.datasets import get_data
data = get_data('juice')**# initialize the setup** from pycaret.classification import *clf = setup(data, target = 'Purchase')**# check all metrics used for model evaluation**get_metrics()**# add Log Loss metric in pycaret**
from sklearn.metrics import log_loss
add_metric('logloss', 'LogLoss', log_loss, greater_is_better=False)**# compare baseline models**best = compare_models()

添加自定义指标后的 compare_models 输出

请注意,在 TT 被添加到 compare_models 得分网格之前,一个新列“log loss”(所有新指标被添加到右侧),因为我们使用 add_metric 函数添加了指标。您可以使用 scikit-learn 中可用的任何指标,或者您可以使用 make_scorer 函数创建自己的指标。您可以使用以下命令删除度量:

remove_metric('logloss')

👉迭代插补

迭代插补是一种使用回归和分类估计器来输入缺失数据的技术,将每个特征建模为其他特征的函数。每个特征以循环方式进行估算,以前的预测用于新的预测。为了提高估算的质量,这个过程要重复几次。与简单的插补相比,它可以创建更接近真实值的合成值,但需要额外的处理时间。

忠于 PyCaret 的精神,用法非常简单:

**# initialize setup**
from pycaret.classification import *clf = setup(data, target = 'Class', imputation_type="iterative")

默认情况下,它将使用光梯度增强机器作为分类特征(分类)和数值特征(回归)的估计器,这可以使用设置中的分类 _ 迭代 _ 估算数值 _ 迭代 _ 估算参数进行更改。

迭代插补与简单插补的基准比较

为了比较简单均值插补和迭代插补的结果,我们使用了包含大量缺失值的马疝气数据集。下图比较了使用不同插补方法的逻辑回归的表现。

安东尼·鲍姆的一篇博文:https://www . LinkedIn . com/pulse/iterative-attumation-py caret-22-安东尼-鲍姆/

与简单平均插补相比,使用 KNN 迭代插补作为分类和数值特征的估计量,平均 AUC 得分提高了 0.014 (1.59%)。要了解更多关于这个功能的信息,你可以在这里阅读完整的博文。

👉折叠策略

PyCaret 2.2 提供了定义折叠策略的灵活性。在 PyCaret 2.1 之前,您不能定义交叉验证策略。它使用‘StratifiedKFold’进行分类,使用‘k fold’进行回归,这限制了 PyCaret 在某些用例中的使用,例如时间序列数据。

为了克服这个问题,在设置功能中增加了一个新参数‘fold _ strategy’****。它可以采用以下值:

  • kfold为 KFold CV
  • stratifiedkfold为分层 KFold CV
  • groupkfold为集团 KFold CV
  • timeseries为 TimeSeriesSplit CV 或者
  • 与 scikit-learn 兼容的自定义 CV 生成器对象。

👉比较保留集上的模型

如果你之前用过 PyCaret,你一定熟悉它最常用的函数 compare_models。此功能使用交叉验证来训练和评估模型库中所有可用估计器的性能。然而,问题是如果你正在处理非常大的数据集,compare_models 可能要花很长时间才能完成。原因是它适合模型库中每个估计器的 10 倍。对于分类,这意味着总共有 15 x 10 = 150 个评估者。

在 PyCaret 2.2 中,我们在 compare_models 函数中引入了一个新参数 cross_validation ,当该参数设置为 False 时,将对维持集上的所有指标进行评估,而不是进行交叉验证。而单独依赖维持指标可能并不可取,尤其是当数据集太小时。在处理大型数据集时,这无疑可以节省大量时间。

为了量化影响,我们比较了 compare_models 在两种场景中的性能(交叉验证=真,交叉验证=假)。用于比较的数据集是这里是 (45K x 50)

交叉验证(耗时 7 分 13 秒):

compare_models 的输出(cross_validation = True)

无交叉验证(耗时 1 分 19 秒):

compare_models 的输出(cross_validation = False)

👉自定义转换

谈到灵活性,这是一个全垒打。一个新的参数 custom_pipeline 被添加到 setup 函数中,该函数可以接受任何转换器并附加到 PyCaret 的预处理管道中。所有自定义变换都在 train_test_split 之后分别应用于每个 CV 折叠,以避免目标泄漏的风险。用法非常简单:

**# import dataset** from pycaret.datasets import get_data
data = get_data('juice')**# build custom transformations** from imblearn.over_sampling import SMOTE
from sklearn.decomposition import PCA
custom_pp = [("PCA",PCA()),("smote", SMOTE())]**# initialize setup** from pycaret.classification import *clf = setup(data, target = 'Purchase', custom_pipeline = custom_pp)

👉独立的训练和测试设备

这是期待已久的,也是自第一次发布以来最受欢迎的特性之一。现在可以通过单独的测试集,而不是依赖 pycaret 内部的 train_test_split 设置中增加了一个新参数‘测试数据’。当一个数据帧被传入 test_data 时,它被用作一个测试集,并且 train_size 参数被忽略。test_data 必须加标签。请参见下面的示例代码:

**# loading dataset**import pandas as pd
train_data = pd.read_csv('/path/train.csv')
test_data = pd.read_csv('/path/test.csv')**# initializing setup**from pycaret.classification import *
clf = setup(data = train_data, test_data = test_data)

👉禁用预处理

如果您不想使用 PyCaret 的默认预处理管道,或者您已经有了转换后的数据集,而只想使用 PyCaret 的建模功能,这在以前是不可能的,但现在我们已经为您做好了准备。只需关闭设置中的'预处理'参数。当预处理设置为 False 时,除了在 custom_pipeline 参数中传递的 train_test_split 和自定义转换之外,不应用任何转换。

**# initializing setup**from pycaret.classification import *
clf = setup(data = train_data, preprocess = False) 

然而,当在设置中关闭预处理时,您必须确保您的数据是建模就绪的,即没有缺失值、没有日期/时间戳、分类数据被编码等。)

👉其他变化

  • plot_model 中添加了新的图“提升”、“增益”和“树”。
  • CatBoost 现在与 plot_model 功能兼容。它需要 catboost > = 0.23.2。
  • 为了使使用和开发更容易,根据最佳实践,所有更新的 pycaret 函数都添加了类型提示。用户可以通过使用支持类型提示的 IDE 来利用它们。

要了解 PyCaret 2.2 中所有更新的更多信息,请参见发行说明

使用 Python 中的轻量级工作流自动化库,您可以实现的目标是无限的。如果你觉得这有用,请不要忘记给我们 GitHub repo 上的⭐️。

想了解更多关于 PyCaret 的信息,请在 LinkedIn 和 Youtube 上关注我们。

重要链接

用户指南
文档
官方教程 示例笔记本
其他资源

想了解某个特定模块?

单击下面的链接查看文档和工作示例。

分类
回归
聚类
异常检测
自然语言处理 关联规则挖掘

PyCaret:用 Python 实现更好的机器学习

原文:https://towardsdatascience.com/pycaret-better-machine-learning-with-python-58b202806d1e?source=collection_archive---------19-----------------------

Scikit 的替代——使用 Python 学习机器

挑选任何数据科学书籍或在线课程。我敢打赌,唯一涵盖的机器学习库是 Scikit-Learn。这是一个很好的起点,不要误会我的意思,但在 2020 年,我们需要更加自动化和节省时间的东西。

安德烈·本兹在 Unsplash 上拍摄的照片

这就是 PyCaret 的用武之地。这是一个相对较新的库,所以没有太多的教程可用——尽管官方文档做了一项惊人的工作。下面是一句话的总结:

PyCaret 是 Python 中的一个开源、低代码机器学习库,允许您在几秒钟内从准备数据到在您选择的笔记本环境中部署模型。[1]

如果你更喜欢视频,或者只是想巩固你的知识,请随意观看我们关于这个主题的视频。源代码包含:

本文的目标读者是熟悉机器学习概念的人,他们也知道如何使用 Scikit-Learn 等库中的各种算法。理想的读者意识到自动化的需要,并且不想花费数天或数周时间寻找最佳算法及其超参数。

这将是一篇相当短的实践性文章,因为其目的只是展示该库能够做什么。未来的文章将更多地关注回归/分类/聚类任务。

好了,我们开始吧!

Python 演示

安装过程因操作系统而异。我在 macOS 上,所以在安装库之前需要一些步骤。

一旦完成,你就可以开始了。我们将从两个导入开始:

from pycaret.classification import * 
from pycaret.datasets import get_data

第一种方法是开始分类任务的推荐方法——尽管你们中的一些人可能不习惯使用 **import *** 语法。如果你不喜欢,就避开它。第二个导入允许我们使用内置数据集。

我们将使用内置的糖尿病数据集,以及 get_data() 函数来获取它。接下来,我们需要做一些设置,并告诉 PyCaret 目标变量是什么:

diabetes = get_data(‘diabetes’)
exp_clf = setup(diabetes, target=’Class variable’)

执行此代码将导致以下结果:

这个结果数据帧相当长,并且报告了大量关于数据的信息。我们现在可以继续机器学习部分。

寻找最佳算法

这一步很简单。键入以下内容:

compare_models()

这是结果:

是的, compare_models() 函数完成了所有这些工作。它还用黄色突出显示得分最高的单元格,这样更容易看到。逻辑回归似乎在准确性方面做得最好,但是 XGBoost 算法总体上执行得最好——所以这是我们将使用的算法。

如何?再一次,再简单不过了:

xgb = create_model(‘xgboost’)

这个链接上,你会找到所有的模型缩写,所以你可以使用 XGBoost 以外的东西。接下来,让我们直观地看看我们的模型表现如何。

可视化模型性能

我们可以使用 plot_model() 函数来可视化模型性能:

plot_model(xgb)

它默认显示 ROC 曲线,但这很容易改变。这是混淆矩阵:

plot_model(xgb, ‘confusion_matrix’)

和分类报告:

plot_model(xgb, ‘class_report’)

整齐,对吧?这里是链接到你可以制作的所有可视化效果。让我们继续模型的可解释性。

SHAP 的模型解释

SHAP,或 SHapley 附加解释,是一种解释机器学习模型输出的方法。通过绘制每个样本的每个特征的 SHAP 值,我们可以使用它来查看哪些特征最重要。

PyCaret 又一次让事情变得非常简单:

interpret_model(xgb)

上图根据所有样本的 SHAP 值大小的总和对要素进行排序,并使用 SHAP 值来显示每个要素对模型输出的影响分布[2]。相当长的句子,所以通读几遍。颜色代表特征值,红色代表高,蓝色代表低。

简而言之,它指出,在口服葡萄糖耐量试验的 2 小时内血浆葡萄糖浓度水平较高(无论这意味着什么),导致患糖尿病的几率较高(由于红色)。

我计划在其他文章中更深入地讨论 SHAP,所以我在这里就不赘述了。让我们继续在测试集上进行模型评估。

模型评估和预测

PyCaret 在加载时将数据分成训练和测试部分(70:30),因此我们不必手动完成。

我们现在可以根据以前未见过的数据来评估模型:

predictions = predict_model(xgb)

上述代码会产生以下结果:

好了,现在当这个已经完成了,让我们看看如何保存和加载模型。

模型保存和加载

在保存模型之前,我们需要完成它:

finalize_model(xgb)

猜猜保存模型有多简单:

save_model(xgb, ‘diabetes_xgboost’)

模型以 pickle 格式保存。

尝试猜测加载已保存模型的函数的名称:

model = load_model(‘diabetes_xgboost’)

你准备再次使用它。

我们今天已经讲了很多东西,所以让我们在下一部分总结一下。更多类似的文章即将发布,敬请关注。

结论

今天我们简要介绍了 PyCaret 所提供的内容。我的想法是把这个变成一个系列,既有基于文章的,也有基于视频的,并且更深入地覆盖这个库。

当使用像这样的库时,像 Scikit-Learn 这样的库很快就会成为过去。不是因为他们不好,而是这些人在各方面都很优秀。

我希望你喜欢它,并设法从中获得一些有用的东西。感谢阅读。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@radecicdario/membership)

参考

[1]https://pycaret.org

[2]https://github.com/slundberg/shap

PyCaret:机器学习的综合体

原文:https://towardsdatascience.com/pycaret-the-machine-learning-omnibus-dadf6e230f7b?source=collection_archive---------33-----------------------

…满足您所有机器学习需求的一站式商店

照片由阿什利·特雷瑟万Unsplash 拍摄

任何机器学习项目之旅都是从加载数据集开始,到结束(继续?!)最终确定用于预测未知数据和生产部署的最佳模型或模型集合。

作为机器学习的实践者,我们知道在达到最佳预测性能结果的过程中会有几个中途停留点。这些中间步骤包括探索性数据分析(EDA)、数据预处理——缺失值处理、异常值处理、改变数据类型、编码分类特征、数据转换、特征工程/选择、采样、训练-测试分离等。举几个例子,在我们开始建模、评估和预测之前。

我们最终导入了几十个 python 包来帮助我们做到这一点,这意味着要熟悉每个包中多个函数调用的语法和参数。

你是否希望有一个单一的包可以用一致的语法界面处理整个端到端的旅程?我当然有!

输入 PyCaret

这些愿望通过PyCaret包得到了回应,现在随着pycaret2.0的发布,它变得更加令人敬畏。

从这篇文章开始,我将发布一系列关于pycaret如何帮助我们快速完成一个 ML 项目的各个阶段的文章。

装置

安装轻而易举,几分钟内即可完成,所有依赖项也已安装完毕。建议使用虚拟环境安装,如 python3 virtualenvconda environments 以避免与其他预安装的软件包冲突。

pip install pycaret==2.0

一旦安装完毕,我们就可以开始了!我们将包导入到我们的笔记本电脑环境中。这里我们将讨论一个分类问题。类似地,可以为涉及回归、聚类、异常检测、NLP 和关联规则挖掘的场景导入相应的 PyCaret 模块。

我们将使用来自 kaggle.com 的titanic数据集。你可以从这里下载数据集。

让我们使用head()函数检查数据集的前几行:

设置

pycaretsetup()函数只需一行代码就可以完成大部分——所有的修正工作,这些繁重的工作通常需要几十行代码才能完成!

我们只需要传递数据帧并指定目标特性的名称作为参数。setup 命令生成以下输出。

setup推断出了数据集中要素的数据类型,非常有用。如果我们同意,我们需要做的就是点击Enter。否则,如果您认为由setup推断的数据类型不正确,那么您可以在底部的字段中键入quit,然后返回到setup函数进行更改。我们将很快看到如何做到这一点。现在,让我们点击Enter,看看会发生什么。

输出续。,

产出续下

输出结束

咻!在一行看似无害的代码中,似乎发生了很多事情!让我们来盘点一下:

  • 已检查缺失值
  • 已识别的数字和分类特征
  • 从原始数据集创建训练和测试数据集
  • 具有平均值的连续要素中的估算缺失值
  • 具有常数值的分类特征中的估算缺失值
  • 完成标签编码
  • ..似乎还有许多其他选择,包括异常值处理、数据缩放、特征变换、降维、多重共线性处理、特征选择和处理不平衡数据等。!

但是嘿!第 11 和 12 行是什么?训练和测试数据集中的特征数量是 1745?似乎是标签编码变得疯狂的一个例子,很可能来自于分类特征,如nameticketcabin。在本文和下一篇文章中,我们将探讨如何根据我们的需求控制设置,以主动解决这种情况。

定制setup

首先,我们如何从模型构建中排除像上面三个特征这样的特征?我们在setup函数的ignore_features参数中传递我们想要排除的变量。需要注意的是,ID 和 DateTime 列在推断时会被自动设置为在建模时被忽略。

请注意下面的pycaret,在要求我们确认时,已经放弃了上面提到的 3 个特性。让我们点击Enter并继续。

在结果输出中(截断版本如下所示),我们可以看到设置后,数据集形状现在更易于管理,只对剩余的更相关的分类特征进行标签编码:

在本系列的下一篇文章中,我们将详细讨论进一步的数据预处理任务,我们可以使用pycaret的这个setup函数通过传递额外的参数在数据集上实现这些任务。

但是在我们走之前,让我们用compare_model()函数来对pycaret惊人的模型比较能力做一个闪影。

在各种分类指标上比较模型性能。

嘣!所有需要做的只是compare_models()获得 15 个分类建模算法的结果,这些算法在交叉验证的各种分类指标之间进行比较。一目了然,我们可以看到CatBoost分类器在大多数指标上表现最佳,其中Naive-Bayes在召回率上表现良好,而Gradient Boosting在精确度上表现良好。每个指标中表现最佳的型号会由pycaret自动突出显示。

根据我们感兴趣的模型评估指标,pycaret有助于我们直接放大表现最佳的模型,我们可以使用超参数进一步调整这些模型。在接下来的文章中会有更多的介绍。

总之,我们已经简要了解了pycaret如何通过最少的代码结合关键数据预处理阶段的广泛而全面的定制,帮助我们快速完成 ML 项目生命周期。

您可能也会对我的其他文章感兴趣,这些文章介绍了在探索性数据分析(EDA)和可视化中使用最少的代码来交付最大的结果的优秀包。

[## 使用 SmartEDA 开发的 EDA

探索性数据分析——更智能、更快速的方式..

towardsdatascience.com](/eda-in-r-with-smarteda-eae12f2c6094) [## 拼凑——下一代 ggplots

进一步扩展 ggplot2 的多功能性..

towardsdatascience.com](/patchwork-the-next-generation-of-ggplots-1fcad5d2ba8a)

感谢您的阅读,并希望听到您的反馈。干杯!

PyCaret:机器学习综合教程—第 2 部分

原文:https://towardsdatascience.com/pycaret-the-machine-learning-omnibus-part-2-87c7d0756f2b?source=collection_archive---------31-----------------------

…满足您所有机器学习需求的一站式商店。

数据预处理和模型比较

阿什利·特雷瑟万在 Unsplash 上拍摄的照片

这是关于 python 中令人惊叹的pycaret包的系列文章的第二篇,它用少得可笑的代码行实现了对 ML 项目生命周期的几乎每个阶段的快速跟踪和自动化。如果您错过了第一部分,请单击下面的链接,我们在其中简要介绍了初始设置,它仅用一行代码就完成了数据预处理的所有方面,并将我们带到建模阶段。

[## PyCaret:机器学习的综合体

..满足您所有机器学习需求的一站式商店

towardsdatascience.com](/pycaret-the-machine-learning-omnibus-dadf6e230f7b)

在本文中,我们将查看几个可以传递给setup()函数的参数,以进一步控制由pycaret完成的预处理。默认情况下,setup函数只需要数据帧和我们想要预测其类别标签的目标特征。但是,由函数自动推断的要素数据类型可能并不总是正确的。在某些情况下,我们可能需要介入。例如,在我们正在使用的泰坦尼克号数据集中,setup函数正确地将Pclass(乘客等级)、SibSp(船上的兄弟姐妹&配偶)和Parch(船上的父母和子女)与sex一起推断为分类特征。pycaret将自动对分类特征进行一键编码,在这种情况下,将对PclassSibspParchsex进行编码。然而,除了sex之外的这些特征都有其固有的等级顺序(普通性),对它们进行标记编码以捕捉等级顺序更为合适。

因此,在下面的输出中,在运行setup时,我们键入Quit并通过将下面列出的附加参数传递给setup函数来解决这个问题。注意,我们使用ignore_features参数从建模中排除了NameTicketCabin特征。

序数 _ 特征()

ordinal_features参数接受一个字典,其中包含我们想要标记为序数的特性以及相应的类别级别。

常化

我们还可以将normalize参数设置为 True(默认为 false)并使用normalize_method参数指定方法(比如说 minmax,默认为 zscore)。

宁滨数字特征

在这种情况下,让我们也对数字特征AgeFares进行分类,因为它们值的每个单位变化不太可能影响我们对目标的预测。

设置

综上所述,我们修改后的setup命令如下所示:

pycaret提示我们确认它的推断时,我们点击Enter。使用单个setup功能,pycaret已经完成:

  • 缺失值插补
  • 分类特征的编码(见下面的第 11 行和第 12 行,现在我们有 31 个特征)
  • 规范化数字特征
  • 收集数字特征
  • 将数据集分为训练和测试

产出续下

产出续下

厉害!对吗?这还不是全部。通过向setup传递额外的参数,您可以根据数据集的性质探索许多设置定制。在上面的输出中,无论您在哪里看到 False/None,我们都保持默认的设置配置不变。您可以根据数据集的性质和想要进行的转换来启用相关的选项。配置这些附加参数的语法很简单。你可以在这里找到分类的完整列表和文档,在这里找到回归的

因此,用一个函数就完成了预处理!

使用 compare_model()进行模型比较

compare_model()函数使我们能够生成 15 个分类模型,并一次性比较多个分类指标的交叉验证性能!模型还会根据精度指标(默认)自动排序,可以使用sort参数将精度指标更改为您喜欢的其他指标。

模型比较

此外,您可以单击任何其他首选指标列标题,根据新指标对模型排名进行交互式排序。这非常有助于快速确定我们首选指标的最佳性能模型,以便我们可以继续对所选模型进行超参数调整。

compare_models()返回指定度量上的最佳执行模型,该模型可以存储为模型对象。

通过将附加参数传递给以下对象,可以进一步定制compare_models()的输出:

  • 省略型号(blacklist)
  • 仅考虑特定型号(whitelist)
  • 指定交叉验证折叠(fold,默认为 10)
  • 四舍五入小数(round,默认为 4)
  • 指定模型排序的度量标准(sort,默认为精确度)
  • 要返回的顶级模型的数量(n_select,默认为 1。如果大于 1,则返回顶级模型的列表)

最后,我们看到,使用pycaret,只需两行代码,我们就能够在 ML 项目中快速完成预处理和初步模型比较阶段。

在接下来的文章中,我们将了解pycaret的强大功能,它可以使用遵循****_model()语法的函数来创建模型、调整模型超参数、集合模型、堆栈模型等等。

如果您喜欢这篇文章,您可能还想看看下面关于探索性数据分析(EDA)和用最少的代码和最大的输出进行可视化的文章。

[## 使用 SmartEDA 开发的 EDA

探索性数据分析——更智能、更快速的方式..

towardsdatascience.com](/eda-in-r-with-smarteda-eae12f2c6094) [## 拼凑——下一代 ggplots

进一步扩展 ggplot2 的多功能性..

towardsdatascience.com](/patchwork-the-next-generation-of-ggplots-1fcad5d2ba8a)

感谢您的宝贵时间!注意安全!!

PyCharm:在 Ubuntu 中管理多个 Python 版本

原文:https://towardsdatascience.com/pycharm-managing-multiple-python-versions-in-ubuntu-11224789845e?source=collection_archive---------22-----------------------

使用 PyCharm 运行不同的 Python 版本

来源:来自 PixabayMustangJoe 的照片

运行 Python 项目时的一个潜在问题是版本冲突。例如,您可能安装了 Python 3.6 作为 Python 的系统级版本,但是需要构建一个需要 Python 3.8 的特定程序。

然而,将 Python 3.8 安装为系统范围的版本会有使您的 Python 3.6 代码与新版本不兼容的风险。

在这种情况下,需要使用虚拟环境,即一个独立的环境,它运行一个不同于系统范围内运行的 Python 版本。

PyCharm 作为多个 Python 版本的 IDE(集成开发环境)非常有效。使用 Ubuntu 18.04,让我们看看如何通过 PyCharm 在虚拟环境中设置 Python 3.8。

安装 PyCharm

JetBrains 网站上,你会看到 PyCharm(在撰写本文时)既提供了付费的专业版py charm,也提供了名为社区的免费开源版。

通过单击下载,该文件将被下载为 tar.gz 文件。在撰写本文时,文件名是 pycharm-community-2020.2.3。

然后,可以将这个 tar.gz 文件解压缩到您选择的文件夹中:

资料来源:Ubuntu 18.04

如另一个教程中所述,导航到 bin 文件夹并打开一个终端。PyCharm 可以通过以下方式安装:

sh pycharm.sh

然后会打开一个相关的窗口,在这里可以定制 PyCharm 的默认设置。

在 PyCharm 中创建项目

如前所述,Python 3.6 是本例中 Python 的默认版本。在 PyCharm IDE 中,一旦选择了创建项目,将显示以下内容:

来源:PyCharm IDE

为了简单起见,这个项目被称为 pythonProject ,但是您可以为这个项目指定任何名称。从上面可以看出,python3.6 被选为基础解释器。在这种情况下,Python 3.6 和 Python 2.7 是系统上安装的仅有的两个版本。

来源:PyCharm IDE

一旦 Python 控制台启动,我们可以看到 Python 3.6.9 被加载。

也就是说,由于我们在自己的独立环境中使用这个版本的 Python,请注意相关的库必须单独安装到这个环境中。

例如,尝试运行 numpy 库第一次失败,因此需要在 PyCharm 项目中手动安装它,如下所示。

来源:PyCharm IDE

然而,当在标准的 Linux 终端(使用系统范围的版本)中运行时,库运行起来没有问题。

来源:PyCharm IDE

配置新的 Python 版本

如前所述,在许多情况下,用户需要使用不同于默认系统范围版本的 Python 版本。

对于这个例子,让我们假设我们希望安装 Python 3.8.0

正如来自的 Serhat Teker 的这个教程中所描述的,这个 Python 版本可以如下下载:

ssudo wget https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tgz

然后,tar 文件可以按如下方式解压缩:

sudo tar xzf Python-3.8.0.tgz

在这种情况下,我们不希望 Python 3.8 成为默认版本。假设系统上的许多其他 Python 代码以不同的版本命名(在这种情况下是 Python 3.6.9 ),那么直接升级 Python 可能会导致严重的依赖性问题,并导致库被弃用。

因此,必须使用 sudo make altinstall 而不是标准的sudo make install——后者将覆盖默认的 Python 版本。在这方面,必须导航到新下载的 Python 文件夹,配置并启用优化,然后使用 altinstall。

cd Python-3.8.0
sudo ./configure --enable-optimizations
sudo make altinstall

在终端中检查 Python 版本时,您会注意到 Python 3.6.9 的默认版本保持不变:

来源:Ubuntu 终端

但是,Python 3.8 也可以作为一个单独的版本来调用:

来源:Ubuntu 终端

我们可以通过终端中的 which 命令找到每个 Python 版本的安装位置:

来源:Ubuntu 终端

相应地,可以通过 PyCharm 设置新目录,基本解释器现在设置为 Python 3.8,如下所示:

来源:PyCharm IDE

相应地,当打开新项目的 Python 控制台时,我们可以看到 Python 3.8.0 现在已经加载。

来源:PyCharm IDE

如上例所示,需要为此环境单独安装库,并且需要配置依赖关系。

然而,PyCharm 符合我们试图实现的目标——在虚拟环境中安装一个单独的 Python 版本,而不影响系统范围的版本。

结论

在本例中,您看到了:

  • 如何在 Ubuntu 中安装多个版本的 Python
  • 创建不干扰系统范围 Python 版本的虚拟环境
  • 配置 PyCharm IDE 以使用不同的 Python 版本

在这方面,PyCharm 为使用不同的 Python 版本提供了一个非常有用的平台。安装的虚拟环境在技术上独立于 PyCharm 本身,可以简单地在终端上运行。然而,我们不能否认 PyCharm 确实使这个过程更加直观。

非常感谢您的阅读!非常感谢任何问题或反馈。你可以在michael-grogan.com找到更多我的数据科学内容。

免责声明:本文是在“原样”的基础上编写的,没有担保。它只是为了教育目的而写的,不应该被解释为任何形式的专业建议。我们不保证上述代码的执行适合您自己的系统,使用风险由您自行承担。

pydantic

原文:https://towardsdatascience.com/pydantic-688e897cfd3a?source=collection_archive---------5-----------------------

如果你篡改数据,你必须知道这个库

作者图片

拥有复杂的嵌套数据结构很难。在 Python 中存储这种数据的传统方法是嵌套字典。虽然 Python 字典很神奇,但通常会出现两个问题:(1)作为开发人员,我如何知道传递的字典中应该有哪种数据;( 2)我如何防止输入错误?

如果您使用类,您的编辑器或 mypy 可以防止属性名中的拼写错误。对于字典,任何有效的字符串都可以是一个键。

解决这两个问题的方法是使用一个库: pydantic 。它是一个验证和解析库,将数据映射到 Python 类。

先决条件

安装 pydantic via

pip install pydantic

对于本文,我假设您的数据是[people.json](https://gist.github.com/MartinThoma/517d20998501afc4fff72be032782d41)中的一个人的网络。他们有一个 ID,一个名字,一个由他们的 ID 给出的朋友列表,一个生日,以及他们银行账户上的金额。

我们想通过这个例子来计算每个人比他们的中位朋友多拥有多少财富。

我们想要解决的问题是:

  • 丑陋无:把None作为朋友的值是相当丑陋的。在某些情况下,None不同于空列表。在这种情况下,我们就假设它的意思是一样的。用其他东西替换缺失数据被称为插补,有几种技术。
  • 丑 Any :类型注释有Dict[str, Any],因为它被认为太复杂甚至不可能知道代表一个人的字典也能映射哪些值。
  • 难看的索引:只是语法,但是["id"].id长 50%。这就是 / 蒙克存在的原因。
  • 错别字:如果你在字典的任何一个字符串索引中出现了错别字,没有静态代码分析工具可以帮你检测出来。没有自动完成将正常工作。
  • 后期错误:好的软件将职责模块化。一个模块负责业务逻辑,一个模块负责输入/输出。当我写“模块”时,我指的是一个代码单元——它可以是一个 Python 模块、一个类、一个函数、一个方法。简单地用一个函数来处理这些不同类型的复杂性是不好的。获得正确的业务逻辑本质上不同于确保您的输入/输出看起来像预期的那样。一个是关于定义和验证适当的接口,另一个是关于理解领域。
  • 文档:新开发人员必须定期阅读更大应用程序的代码。通常,没有时间让对应用程序了如指掌的人详细解释每一个部分。大多数时候,甚至没有一个人什么都知道——即使项目是由一个开发人员完成的。我总是忘记部分代码。因此记录是至关重要的。在 Python 中,记录预期的参数类型及其返回值至关重要。有Dict[str, Any]总比没有好,但比Person差得多。

创建一个 pydantic 模型

我们为一个人的 ID 创建了一个新的类型,仅仅是因为 PersonId 比 T2 更有意义。然后我们子类化[pydantic.BaseModel](https://pydantic-docs.helpmanual.io/usage/models/#basic-model-usage)

将其用于输入解析

接下来,我们使用[parse_file_as](https://pydantic-docs.helpmanual.io/usage/models/#parsing-data-into-a-specified-type)来读取 JSON 文件:

请注意, datetime 和 Decimal 是自动解析的——您仍然应该经常查看它是如何完成的。尽早进行数据验证是有好处的,这样错误也会在已知的地方尽早发生。这意味着 pydantic 轻推你到一个好的设计。我喜欢它😍

约束类型

约束类型是某个取值范围内的整数/浮点数或与正则表达式匹配的字符串😃

缺少数据:使用默认值

如果您的 JSON 可能缺少一些您想要的属性,那么您需要使用默认值。典型的默认值是None,这意味着您需要将类型更改为Optional[what it was before]。这通常很难看,因为您需要在代码的后面检查None

特别是对于列表,您可能要考虑使用空列表。你这样做:

对于不可变的数据类型,比如字符串、整数、浮点数、元组,可以简单地赋值。对于可变列表,您需要使用带有default_factory的 Field,每次都会生成一个新列表。如果你还不知道的话,学习一下为什么可变缺省是邪恶的

附加数据:忽略、允许或禁止

有时在开发时不可能知道 JSON 对象具有哪些属性。尽管如此,你还是需要把它们传来传去。这是非常不幸的,应该受到挑战,但这是可能发生的。

Pydantic 称那些为临时演员。如果忽略它们,读取的 pydantic 模型将不会知道它们。被忽略的额外参数被丢弃。允许他们意味着接受这个不幸的设计是必要的。允许的额外内容将是解析对象的一部分。最后,禁止额外参数意味着如果出现额外参数,将抛出pydantic.ValidationError 异常

这是通过向 pydantic 模型添加一个名为Config的子类来配置的:

重命名属性

名字很重要。可读性计数。在 Python 中,变量应该遵循一个snake_case命名方案,而在 JavaScript 中,变量应该遵循一个camelCase命名方案。为了实现这两个目标,pydantic 提供了[allow_population_by_field_name](https://pydantic-docs.helpmanual.io/usage/model_config/)作为配置参数。

验证器

有时候,简单的类型是不够的。你想检查更复杂的东西。

文件已经给出了一个很好的例子:

你可以检查几乎任何东西,只要你只需要类本身。请不要对数据库运行查询来进行一致性检查;例如,如果您希望用户名是唯一的或类似的。尽管您可能会运行此操作,但通过创建“数据容器”来触发数据库查询将是意想不到的。

在我们的例子中,我们可能想要阻止人们成为自己的朋友:

除了抛出异常,我们还可以简单地修复它:

使用 Pydantic 进行基于属性的测试

Unsplash科学高清摄影

基于属性的测试自动生成被测函数的输入,并确保满足某个属性。在最简单的情况下,这个属性是测试中的函数不会崩溃。如果你想了解更多关于这种类型的测试,请阅读我的关于基于属性的测试和假设的文章。

顺便说一下,这个测试实际上指出了一个潜在的问题:

Falsifying example: test_two_people(
    person_a=Person(id=0, name='', bank_account=Decimal('NaN'), birthdate=datetime.date(2000, 1, 1), friends=[]),
    person_b=Person(id=0, name='', bank_account=Decimal('NaN'), birthdate=datetime.date(2000, 1, 1), friends=[]),
)

更整洁的东西

Pydantic 非常棒:

  • 您可以从它的模型中生成一个模式( source ),
  • mypy 插件提供了更好的类型检查
  • 对字典的序列化可以用.dict()方法完成,对 JSON 字符串的序列化可以用.json()方法完成。

操作安全

照片由本工程图Unsplash 上拍摄

我通常担心的一部分是普遍支持。以下是 pydantic 拥有健康社区的一些指标:

  • ✔️ GitHub : 4.5k 星,404 叉,172 贡献者
  • ✔️用法: FastAPI 使用它。微软的 Onefuzz 使用它。 AWS Lambda Powertools 也是如此。许多机器学习项目
  • PyPI 项目:很遗憾,这个只有一个维护者。如果有两个,我会更喜欢一点。只是为了防止有人丢失密码。
  • ✔️Self-decided 项目状态:维护者认为 pydantic 可以投入生产/稳定。

摘要

pydantic 是一个非常棒的数据解析和验证库。它可以很好地支持你在 Python 中获得更好的类型注释。用它!

非线性模型参数不确定性量化的 PyMC3 和贝叶斯推理(二)

原文:https://towardsdatascience.com/pymc3-and-bayesian-inference-for-parameter-uncertainty-quantification-towards-non-linear-models-a03c3303e6fa?source=collection_archive---------19-----------------------

参数和模型不确定性量化

导航的不确定性(作者图片)

在本系列的第 2 部分中,我们将深入 PyMC3,并学习如何将其应用于非线性模型的不确定性量化(UQ)。为了验证,我们还将看到贝叶斯方法如何与 UQ 参数的频率主义方法进行比较。我假设你已经为你的模型优化了参数。我将使用的模型来自本系列的第 1 部分。

我们将在本系列中使用的库如下:

将要使用的库

对于那些从第 1 部分跳到这里的人,或者那些需要重温第 1 部分的人,非线性模型是集总电容对象(多么拗口)的一阶瞬态热响应的解决方案。

集总电容物体一阶瞬态热响应的解

Python 中的函数

我们假设 T_0 = 100C,T_env = 30C。我们试图估计冷却参数τ和模型的不确定性。这个问题的日常例子是冷却保温良好的热饮!

热饮…也许我们把它放在一个非常好的保温瓶里(图片由作者提供)

PyMC3 下的贝叶斯推理

为了开始对模型参数的 UQ 进行贝叶斯推断,我们首先使用 PyMC3 创建一个模型,这里我在第 1 行将其称为“model_g”。

引用 Therese Donovan 和 Ruth M. Micket 的话[1],

“如果不使用先验分布,就无法进行贝叶斯分析”。

贝叶斯框架。p 代表概率。

这里我们的先验是 P(τ,ϵ),我们将把这个先验分解成两个先验,每个参数一个。而我们对τ的分布知之甚少或没有多少先验知识。然而,我们可以提供一个弱信息先验[2]。通过简单地画出τ的不同值,我们可以看出τ一定是有界的。我们将假设τ为均匀分布,下界为 0,上界为 100。我们可以看到,这很容易涵盖这个问题的可能值,然后一些。从第 1 部分中,我们发现τ的最佳参数是 14.93,从图中可以看出这是有意义的。

调查 tau 的前科

我们需要的下一个先验是误差的标准差,ϵ.我们知道这个参数不能小于 0,因为标准差总是大于或等于 0。半正态分布似乎适合于ϵ.的先验分布我们再次通过选择标度值为 5 的半正态分布来选择弱信息先验。我使用ϵ而不是第一部分中使用的σ,以避免与也用于衡量半正态分布的σ术语混淆

调查ϵ的前科

将所有内容结合在一起,第 5 行描述了预测温度“T_pred”来自使用我们的非线性牛顿冷却函数的平均值(μ)的正态分布。这个模型是我们的可能性,代表 p(数据| τ,ϵ)。我们还让 PyMC3 知道我们模型的标准偏差是ϵ.的先验分布最后,我们传递的最后一个参数是观察到的“实验”温度数据。

使用第 8 行,我们让 PyMC3 通过抽取 2000 个后验样本,使用 NUTS 采样来完成繁重的工作。我非常非常推荐去看看 Richard 的 McElreath 关于采样算法的网页。我们通常无法显式求解上述贝叶斯框架方程中的分子,因此我们必须使用采样算法来帮助我们探索它。

一旦执行了采样,我们就可以检索摘要

az.summary(trace_g)

跟踪摘要

在第 1 部分中,我们发现τ_opt = 14.93,σ的估计值=1.42。查看上表,我们的采样方法的平均值也提供了非常相似的结果,这是有道理的。我们之前做的优化也允许我们检查我们的贝叶斯推理。

我们参数的联合图

joint_plt = az.plot_joint(data_spp, var_names=['τ', 'ϵ'], kind='kde', fill_last=False);

使用上面的代码,我们可以通过对后验概率 P(τ,ϵ |数据)进行抽样来生成一个联合图。

我们还可以获得一个跟踪图,以验证我们的采样没有停滞,并且我们的采样充分探索了参数空间。我们想要像“毛毛虫”一样的痕迹。

trace_fig = az.plot_trace(trace_g,
 var_names=[ 'τ', 'ϵ'],
 figsize=(12, 8));

追踪图

我们还可以通过使用以下方法获得参数的最高后验密度(HPD ),这里我们选择 99%。

posterior_params = pm.plot_posterior(data_spp,
                                     point_estimate='mean',
                                     credible_interval=0.99,
                                     textsize=20,
                                     round_to=4);

如果没有噪声,我们的平均值将完全等于“未知”参数。由于存在噪声,就像真实数据一样,我们的参数值存在不确定性,我们需要量化其中的不确定性。

从第 1 部分可以看出,实际值τ=15,σ=1.5。不仅平均后验概率接近这些值,而且 HPD 很容易包含真实值,这正是我们想要的。

贝叶斯推理的好处之一是,除了计算参数的平均值,我们还可以得到参数的分布,如上所示。我们的非线性模型的 UQ 就像从我们的分布中取样一样简单,这是在上面的 sample_posterior.py 中完成的,为了清楚起见,下面使用方法

pm.sample_posterior_predictive()

计算模型中的不确定性,不仅从参数中,而且从数据中,是通过从我们的后验样本完成的。使用 NumPy 中的百分位数方法,从我们的后验预测中生成分位数是非常容易的。

将所有这些放在一起,让我们不仅绘制平均后验反应,而且绘制 95%后验预测。

参数和模型 UQ 的贝叶斯推断

频繁主义方法

如果我们想验证我们的贝叶斯推断,我们还应该将我们的结果与频率主义方法进行比较。由于模型是非线性的,这将需要更多的手工计算,但是对于我们将要使用的库来说,这应该不会太难。

首先,我们需要为模型“grad_newton_values”构建一个灵敏度矩阵。由于模型中只有 1 个参数,这个矩阵只是一个列向量。我们将使用自动签名库来自动区分关于τ的模型。

模型误差δk 可以从我们的灵敏度阵列中计算出来。利用δk、t-逆数值(1.99)和我们对第 1 部分中σ的估计(1.42),我们可以计算参数τ [3]的置信区间。

我们发现,在 95%的置信区间下,τ在 14.571 和 15.292 之间。非常接近贝叶斯方法!

接下来,我们想比较贝叶斯和频率主义方法之间的 UQ 传播在我们的模型。这包括模型参数和数据的不确定性。下面我为我们的非线性模型生成了置信区间和预测区间。

我用星形影线绘制了 95%的贝叶斯后验预测,用纯紫色绘制了 95%的频率预测区间。这两种方法几乎完全重叠,因为在紫色阴影区域下面可以看到星形影线。我们看到在边界上,最小的绿色。看起来我们的贝叶斯方法和频率主义方法是一致的。

根据这些预测,我们可以提供作为时间函数的饮料温度的不确定性。例如,在 25 分钟时,如果我们多次运行该实验,我们预计大多数热饮的温度在 40℃到 45℃之间,有 95%的把握。

两种方法的预测区间几乎相同

结论

我们对参数的估计以及模型本身进行了 UQ。我们已经发现 PyMC3 库对于处理非线性模型是多么强大,以及它与 Python 的集成是多么好。贝叶斯方法为我们如何开发和设计模型提供了极大的自由度。如果需要,我们可以将我们的可能性或温度模型从正态分布改为另一个参数模型。PyMC3 的过程不会有太大变化。

参考文献

[1] T. Donovan 和 R. M. Mickey,贝叶斯统计初学者:循序渐进的方法。牛津大学出版社。

[2] O. Martin,用 Python 进行贝叶斯分析:使用 PyMC3 和 ArviZ 进行统计建模和概率编程介绍,第 2 版。帕克特出版有限公司,2018 年。

[3] R. C. Smith,不确定性量化:理论、实施和应用。暹罗,2013 年。

非线性模型的 PyMC3 和贝叶斯推理:第一部分

原文:https://towardsdatascience.com/pymc3-and-bayesian-inference-for-parameter-uncertainty-quantification-towards-non-linear-models-d1d50250f16a?source=collection_archive---------24-----------------------

参数和模型不确定性量化

不确定的世界(作者图片)

像 Stan 这样的概率编程语言已经为科学家和工程师提供了进入贝叶斯统计世界的便利手段。作为一个熟悉 Python 编程的人,我一直在努力寻找完美的贝叶斯库来补充 Python 美妙而简洁的语法。

学习新材料和新图书馆的最大挑战之一是找到足够的资源和例子。我找不到一篇关于使用 Python 和贝叶斯推理对非线性模型进行参数和模型不确定性量化(UQ)的文章。因此,我希望这篇文章能帮助其他人将这些方法应用到他们自己的研究或工作中。

这将是一篇由两部分组成的文章,目的是让更多的读者能够阅读它,同时也让浏览和阅读文章变得更加容易。

第 1 部分将快速讨论贝叶斯推理的两个公共库:PyStan 和 PyMC3。我们还将建立一个非线性函数用于贝叶斯推理。这将包括通过 SciPy 库进行参数优化。我们将使用最佳参数作为我们贝叶斯推理的起点,并检查我们的贝叶斯方法。如果你已经熟悉了参数优化,可以直接跳到第 2 部分中的 PyMC3 部分。

第 2 部分是我们开始使用 PyMC3 并深入研究语法和结果的地方。为了验证,我们还将看到贝叶斯方法如何与频率主义方法进行参数不确定性量化的比较。

我不打算对 Baye 定理和整个贝叶斯框架进行过多的推测,有大量关于 Medium 的文章可以满足您的好奇心。本文的主要成果是让读者了解如何利用 PyMC3 来量化线性模型(尤其是非线性模型)中使用的参数和模型的不确定性。Jupyter 笔记本可以在这里找到。

PyStan

Stan 以 PyStan 的形式提供给 Python,但是语法相当令人不快。让我们看一个在 PyStan 中创建模型的例子,这个模型被分配给一个 string 类型的变量。然后这个模型会在 PyStan 的帮助下编译成 C++。

上面是一个简单的二次模型示例,它有两个参数,α和β,响应为 y。当开始使用更复杂的模型时,该模型非常冗长,很难调试。肯定有更 Pythonic 化的东西…

PyMC3

我相信 PyMC3 对于刚进入 Python 概率编程领域的人来说是一个完美的库。PyMC3 使用原生 Python 语法,使得调试更容易,也更直观。让我们深入一个例子,看看这个库的威力。

我们将使用的库

在这个例子中,我将使用一个简单的非线性方程的日常例子,希望这些概念更容易理解和记忆。

让我们从利用牛顿冷却定律来冷却一个热物体开始。我们假设物体中不存在热梯度(集总电容)。

让我们假设热物体是一种饮料(图片由作者提供)

对于那些对常微分方程(ODE)生疏的人来说,不用担心。解决方法如下。

T(t)表示在给定时间 t 饮料的温度。τ是我们感兴趣的参数,它决定了这个问题的冷却速率。T_env 是我们的环境温度,T_0 是 t=0 时饮料的温度。我们假设 T_env 不随时间变化。

在 Python 中:

让我们也假设我们提前知道,先验,环境温度是 30 摄氏度,物体开始于 100 摄氏度。最后,我们假设未知参数τ=15。

我们将首先绘制出热饮冷却的理论解,如蓝色实线所示。这里我们可以对方程和参数有一个直观的认识。

我们还将生成一些带有人工噪声的数据来模拟现实生活中的数据,这里显示为红色散射点。我们将假设数据是 IID 。饮料温度的响应是高斯型的,即 T(t)~ N(μ,σ)。平均值μ将遵循上面的解。我们将很快解决从数据本身不知道τ的问题。响应中的标准偏差为σ=1.5。这就是我们如何产生假噪声的,我们也能够从数据中估计出来。

根据这些模拟数据,我们想要估计冷却参数τ,并估计其值的不确定性。理想情况下,我们的估计参数和不确定性将封装真实值。同样,我们也希望模型标准误差中的不确定性包含σ。

为了阐明术语“封装”的含义,假设我们估计一个参数γ= 100 ^ 10。我们希望真实参数在 90–110 的范围内,与 100±10 相同。

优化:估计τ

在估算τ的不确定性之前,我们必须首先优化最符合数据的τ值。用更专业的术语来说,我们希望找到τ,使得残差平方和最小。

n 是数据点的数量

其中括号左侧的函数是我们的数据,括号右侧的函数是我们的 ODE 的解。

我们发现τ_opt = 14.93,非常接近τ=15 的真实参数的估计值。回到我们最初的问题,记住响应,饮料的温度,是高斯的,即 T(t)~ N(μ,σ)。我们终于有了τ的估计,我们可以检验正态性。

请记住,如果我们的响应来自高斯分布,那么我们的残差(数据减去预测)也必须是高斯分布。

residuals = T_data -  newton_cooling(tau_opt, T_0, T_env, time_data)

想一想,线性变换,或者更基本的,Z 值的变化。

残差,o =数据和我们的模型之间的差异,看起来很大,平均值大约为 0。它们看起来是随机的,同质的,大部分数据在两条红色虚线之间。

让我们看看我们是如何估算σ的

sigma_error_square = (1/(len(time_data)-1))*ss_min
sigma_error = np.sqrt(sigma_error_square)
print(sigma_error)

我们发现σ的估计值是 1.42,非常接近 1.5

剩余剧情。两条红色虚线代表 0 1.96*σ或 95%的数据。

不确定性量化

如果你还和我在一起,太好了!现在我们已经有了τ和σ的估计值,我们终于可以开始研究贝叶斯统计和 PyMC3 了。点击查看该系列的第二部分。

PyQGIS 连接表-厄瓜多尔自然保护区的国际游客

原文:https://towardsdatascience.com/pyqgis-join-table-international-visitors-in-natural-protected-areas-in-ecuador-7deb7ed8d868?source=collection_archive---------41-----------------------

如何在 PyQGIS 3.10 中使用连接表创建 choropleth 地图

PyQGIS 为管理 GIS 过程中的自动化提供了一个很好的解决方案。厄瓜多尔国家保护区系统(SNAP)以电子表格形式获取国际游客的信息,但不一定是地图。因此,如果需要地图,可以使用一个 python/PyQGIS 脚本来创建地图,该脚本可以输出适当的图层,包括受保护区域的游客数量。此处可在厄瓜多环境信息地理门户下载快照图层。

在这篇文章/教程中,我将向你展示如何在 Qgis 3.10 中将连接表自动化为 Shapefile。这个脚本最好的一点是,它通过 QInputDialog() 与用户(在本例中是您)进行交互,因此您必须使用的输入只是您的数据的 URL。

所以,我们来看看这个剧本的产物。如上所述,该脚本生成了一个新图层,其中包含添加到 自然保护区 的 shapefile 中的 游客数量 的附加信息。如果你不熟悉加入,看看这里的。

图片由作者提供,choropleth 地图包含国际游客数量的相关信息

首先,您必须在 Qgis 中打开 python 控制台并打开编辑器。

图片由作者提供,Python 控制台,编辑器窗口“无标题-0”位于右侧

我们的第一个任务是打开 shapefile,并在 Qgis 中打开表。在本教程中,您唯一需要做的就是复制和编辑数据的 URL。我的例子的 URL 如下:C:\ Desktop \ Pyqgis \ data \ natural _ areas . shp

首先,将下面的代码复制并粘贴到 python 编辑器中,然后运行。然后,您将看到一个新的对话窗口打开。

#Dialog 
qid1 = QInputDialog()
title = ‘Write the URL’
label = ‘Shapefile url: ‘
mode = QLineEdit.Normal
default = ‘<shp url here>’
snapUrl, ok = QInputDialog.getText(qid1, title, label,mode, default)#Adding Layer 
snap_layer = iface.addVectorLayer(snapUrl,’Natural Areas’,’ogr’)

图片作者,输入框添加您的 shapefile 的 URL

然后,您将看到 shapefile 如何像图层一样添加到内容列表中。添加 shapefile 时,您只需注意正确书写您计算机的 URL,包括扩展名 shp
( 例如\…\…\areas.shp )

作者的图片,屏幕上的 shapefile。

如您所见,您正在与 python 控制台进行交互。基本上就是在问你开什么,你在回复一个网址。下一步是执行相同的过程,但是包括显示的表格,在本例中是 。csv ,要与Natural areas . shp .进行连接记住,要正确处理连接表,两边需要有相似的属性。在这种情况下,shapefile 和表都有一个包含自然区域代码的列。
按照下面的代码打开表格。

#Dialog CSV june
qid2 = QInputDialog()
title = ‘url of table’
label = ‘csv url: ‘
mode = QLineEdit.Normal
default = ‘<csv url here>’
juncsvUrl, ok = QInputDialog.getText(qid2, title, label,mode, default)#Adding csv juneurljun = r’file:\\’+juncsvUrl+’?delimiter={}’.format(“,”)
juncsv = QgsVectorLayer(urljun, “June 2019”, “delimitedtext”)
iface.addVectorLayer(juncsvUrl, “June visitors”, “ogr”)

图片作者,输入收件箱添加您的 CSV 表的网址

然后,您将看到该表被添加到屏幕上。

图片由作者提供,屏幕上的 CSV 表。

目前,我们已经获得了连接表所需的数据。现在我们运行下面的代码来处理连接。你会看到一个新的消息框打开,要求一个网址,你必须写下你要保存新层的文件夹的网址。不要忘记包括扩展名。例如:①..\…\join.shp )。

如果你用的是自己的数据。请注意,在行字段中必须包含 shapefile 的列名,在字段 2 中必须包含 CSV 表的列名。

#Dialog JOIN 
qid4 = QInputDialog()
title = ‘Output layer of Join’
label = ‘url + \name.shp: ‘
mode = QLineEdit.Normal
default = ‘<new layer url here>’
out, ok = QInputDialog.getText(qid4, title, label,mode, default)#Join Table June
processing.run(“native:joinattributestable”, \
{‘INPUT’:snapUrl,\
‘FIELD’:’csnap’,\
‘INPUT_2’:juncsvUrl,\
‘FIELD_2’:’codt_snap’,\
‘FIELDS_TO_COPY’:[],\
‘METHOD’:1,\
‘DISCARD_NONMATCHING’:True,\
‘PREFIX’:’’,\
‘OUTPUT’: out,})jun_visitors = iface.addVectorLayer(out,’Visitors in June 2019',’ogr’)

作者的图像,新图层 URL 的消息框。

最后,您会看到新层被添加。包含访问者数量的那个。

图像由作者创建,屏幕上的新图层包含表中的数据。

这是您应该知道的关于将表连接到 shapefiles 的全部内容。您可以轻松地重写代码,并使其与您自己的数据一起工作。本教程是我关于 PyQGIS 的一个简短课程的一部分。如果您对更大的项目有任何疑问,请访问我的个人资料

Pyro 自上而下预测|应用案例

原文:https://towardsdatascience.com/pyro-top-down-forecasting-application-case-4781eb2c8485?source=collection_archive---------48-----------------------

将一段时间内的点连接起来,满怀信心地进行预测(-区间)。

跨越时间的连接点— 照片由伊斯雷尔·帕拉西奥在 Unsplash 上拍摄

你有没有想过如何解释时间序列预测中的不确定性?你有没有想过应该有一种方法从以前看到的数据中生成数据点,并对确定性做出判断?我知道我有。
如果你想建立捕捉概率并保持信心的模型,我们建议使用概率编程框架,如 Pyro
在之前的一篇文章中,我们研究了 NGBoosting,并将其应用于 Kaggle 上的 M5 预测挑战。简单回顾一下——M5 预测挑战要求我们预测沃尔玛商品的销售将如何发展。它提供了来自不同州的不同商店的不同类别的商品的大约 4-5 年的数据,并要求我们预测我们没有信息的 28 天。作为对挑战和数据集的概述,我们仍然推荐这款令人惊叹的笔记本。上次我们总结说,我们用 Pyro 得到了更好的结果,这里是一个简单的演示我们是如何做到这一点的。

随着时间的推移,有不同的方法来建模和预测数据。有自顶向下模型状态空间模型层次模型——仅举几个例子。在这篇文章中,我们看到了如何通过一个非常粗糙和基本的自顶向下的模型进行预测。我们充分利用了 Pyro 中现有的预测器对象。我们只是告诉模型如何做出明智的预测。之后,我们将所有数据转储到其中。就是这样——很简单!没有花哨的先验,没有花哨的潜在分布假设,只有数据和概率框架。我们还需要做一些假设,我们会带你经历这些。

Sidenote: One more elegant way to do forecasting is with hierarchical models. These models allow accounting for different distributions over different categories in your data. You can assign individual priors and make use of information that you have about your model. The elegance of such an approach will be covered in another post.

最后,我们将所有的时间序列信息转储到模型中,这是一段时间内的销售,同时将销售作为独立的随机事件保存。我们不用别的。
Pyro 编程框架,特别是 ForecastingModel ,是我们模型的引擎,我们还需要一个驱动程序。
推动我们的模型朝着正确方向发展的因素是:

prediction = regressor + trend + seasonal + motion + bias

这一行简单的代码结合了我们随时间采样的 Pyro 对象。现在,让我们看看所有这些部分的含义:

构建模型

实际模型零件由回归器捕获。这一部分寻找合适的模型权重,并将它们与直接来自数据输入的特征进行比较。每个权重都位于经典的高斯曲线上。这意味着我们从以零为中心、标准差为 1 (μ=0,σ =1)的正态分布中采样。

weight = pyro.sample("weight", dist.Normal(0, 1).expand(
        [feature.size(-1)]).to_event(1))
 regressor = (weight * feature).sum(-1)

第二个参数是趋势。我们参考我们的概率窥镜,然后决定它应该来自对数正态分布,例如 l∞LN,μ=-2,σ =1。一个关键的因素是我们考虑了我们提供给模型的时间特征。

trend_coef = pyro.sample("trend", dist.LogNormal(-2, 1))
trend = trend_coef * time

现在没有的趋势是什么?潮流来来去去,但季节是我们可以依靠的。我们知道基础数据描述了一段时间内的购买情况。我们认为销售额的变化是通过一周中的某一天来捕捉的。因此我们说

with pyro.plate("day_of_week", 7, dim=-1):
    seasonal = pyro.sample("seasonal", dist.Normal(0, 5))
seasonal = periodic_repeat(seasonal, duration, dim=-1)

这里我们使用了另一个简洁的烟火物体:盘子。这种结构用于模拟随机事件的独立性。这意味着我们正在观察一个实例的发生。这个观察来自我们数据的每个时间步。彻底的解释可以在烟火 SVI 教程中找到。出于简单的目的,我们将其分解,并说我们认为数据在七天的窗口内上升和下降。我们将其转化为独立采样的事件。最后但并非最不重要的是,不仅仅有一个七天的间隔,但是我们在我们所有给定的时间输入 aka 上周期性地重复这个。我们的持续时间是时间张量的大小。

最后,每一个专业的 ML 模型都需要一些可训练的参数,以说明有时事情并不像你期望的那样好——我们称之为偏差。我们决定我们的偏差(b)来自一个正态分布,这样 b∞N 其中μ=0 和σ =10 或 loc=0 和 scale=10,如果你想谈论 Pyro。

bias = pyro.sample("bias", dist.Normal(0, 10))

在我们继续之前,让我们看看参数的分布。

图 1——根据颜色绘制的所有采样参数的密度图。y 轴被截断,趋势对数正态分布的最大值为> 2.5。

你,细心的读者,可能会在这一点上得出结论。你有你需要的一切,我们同意。我们现在所拥有的足以给我们一个估计,并对未来几天做出预测。不过我们可以做得更好。到目前为止,我们预测的是一个非常僵硬的表达。模型被告知要符合输入,但我们不允许留有余地。为了便于讨论,让我们假设加州的所有人都决定在周四下午而不是周六去购物;或者危机发生,每个人都去为世界末日做准备。我们的模型可能已经正确预测了所有以前的星期六,但是那个星期四真的把它打乱了。为了解决这个问题,我们引入了一个叫做重新参数化的东西。有关该主题的详细概述,请参见[2]。
为了使它更加健壮,我们通过另一个重新参数化来进行重新参数化——我们这样做的原因在这里解释
将所有东西打包在一起,我们得到一个漂移,它定义了我们模型的运动。这就翻译成了烟火:

drift_stability = pyro.sample("drift_stability", dist.Uniform(1, 2))
drift_scale = pyro.sample("drift_scale", dist.LogNormal(-17, 5))
with self.time_plate:
   with poutine.reparam(config={"drift": LocScaleReparam()}):
      with poutine.reparam(config={"drift": SymmetricStableReparam()}):
         drift = pyro.sample("drift", dist.Stable(drift_stability, 0, drift_scale))
motion = drift.cumsum(dim=-1)

现在我们有了模型运行所需的一切。

你的工作模型

对于实际的模型拟合部分,我们使用 Pyro 的随机变量推理机或 SVI。这个算法允许我们在合理的时间内有效地计算后验分布。在我们的例子中,这样做是为了最大化证据下限或 ELBO 。考虑 ELBO 的一个简单方法是观察两个不同的分布,一个当前分布和一个先前分布。如果分布相差很大,我们会得到一个低的 ELBO 值。另一方面,如果我已经拟合了一个好的分布,我的下一个可能也一样好,与已经观察到的一个很好地对齐,并且我得到一个高的 ELBO 值。有些人甚至会说两种分布的差异被最小化。要详细阅读它,我们可以参考 SVI 的原始论文(见【3】)。现在让我们假设这是可行的,因为聪明的研究人员已经充分实现了它。

We will go into the interplay of Stochastic Variational Inference and ELBO (or minimizing KL) in another article.

现在,我们已经建立了一个工作模型,选择了我们的算法来计算我们的后验分布,我们必须设置超参数,加载数据并开始训练。对于数据处理,我们广泛关注 github 上的 M5 初学者工具包实现,这是 Pyro PPL 团队慷慨提供的。这是一种简单的方法,可以对销售数据等进行汇总。请自行实现。这是了解张量的可靠方法。对于我们的初学者模型,我们只关心一段时间内的销售数据。
我们现在设置参数并实例化预测器,如下所示:

forecaster_opt = {
    "learning_rate": 0.1,
    "learning_rate_decay": 0.1,
    "clip_norm": 10,
    "num_steps": 3501,
    "log_every": 100,
}
forecaster = Forecaster(TopDownModel(), data, covariates[:-28], **forecaster_opt)
samples = forecaster(data, covariates, num_samples=1000).exp().squeeze(-1).cpu()
pred = samples.mean(0)

在上面的代码中,我们安装了预测器,它使用了一个 DCTAdam 优化器。我们提供了培训的协变量,并保留了 28 天,我们在下面的行中将其用于实际预测。实际的预测是样本的平均值,但是我们不要在这里妄下结论。当我们运行上述代码并正确实现我们的模型时,我们应该得到以下输出—实际训练:

预测者训练过程用指定的模型结束了 3501 步的所有训练数据。随着时间的推移,损耗被最小化。

我们看到我们的损失减少了。这很好,它告诉我们,随着时间的推移,我们预测的计算分布会变得更好。这里的损失是相对于数据和部分预测者文档的负 ELBO 的商(见【4】)。

真正不确定的事情——自信和一切

我们现在在记忆中保存了一个最终模型。我们可以用它来计算损失,用它来对抗新数据,戳戳它,看看它会产生什么。
例如,我们可以对一段时间内的销售额进行采样,如下图所示:

图 2 —真实数据和随时间推移从拟合模型中采样的数据。红线表示最近可用(真实)的 14 天,而模型的抽样预测为浅绿色。报告的预测值是所有样本的平均值(绿线)。我们可以预测所需的 28 天。每个时间步长 10%-90%的置信区间用红色阴影显示。请参考下面的代码。

为了计算各个步骤的置信度,我们要求我们的模型有 100 个样本,并计算这些样本的分位数(0.1 和 0.9)。这就是你在图 2 中看到的红色区域。既然这个模型由你支配,如果你想使它更精确,你可以要求更多的样品。为了更好地拟合模型,图中的销售额是累计的记录值。要获得更真实范围内的值,请使用 numpy 的 exp 转换这些值。

总结

我们已经展示了如何构建 Pyro 模型并使用预测器实现。您可以使用您所知道的关于问题的事实来设置模型参数并找到合适的分布。Pyro 附带了很多功能。其中之一是 SVI,一种计算后验概率的算法,这使得模型训练首先成为可能。在我们拟合我们的模型后,我们可以从中取样,预测数据点并计算我们预测的置信区间。总而言之,概率编程和 Pyro 之类的框架提供了一个强大的工具集,在处理不确定性和对现实世界数据建模时可以使用。

完整的型号代码

class TopDownModel(ForecastingModel):
  """
  Top-Down Hierarchical Forecasting Model
  """
  def model(self, zero_data, covariates):
    # check univariate data
    assert zero_data.size(-1) == 1 
    duration = zero_data.size(-2) time, feature = covariates[..., 0], covariates[..., 1:] bias = pyro.sample("bias", dist.Normal(0, 10))
    trend_coef = pyro.sample("trend", dist.LogNormal(-2, 1))
    trend = trend_coef * time weight = pyro.sample("weight", dist.Normal(0, 1).expand(
        [feature.size(-1)]).to_event(1))
    regressor = (weight * feature).sum(-1) # weekly seasonality as independent events
    with pyro.plate("day_of_week", 7, dim=-1):
      seasonal = pyro.sample("seasonal", dist.Normal(0, 5))
    seasonal = periodic_repeat(seasonal, duration, dim=-1) drift_stability = pyro.sample("drift_stability", dist.Uniform(1, 2))
    drift_scale = pyro.sample("drift_scale", dist.LogNormal(-17, 5)) # introduce drift
    with self.time_plate:
          # We combine two different reparameterizers: the inner SymmetricStableReparam
          # is needed for the Stable site, and the outer LocScaleReparam improves inference.
          with poutine.reparam(config={"drift": LocScaleReparam()}):
              with poutine.reparam(config={"drift": SymmetricStableReparam()}):
                  drift = pyro.sample("drift",
                                      dist.Stable(drift_stability, 0, drift_scale))
    motion = drift.cumsum(dim=-1) # predict
    prediction = regressor + trend + seasonal + motion + bias
    # Pyro Forecast is multivariate - univariate timeseries is needed
    prediction = prediction.unsqueeze(-1) # heavy tail nose to account for outliers
    stability = pyro.sample("noise_stability", dist.Uniform(1, 2).expand([1]).to_event(1))
    skew = pyro.sample("noise_skew", dist.Uniform(-1, 1).expand([1]).to_event(1))
    scale = pyro.sample("noise_scale", dist.LogNormal(-5, 5).expand([1]).to_event(1))
    noise_dist = dist.Stable(stability, skew, scale)
    with poutine.reparam(config={"residual": StableReparam()}):
      self.predict(noise_dist, prediction)

抽样和绘制置信区间

# sample from the fitted model to forecast data
samples = forecaster(data[T0:T1], covariates[T0:T2], num_samples=100)
samples.clamp_(min=0)p10, p50, p90 = quantile(samples[:, :], (0.1, 0.5, 0.9)).squeeze(-1)fig, ax = plt.subplots()ax.set_title("aggregated (log1p) sales over 42 days")
ax.plot(data[T1:T2].squeeze(-1).cpu().numpy(), "r-",lw=4, label="truth")
ax.fill_between(np.arange(0, (T2-T1)), p10.cpu().numpy(), p90.cpu().numpy(), alpha=0.3, color="red", label="confidence")
ax.plot(samples.squeeze(-1).T.cpu().numpy()[:, 10:13], color="green", alpha=0.35, label="sample")
ax.plot(np.mean(samples.squeeze(-1).T.cpu().numpy()[:, :], axis=1),color="green", lw=2, alpha=0.75, label="mean")
ax.set_xlabel("t in days")
ax.set_ylabel("aggregated sales")
labels = np.arange(len(covariates)-42, len(covariates), step=8)
ax.set_xticklabels(labels)
plt.ylim((9.5, 11.2))
plt.legend(loc='lower right')
plt.show()

承认

非常感谢 Pyro 文档和开发团队。GitHub 上关于主题和实现的全面写作确实使 Pyro 用户能够立即投入使用。我们的模型是不同模型的混合实验,我们测试了哪些部分可以很好地协同工作。

参考

  1. Pyro 文档—预测教程 IIIIII
  2. 米(meter 的缩写))戈里诺瓦,d .摩尔,m .霍夫曼。概率程序的自动重新参数化。2019 发表于 ArXiv
  3. 米(meter 的缩写))霍夫曼等人在随机变分推理。 2013 年。在 JMLR
  4. 优步技术公司。2018.烟火预报员见文件

PySnpTools

原文:https://towardsdatascience.com/pysnptools-9038f994fdd7?source=collection_archive---------56-----------------------

在 Python 中读取和操作基因组数据

国立癌症研究所Unsplash 拍摄的照片

PySnpTools 是一个 Python 库,用于读取和操作 Python 中的基因组数据。它允许用户有效地选择和重新排序个体(行)和 SNP 位置(列)。然后,它只读取选定的数据。PySnpTools 最初是为了支持快速 LMM——一种全基因组关联研究(GWAS)工具——而开发的,现在支持大内存和集群规模的工作。

2022 年 3 月 22 日更新:更新示例以匹配本笔记本

介绍

当我们开发快速 LMM 包(1;2;3;4;5;6),我们厌倦了重新编写代码来支持越来越多的文件格式(例如,PLINK 的 Bed,Dat,Pheno 等。) (7;8).此外,我们注意到自己重复地进行类似的操作,例如,

  • 读取 SNP 子集(列)的数据,
  • 对我们的表型数据中的个体(行)进行重新排序,以匹配它们在 SNP 数据中的顺序,以及
  • 填补缺失数据和规范化数据。

受 NumPy 和 Pandas 的启发,我们创建了 PySnpTools,这是一个开源库,使这些操作变得简单。

我们在西雅图的 PyData 2015 大会上展示了 PySnpTools 的第一个公开版本。

在会议上,Travis oli phant(NumPy 的主要创建者)推荐了 PySnpTools 读取和操作基因组数据的方法(9)。

会议结束后不久,希拉里·菲纽肯(麻省理工学院和哈佛大学布罗德研究所菲纽肯实验室的负责人)写信给我们:

“我一直喜欢 PySnpTools,并向其他使用 Python (10)的统计遗传学家推荐它!”

自会议以来,随着 FaST-LMM 发展到支持多达 100 万个样本的数据集(6),我们扩展了 PySnpTools 以简化:

  • 大于内存的数据集
  • 在多个处理器或任何集群上运行循环,以及
  • 在本地或从/向任何远程存储器读写文件。

最近,我们已经使用多线程来加快读床速度,并增加了对 BGEN 格式的支持。

本文讲述了如何安装 PySnpTools,并描述了 PySnpTools 关注的基因组数据。然后给出了核心用法的例子。最后,它列出了 PySnpTools 的其他特性,并提供了与其他数据集方法的简要比较。

安装 PySnpTools

要使用 PySnpTools:

pip install pysnptools

你可以在https://github.com/fastlmm/PySnpTools找到 Jupyter 笔记本、完整的 API 文档和示例以及源代码。

基因组数据

我们感兴趣的基因组数据通常由 500,000 到 150 万列组成——每个 SNP 或变体一列(这是已知人类不同的基因组位置)。数据包括每个人的一行。一千到一百万行是典型的。初始数据中的值可能是 0、1、2 或缺失(代表在一个基因组位置为一个个体测量的次要等位基因的数量)。标准化后,值是 64 位或 32 位浮点数,缺少的值用 NaN(“非数字”)表示。

图 1 显示了 PySnpTools 对基因组数据的内存表示。被称为iid的两个字符串标识每个个体。一个名为**sid**的字符串识别每个 SNP。一种叫做**val**的浮动,告诉一个 SNP 个体的等位基因数。最后,名为**pos**的三重浮点表示每个 SNP 的位置(染色体数目、遗传距离和碱基对位置)。对于**val**中的一个给定位置,PySnpTools 可以轻松找到对应的**iid****sid****pos.** 而且,对于任何感兴趣的**iids****sids** ,PySnpTools 都可以轻松高效地在**val**中找到对应的位置。

图一。PySnpTools 的基因组数据的内存表示

对于表型和协变量数据(例如,年龄、性别、身高、体重、疾病的存在),PySnpTools 使用相同的表示法。对于这样的数据,**sid** 给出特征的名称(,“高度”),而**pos**被忽略。**val** 数组作为浮点数,也可以通过 0.0 和 1.0 表示二进制数据。我们通过 hot-one 编码处理分类数据。

读取基因组文件:一个例子

PySnpTools 将从文件中读取基因组数据的 Python 对象称为 SnpReader。下面是如何为流行的 Bed 文件格式创建 SnpReader:我们告诉它要读取什么文件以及如何读取。(这个 SnpReader 还没有从它的文件中读取任何内容。)

输入:

*# Download BED files and return local file name*
**from** **pysnptools.util** **import** example_file
all_bed_file = example_file("doc/ipynb/all.*",endswith="*.bed"**from pysnptools.snpreader import Bed** snpreader = Bed(all_bed_file, count_A1=True)
print(snpreader)

输出:

Bed("[...]/all.bed",count_A1=True)

我们可以向 SNP 阅读器询问个体的数量和 SNP 的数量。我们也可以,例如,要求它为第一个体的**iid** 。我们可以另外向它索要最后一个 SNP 的**sid** 。(Bed SnpReader 只读取回答这些问题所需的小文件。)

输入:

print(snpreader.iid_count,snpreader.sid_count)
print(snpreader.iid[0])
print(snpreader.sid[-1])

输出:

500 5000
['cid0P0' 'cid0P0']
snp124_m0_.23m1_.08

接下来,我们可以将所有基因组数据读入内存,创建一个新的 SnpReader,称为 SnpData。因为 SnpData 是 SnpReader,我们可以再次询问个体和 SNP 的数量。

输入:

snpdata = snpreader.read()
print(snpdata)
print(snpdata.iid_count, snpdata.sid_count)

输出:

SnpData(Bed('all.bed',count_A1=True))
500 5000

SnpData 是一个 SnpReader,它包含一个其他 SNP reader 没有的额外的**val** 属性。**val** 属性是基因组数据的(内存中)NumPy 数组。

例如,我们可以显示前 7 个个体和前 7 个 SNPs 的基因组数据。我们还可以找到所有基因组数据的平均值。

输入:

**import** **numpy** **as** **np** print(snpdata.val[:7,:7])
print(np.mean(snpdata.val))

输出:

[[0\. 0\. 1\. 2\. 0\. 1\. 2.]
 [0\. 0\. 1\. 1\. 0\. 0\. 2.]
 [0\. 0\. 1\. 2\. 1\. 0\. 0.]
 [0\. 0\. 0\. 2\. 0\. 0\. 0.]
 [0\. 0\. 0\. 0\. 0\. 0\. 2.]
 [0\. 0\. 1\. 0\. 0\. 0\. 2.]
 [0\. 0\. 2\. 1\. 0\. 1\. 2.]]
0.521412

或者,我们可以在一行中做所有的事情。

输入:

print(np.mean(Bed(all_bed_file,count_A1=**True**).read().val))

输出:

0.521412

SnpData

SnpData,特殊的内存 SnpReader,由任何 SnpReader 的**read()** 方法创建。我们还可以从头开始创建 SnpData。

这里我们为三个个体和两个 SNP 创建**snpdata1** 。我们用 NaN 标记一个缺失值,然后求平均值(忽略缺失值)。

输入:

**from pysnptools.snpreader import SnpData**
snpdata1 = SnpData(iid=[['f1','c1'],['f1','c2'],
                       ['f2','c1']],
                   sid=['snp1','snp2'],
                   val=[[0,1],[2,.5],[.5,np.nan]])
print(np.nanmean(snpdata1.val))

输出:

0.8

在读取前选择并重新排序数据

假设我们只关心前 7 个个体和前 7 个 SNP 的基因组数据。PySnpTools 使从磁盘中读取所需的数据变得很容易。我们在 read 方法之前使用类似 NumPy 的索引。

输入:

*snpreader = Bed(all_bed_file,count_A1=**True**)
snpdata77 = snpreader[:7,:7].read()
print(snpdata77.val)*

输出:

*[[0\. 0\. 1\. 2\. 0\. 1\. 2.]
 [0\. 0\. 1\. 1\. 0\. 0\. 2.]
 [0\. 0\. 1\. 2\. 1\. 0\. 0.]
 [0\. 0\. 0\. 2\. 0\. 0\. 0.]
 [0\. 0\. 0\. 0\. 0\. 0\. 2.]
 [0\. 0\. 1\. 0\. 0\. 0\. 2.]
 [0\. 0\. 2\. 1\. 0\. 1\. 2.]]*

支持所有类似 NumPy 的花哨索引:切片、布尔、整数列表、负整数(11)。此外,PySnpTools 允许同时对行和列进行有趣的索引。

将索引附加到任何 SnpReader,创建一个新的 SnpReader。这里有一个极端的例子。它说,“创造一个阅读器

  • 来自 bed 格式的文件“all.bed”
  • 个体以相反的顺序并且对于每第二个 SNP
  • 对于前 5 个这样的个体和前 5 个这样的 SNP
  • 对于第一个和最后一个个体以及第一个、第二个和第五个 SNP,
  • 然后读。"

和以前一样,只从磁盘中读取最终所需的数据。

输入:

*print(Bed(all_bed_file,count_A1=**True**)[::-1,::2][:5,:5]
       [[0,-1],[True,True,False,False,True]]
       .read().val)*

输出:

*[[0\. 0\. 1.]
 [0\. 1\. 1.]]*

通过单个(行)和 SNP(列)标识符进行索引

我们已经看到了如何使用基于位置的索引来操作 SnpReaders。如果我们转而希望通过**iid** (个体的标识符)或**sid**(SNPs 的标识符)来操纵 SnpReaders 呢?这是一个更像熊猫的场景。在这种情况下,我们可以使用**iid_to_index()****sid_to_index()** 的方法。

这个例子显示了如何读取三个感兴趣的 SNP,每个 SNP 由**sid**而不是位置识别。

输入:

***desired_sid_list = ['snp1750_m0_.02m1_.04',
              'snp0_m0_.37m1_.24','snp122_m0_.26m1_.34']
snpreader = Bed(all_bed_file,count_A1=**True**)
desired_snpreader = \
    snpreader[:,snpreader.sid_to_index(desired_sid_list)]
print(desired_snpreader.iid_count,
      desired_snpreader.sid_count)***

输出:

***500 3***

读者和伪读者

PySnpTools 包括这些常见文件格式的 SNP reader:Bed、Pheno、Dat、Ped、Dense。它还定义了这些新的二进制格式:SnpNpz、SnpHdf5 和 SnpMemMap。最后一点很有趣,因为它使用 NumPy 的内存映射数组来提供对大于内存容量的数据的内存访问。PySnpTools 还定义了一种称为 DistributedBed 的格式,这种格式提供了对密集存储在几十个(或几百或几千个)Bed 文件中的数据的随机访问。

此外,PySnpTools 还包括 SnpGen,可以称之为“伪阅读器”。对于任何使用 SnpGen 的程序来说,它看起来像一个文件阅读器,但它不是从磁盘读取数据,而是动态生成随机的基因组数据。基于用户提供的种子的这一代是确定性的。

除了阅读 SNPS,PySnpTools 还包括大量内核数据的读者和伪读者。(核数据表示个体之间成对的相似性。)

如果 PySnpTools 不支持感兴趣的数据格式,您有两种选择。如果您的数据相对较小,您可以使用其他 Python 工具读取它,然后创建内存中的 SnpData(或 SnpMemMap)对象。如果需要更高的性能,可以为该格式编写一个新的 SnpReader 模块。在这两种情况下,为 SnpReader 编写的任何程序都将自动使用新的数据格式。

超越阅读

最近,当我们努力将快速 LMM 扩展到 100 万个样本时,我们向 PySnpTools 添加了更多功能。PySnpTools 现在包括以下工具:

  • 标准化 SNP 数据和内核,
  • 交叉(和排序)来自任何数量 SnpReaders 的个体(在一行中),
  • 有效地处理大整数范围,
  • 编写循环,以便它们可以在多个处理器或任何集群(由一个模块定义)上运行,以及
  • 向任何本地或任何分布式文件系统(由模块定义)读写文件。

与其他数据集格式相比

在 PyData 2015 上,Joshua Bloom 比较了用于数据科学的数据集工具(12)。表 1 用 PySnpTools 更新了他的表。基本上,与 xarray 非常相似,PySnpTools 用不可变的索引行和列标识符来修饰 2d NumPy 数组。这给了我们方便和高效率,但比其他方法更特殊的目的。PySnpTools 还延迟了所有的复制(和读取),直到**read()** 方法被显式调用,这给了我们效率和可预测性。

表 1。Bloom 的数据科学数据集,加上 PySnpTools

摘要

PySnpTools 是一个 Python 库,用于读取和操作基因组数据。受 NumPy 和 Pandas 的启发,PySnpTools 可以被认为是一种向基因组数据添加熊猫式索引的方法。要安装 PySnpTools:

pip install pysnptools

你可以在https://github.com/fastlmm/PySnpTools找到 Jupyter 笔记本、完整的 API 文档和示例以及源代码。

感谢

感谢 FaST-LMM 团队中的每个人,他们的使用和反馈为 PySnpTools 的设计提供了信息。特别感谢 Christoph Lippert,他编写了我们最初的 BED reader,以及 David Heckerman,他鼓励了 PySnpTools 的开发。

参考

1.用于全基因组关联研究的快速线性混合模型。【Lippert,c .】等*** 2011,《自然方法》,8 833–835 页。***

2.对扩展的威康信托数据进行详尽的上位 SNP 关联分析。 Lippert,c .等人 2013 年,科学报告 3,1099。**

3.基于核的遗传变异集关联测试的能力和计算效率更高。 **李柏特,C,等*** 2014,生物信息学 30,22。***

4.对全基因组关联研究线性混合模型的进一步改进。 **Widmer,c .,等*** 2015,科学报告,4 6874。***

5.遗传力估计的线性混合模型。 赫克曼,D. 等人 2016 年美国国家科学院院刊 113 期(27)。**

6.用于全基因组关联研究的 Ludicrous Speed 线性混合模型。 卡迪,C. &海克尔马,D. 2019,bioRxiv 154682。

7.珀塞尔,s .普林克。【http://zzz.bwh.harvard.edu/plink/.在线】

8. PLINK:全基因组关联和基于人群的工具集。 Purcell,S. 2007,美国人类遗传学杂志,81。

9.奥列芬特,t。2015.

10.个人通信。2015.

11.分度* NumPy 用户指南。【在线】https://docs . scipy . org/doc/numpy/reference/arrays . indexing . html***

12.机器学习的系统观点。 布鲁姆,J. 西雅图:s.n .,2015。PyData。

PySpark 和 SparkSQL 基础知识

原文:https://towardsdatascience.com/pyspark-and-sparksql-basics-6cb4bf967e53?source=collection_archive---------0-----------------------

使用 PySpark 实施大数据

如何用 Python 编程实现 Spark

【来源】

Python 通过 Spark Python API 揭示了 Spark 编程模型来处理结构化数据,该 API 被称为 PySpark

这篇文章的目的是演示如何用 PySpark 运行 Spark 并执行常见的函数。

Python 编程语言需要安装 IDE。使用 Python 和 Anaconda 的最简单的方法,因为它安装了足够的 IDE 和重要的包。

1.下载 Anaconda 并安装 PySpark

借助这个 链接 ,可以下载 Anaconda。下载合适的 Anaconda 版本后,点击它继续安装程序,安装程序在 Anaconda 文档 中有详细说明。

安装完成后,将会打开 Anaconda Navigator 主页。要使用 Python,只需点击“笔记本”模块的“启动”按钮。

Anaconda Navigator 主页(图片由作者提供)

为了能够通过 Anaconda 使用 Spark,应该遵循下面的包安装步骤。

Anaconda 提示终端

康达安装 pyspark

康达安装 pyarrow

PySpark 和 PyArrow 包安装完成后,只需关闭终端,返回 Jupyter Notebook,在代码顶部导入所需的包。

import pandas as pd
from pyspark.sql import SparkSession
from pyspark.context import SparkContext
from pyspark.sql.functions 
import *from pyspark.sql.types 
import *from datetime import date, timedelta, datetime
import time

2.正在初始化 SparkSession

首先,需要初始化一个 Spark 会话。在 SparkSession 的帮助下,可以创建 DataFrame 并将其注册为表。而且执行 SQL 表,可以缓存表,可以读取 parquet/JSON/CSV/Avro 数据格式的文件。

sc = SparkSession.builder.appName("PysparkExample")\    
.config ("spark.sql.shuffle.partitions", "50")\    .config("spark.driver.maxResultSize","5g")\    
.config ("spark.sql.execution.arrow.enabled", "true")\    .getOrCreate()

关于 SparkSession 各个参数的详细解释,敬请访问py spark . SQL . spark session

3.创建数据框

数据帧可以被接受为标题列的分布式列表集合,类似于关系数据库中的表。在本文中,我们将在 PySpark API 上使用 DataFrame 操作来处理数据集。

你可以从这个链接下载 Kaggle 数据集。

3.1。来自星火数据来源

可以通过读取文本、CSV、JSON 和拼花文件格式来创建数据帧。在我们的例子中,我们将使用一个. json 格式的文件。您还可以通过使用如下所示的相关读取函数来查找和读取文本、CSV 和拼花文件格式。

**#Creates a spark data frame called as raw_data.****#JSON**
dataframe = sc.read.json('dataset/nyt2.json')**#TXT FILES#** 
dataframe_txt = sc.read.text('text_data.txt')**#CSV FILES#** 
dataframe_csv = sc.read.csv('csv_data.csv')**#PARQUET FILES#** 
dataframe_parquet = sc.read.load('parquet_data.parquet')

4.重复值

使用 dropDuplicates()函数可以消除表中的重复值。

dataframe = sc.read.json('dataset/nyt2.json') 
dataframe.show(10)

(图片由作者提供)

在应用 dropDuplicates()函数之后,我们可以观察到重复项被从数据集中删除了。

dataframe_dropdup = dataframe.dropDuplicates() dataframe_dropdup.show(10)

(图片由作者提供)

5.问题

查询操作可以用于各种目的,例如用 "select" 子集化列,用 "when" 添加条件,用 "like "过滤列内容。下面举例说明一些最常用的操作。有关查询操作的完整列表,请参见 Apache Spark 文档

5.1。【选择】操作

可以通过属性(“作者”)或索引(dataframe['author'])来获取列。

**#Show all entries in title column**
dataframe.select("author").show(10)**#Show all entries in title, author, rank, price columns**
dataframe.select("author", "title", "rank", "price").show(10)

第一个结果表只显示“作者”选择,第二个结果表显示多列(作者的图像)

5.2。【当】操作

在第一个示例中,选择了“title”列,并添加了一个带有“when”条件的条件。

**# Show title and assign 0 or 1 depending on title**dataframe.select("title",when(dataframe.title != 'ODD HOURS', 
1).otherwise(0)).show(10)

显示 10 行指定条件(图片由作者提供)

在第二个示例中,应用了“isin”操作,而不是“when ”,后者也可用于为行定义一些条件。

**# Show rows with specified authors if in the given options**dataframe [dataframe.author.isin("John Sandford", 
"Emily Giffin")].show(5)

结果集显示 5 行指定的条件(图片由作者提供)

5.3。【喜欢】操作

在“Like”函数的括号中,%字符用于过滤掉所有包含“the”单词的标题。如果我们正在寻找的条件是完全匹配的,那么不应该使用%字符。

**# Show author and title is TRUE if title has " THE " word in titles**dataframe.select("author", "title",
dataframe.title.like("% THE %")).show(15)

包含“THE”单词的标题的结果集。(图片由作者提供)

5.4

从单词/内容的开头开始扫描,并在括号中指定标准。并行地,EndsWith 从末尾开始处理单词/内容。这两个函数都区分大小写。

dataframe.select("author", "title", dataframe.title.startswith("THE")).show(5)dataframe.select("author", "title", dataframe.title.endswith("NT")).show(5)

结果集有 5 行 startsWith 和 endsWith 操作。(图片由作者提供)

5.5。【子串】操作

Substring 函数提取指定索引之间的文本。在以下示例中,从索引号(1,3)、(3,6)和(1,6)中提取文本。

dataframe.select(dataframe.author.substr(1, 3).alias("title")).show(5)dataframe.select(dataframe.author.substr(3, 6).alias("title")).show(5)dataframe.select(dataframe.author.substr(1, 6).alias("title")).show(5)

分别显示子字符串(1,3)、(3,6)、(1,6)的结果。(图片由作者提供)

6.添加、更新和删除列

DataFrame API 中也提供了数据操作函数。下面,您可以找到添加/更新/删除列操作的示例。

6.1。添加

**# Lit() is required while we are creating columns with exact values.**dataframe = dataframe.withColumn('new_column', 
F.lit('This is a new column'))display(dataframe)

新列被添加到数据集的末尾(图片由作者提供)

6.2。更新列

对于 DataFrame API 的更新操作,withColumnRenamed()函数使用两个参数。

**# Update column 'amazon_product_url' with 'URL'**dataframe = dataframe.withColumnRenamed('amazon_product_url', 'URL')dataframe.show(5)

“Amazon_Product_URL”列名更新为“URL”(图片由作者提供)

6.3。移除列

可以通过两种方式删除列:在 drop()函数中添加列名列表,或者通过在 drop 函数中指向来指定列。两个示例如下所示。

dataframe_remove = dataframe.drop("publisher", "published_date").show(5)dataframe_remove2 = dataframe \ .drop(dataframe.publisher).drop(dataframe.published_date).show(5)

“publisher”和“published_date”列以两种不同的方法删除。(图片由作者提供)

7.检查数据

存在几种类型的函数来检查数据。下面,你可以找到一些常用的。要深入了解,请访问 Apache Spark 文档

**# Returns dataframe column names and data types**
dataframe.dtypes**# Displays the content of dataframe**
dataframe.show()**# Return first n rows**
dataframe.head()**# Returns first row**
dataframe.first()**# Return first n rows**
dataframe.take(5)**# Computes summary statistics**
dataframe.describe().show()**# Returns columns of dataframe**
dataframe.columns**# Counts the number of rows in dataframe**
dataframe.count()**# Counts the number of distinct rows in dataframe**
dataframe.distinct().count()**# Prints plans including physical and logical**
dataframe.explain(4)

8.“分组”操作

通过在函数中添加列名,使用 GroupBy()函数应用分组过程。

**# Group by author, count the books of the authors in the groups**dataframe.groupBy("author").count().show(10)

作者按出版的书籍数量分组(图片由作者提供)

9.“过滤”操作

通过使用 filter()函数并在其中添加一个条件参数来应用过滤。该函数区分大小写。

**# Filtering entries of title
# Only keeps records having value 'THE HOST'**dataframe.filter(dataframe["title"] == 'THE HOST').show(5)

标题列被过滤,内容只有“主机”并显示 5 个结果。(图片由作者提供)

10.缺少和替换值

对于每个数据集,在数据预处理阶段总是需要替换现有值、删除不必要的列和填充缺失值。py spark . SQL . dataframenafunction库帮助我们在这方面操作数据。下面补充一些例子。

**# Replacing null values**
dataframe.na.fill()
dataFrame.fillna()
dataFrameNaFunctions.fill()**# Returning new dataframe restricting rows with null** valuesdataframe.na.drop()
dataFrame.dropna()
dataFrameNaFunctions.drop()**# Return new dataframe replacing one value with another**
dataframe.na.replace(5, 15)
dataFrame.replace()
dataFrameNaFunctions.replace()

11.分配

可以增加或减少 RDD 中现有的分区级别。增加可以通过使用 repartition(self,numPartitions) 函数来实现,该函数会产生一个获得更多分区数量的新 RDD。减少可以用 coalesce(self,numPartitions,shuffle=False) 函数处理,该函数产生一个新的 RDD,其分区数量减少到指定的数量。更多信息请访问Apache Spark docs

**# Dataframe with 10 partitions**
dataframe.repartition(10).rdd.getNumPartitions()**# Dataframe with 1 partition**
dataframe.coalesce(1).rdd.getNumPartitions()

12.以编程方式运行 SQL 查询

还可以通过在 SparkSession 上启用“sql”操作来使用原始 SQL 查询,从而以编程方式运行 SQL 查询,并将结果集作为 DataFrame 结构返回。更多详细信息,敬请访问Apache Spark docs

**# Registering a table**
dataframe.registerTempTable("df")sc.sql("select * from df").show(3)sc.sql("select \               
CASE WHEN description LIKE '%love%' THEN 'Love_Theme' \               WHEN description LIKE '%hate%' THEN 'Hate_Theme' \               WHEN description LIKE '%happy%' THEN 'Happiness_Theme' \               WHEN description LIKE '%anger%' THEN 'Anger_Theme' \               WHEN description LIKE '%horror%' THEN 'Horror_Theme' \               WHEN description LIKE '%death%' THEN 'Criminal_Theme' \               WHEN description LIKE '%detective%' THEN 'Mystery_Theme' \               ELSE 'Other_Themes' \               END Themes \       
from df").groupBy('Themes').count().show()

13.输出

13.1。数据结构**

DataFrame API 使用 RDD 作为基础,它将 SQL 查询转换为低级 RDD 函数。通过使用。rdd 操作,一个数据帧可以转换成 RDD。也可以将 Spark Dataframe 转换成一串 RDD 和熊猫格式。

**# Converting dataframe into an RDD**
rdd_convert = dataframe.rdd**# Converting dataframe into a RDD of string** dataframe.toJSON().first()**# Obtaining contents of df as Pandas** 
dataFramedataframe.toPandas()

不同数据结构的结果(图片由作者提供)

13.2。写&保存到文件**

作为数据帧加载到我们代码中的任何数据源类型都可以很容易地转换并保存为其他类型,包括。parquet 和. json .更多保存、加载、写函数细节请访问Apache Spark doc

**# Write & Save File in .parquet format**
dataframe.select("author", "title", "rank", "description") \
.write \
.save("Rankings_Descriptions.parquet")

拼花文件是在。写吧。save()函数被处理。(图片由作者提供)

**# Write & Save File in .json format**
dataframe.select("author", "title") \
.write \
.save("Authors_Titles.json",format="json")

JSON 文件是在。写吧。save()函数被处理。(图片由作者提供)

13.3。停止火花会话**

可以通过运行 stop() 功能来停止 Spark 会话,如下所示。

**# End Spark Session**
sc.stop()

代码和 Jupyter 笔记本都在我的 GitHub 上。

非常感谢您的提问和评论!

参考文献:

  1. http://spark.apache.org/docs/latest/
  2. https://docs.anaconda.com/anaconda/

Pyspark 数据操作教程

原文:https://towardsdatascience.com/pyspark-data-manipulation-tutorial-8c62652f35fa?source=collection_archive---------13-----------------------

入门

绝对火花初学者入门

图片由免费提供-照片来自 Pixabay

这个教程适合你吗?

本教程是为有一些 Python 经验的数据人员编写的,他们绝对是 Spark 初学者。它将帮助您安装 Pyspark 并启动您的第一个脚本。您将了解弹性分布式数据集(rdd)和数据帧,它们是 Pyspark 中的主要数据结构。我们讨论一些基本的概念,因为我认为它们会让你以后不会感到困惑和调试。您将学习数据转换以及从文件或数据库中读取数据。

为什么火花

学习 Spark 的主要原因是,您将编写可以在大型集群中运行并处理大数据的代码。本教程只讨论 Python API py Spark,但是你应该知道 Spark APIs 支持 4 种语言:Java、Scala 和 R 以及 Python。由于 Spark core 是用 Java 和 Scala 编程的,所以那些 API 是最完整和最有原生感觉的。

Pyspark 的优势在于 Python 已经有了许多数据科学的库,您可以将它们插入到管道中。再加上 Python 摇滚的事实!!!能让 Pyspark 真正有生产力。例如,如果你喜欢熊猫,你知道你可以用一个方法调用将 Pyspark 数据帧转换成熊猫数据帧。然后你可以对数据做一些事情,并用 matplotlib 绘制出来。

随着时间的推移,你可能会发现 Pyspark 几乎和 pandas 或 sklearn 一样强大和直观,并在你的大部分工作中使用它。试试 Pyspark 吧,它可能会成为你职业生涯中的下一件大事。

Pyspark 快速启动

有很多关于如何创建 Spark 集群、配置 Pyspark 向它们提交脚本等等的文章。所有这些都是在 Spark 上进行高性能计算所需要的。然而,在大多数公司中,他们会有数据或基础架构工程师来维护集群,而您只需编写和运行脚本。因此,您可能永远不会安装 Spark 集群,但是如果您需要,您可以在问题出现时处理它。OTOH,如果我告诉你,只需一个命令,你就可以在几分钟内开始工作,那会怎么样?

pip install pyspark

这将在您的机器上下载并安装 Pyspark,这样您就可以学习其中的诀窍,然后,当您得到一个集群时,使用它将会相对容易。

为了支持本教程,我创建了这个 GitHub 库:

[## ArmandoRiveroPi/py spark _ 教程

pyspark GitHub 中的数据操作和机器学习介绍是超过 5000 万开发人员的家园,他们致力于…

github.com](https://github.com/ArmandoRiveroPi/pyspark_tutorial)

示例中的大部分代码最好放在tutorial _ part _ 1 _ data _ wrangling . py文件中。

在加快速度之前,先给你点提示。我发现如果我不在主 Python 脚本的开头设置一些环境变量,Pyspark 会抛出错误。

import sys, os
environment = ['PYSPARK_PYTHON', 'PYSPARK_DRIVER_PYTHON']
*for* var *in* environment:
    os.environ[var] = sys.executable

之后,您可以创建 spark 会话

*from* pyspark.sql *import* SparkSession
session = SparkSession.builder.getOrCreate()

相信我,这是你开始工作所需要的。

基本概念

火花建筑

好了,我们可以进入正题了。首先,你必须知道 Spark 是复杂的。它不仅包含大量用于执行许多数据处理任务的代码,而且在执行分布在数百台机器上的代码时,它有望高效无误。在开始的时候,你真的不需要这种复杂性,你需要的是把事情抽象出来,忘记那些具体的细节。不过,重要的是司机和工人之间的区别。驱动程序是 Python (single)流程,您在其中为工人发布订单。工人是听从司机命令的火花过程。您可能会认为这些工人“在云中”(Spark 集群)。Spark 假设大数据将分布在工人中,这些工人有足够的内存和处理能力来处理这些数据。预计驱动程序没有足够的资源来保存这么多的数据。这就是为什么你需要明确地说你什么时候想要移动数据到驱动程序。我们一会儿会谈到这一点,但要注意,在实际应用中,你应该非常小心你带给驱动程序的数据量。

RDDs

弹性分布式数据集是 Spark 中最重要的数据结构之一,是数据帧的基础。您可以将它们视为“分布式”阵列。在许多方面,它们的行为类似于列表,一些细节我们将在下面讨论。

那么,如何创建 RDD 呢?最直接的方法是“并行化”Python 数组。

rdd = session.sparkContext.parallelize([1,2,3])

要开始与您的 RDD 互动,请尝试以下操作:

rdd.take(num=2)

这将为驾驶员带来 RDD 的前两个值。计数方法将返回 RDD 的长度

rdd.count()

如果你想把所有的 RDD 数据作为一个数组发送给驱动程序,你可以使用 collect

rdd.collect()

但是要小心,正如我们之前说过的,在实际应用中,这可能会使驱动程序崩溃,因为 RDD 的大小可能是千兆字节。一般来说,更喜欢使用 take 传递您想要的行数,只有当您确定 RDD 或数据帧不太大时才调用 collect

数据帧

如果你了解熊猫或 R 数据帧,你会非常清楚 Spark 数据帧代表什么。它们用命名列表示表格(矩阵)数据。在内部,它们是通过行对象的 RDD 实现的,这有点类似于名为 tuple 的 Python。数据框架的最大优势在于,它们使您能够将 SQL 思维付诸实践。我们稍后将讨论数据帧操作,但是让我们开始创建一个数据帧,以便您可以使用它。

df = session.createDataFrame(
  [[1,2,3], [4,5,6]], [‘column1’, ‘column2’, ‘column3’]
)

首先是数据矩阵,然后是列名。

可以像 RDD 案一样,尝试的方法;take and collect 将为您提供一个行对象列表。但是对我来说,最友好的显示方式应该是 show :

df.show(n=3)

它将用前 n 行打印数据帧的表格表示。

不变

Python 列表的一个关键区别是 rdd(以及数据帧)是不可变的。在并发应用程序和函数式语言中,经常需要不可变数据。

让我们讨论一下 Python 中不变性的含义。假设你这样做:

a = list(range(10))
a.append(11)

在这里,解释器首先创建一个名称“a ”,它指向一个列表对象,在第二行中,它修改了同一个对象。然而,当你这样做的时候

st = “my string”
st += “ is pretty”

解释器首先创建指向字符串对象的名称“st”,然后创建一个带有“my string is pretty”的全新字符串对象(在内存中的不同位置),并将名称“ST”指向该新对象。发生这种情况是因为字符串是不可变的,你不能就地修改它们。

同样,rdd 和数据帧也不能就地修改,所以当您这样做时

my_rdd.map(*lambda* *x*: x*100)

我的 _rdd 不变。你需要做什么

my_rdd = my_rdd.map(*lambda* *x*: x*100)

以获得指向转换后的 rdd 对象的名称“my_rdd”。

转换和动作

与普通 Python 相比,一个更令人震惊的区别可能会让您在开始时感到困惑。有时您会注意到一个非常繁重的操作会立即发生。但是后来你做了一些小事情(比如打印 RDD 的第一个值),这似乎要花很长时间。

让我试着把这个问题简化很多来解释。在 Spark 中,变换动作是有区别的。当你改变一个数据帧时,那是一个转换,然而,当你实际使用数据时(例如 df.show(1)),那是一个动作。转换是延迟加载的,当你调用它们时它们不会运行。当您通过操作使用它们的结果时,它们就会被执行。然后,所有需要的转换将被一起计划、优化和运行。所以当你看到看起来瞬时的操作时,即使它们很重,那也是因为它们是转换,它们将在以后运行。

数据帧操作

用户定义函数

用户定义的函数允许您使用 Python 代码对数据帧像元进行操作。你创建一个常规的 Python 函数,把它包装在一个 UDF 对象中,并把它传递给 Spark,它会让你的函数在所有的工作器中可用,并安排它的执行来转换数据。

*import* pyspark.sql.functions *as* funcs
*import* pyspark.sql.types *as* typesdef multiply_by_ten(number):
    return number*10.0multiply_udf = funcs.udf(multiply_by_ten, types.DoubleType())transformed_df = df.withColumn(
    'multiplied', multiply_udf('column1')
)
transformed_df.show()

首先你创建一个 Python 函数,它可以是一个对象中的方法,也是一个函数。然后创建一个 UDF 对象。恼人的部分是您需要定义输出类型,这是我们在 Python 中不太习惯的。要真正有效地使用 UDF,你需要学习这些类型,特别是复合映射类型(如字典)和数组类型(如列表)。这样做的好处是,您可以将这个 UDF 传递给 dataframe,告诉它将对哪一列进行操作,这样您就可以在不离开旧 Python 的舒适环境的情况下完成奇妙的事情。

然而,UDF 的一个主要限制是,尽管它们可以接受几列作为输入,但是它们不能整体改变行。如果您想要处理整行,您将需要 RDD 地图。

RDD 制图

这很像使用 UDF,你也传递一个常规的 Python 函数。但是在这种情况下,该函数将接收一个完整的行对象,而不是列值。预计它也将返回一整行。这将赋予您对行的最终权力,但有几个注意事项。首先:Row 对象是不可变,所以您需要创建一个全新的行并返回它。第二:你需要将数据帧转换成 RDD,然后再转换回来。幸运的是,这些问题都不难克服。

让我向您展示一个函数,它将对数转换您的数据帧中的所有列。作为一个不错的尝试,它还将每个列名转换为“log(column_name)”。我发现最简单的方法是用 row.asDict()将行放入字典。这个函数有点 Python 的魔力,比如字典理解和关键字参数打包(双星形)。希望你能全部理解。

*import* pyspark.sql.types *as* types*def* take_log_in_all_columns(row: types.Row):
     old_row = row.asDict()
     new_row = {f'log({column_name})': math.log(value) 
                *for* column_name, value *in* old_row.items()}
     *return* types.Row(**new_row)

这本身不会做任何事情。你需要执行地图。

logarithmic_dataframe = df.rdd.map(take_log_in_all_columns).toDF()

您会注意到这是一个链式方法调用。首先调用 rdd,它将为您提供存储数据帧行的底层 RDD。然后在这个 RDD 上应用 map,在这里传递函数。要关闭,您可以调用 toDF(),它将行的 RDD 转换为数据帧。进一步讨论见这个栈溢出问题

SQL 操作

由于数据帧表示表,自然地,它们被赋予了类似 SQL 的操作。为了让你兴奋,我将只提到其中的几个,但是你可以期待找到几乎同构的功能。调用 select 将返回一个只有一些原始列的数据帧。

df.select('column1', 'column2')

的调用,其中将返回一个数据帧,其中只有列 1 的值为 3 的行。

df.where('column1 = 3')

这个对 join 的调用将返回一个 dataframe,也就是,嗯…,一个 df 和 df1 通过 column1 的连接,就像 SQL 中的内部连接一样。

df.join(df1, [‘column1’], how=’inner’)

如果您需要执行右或左连接,在我们的例子中,df 就像左边的表,而 df1 就是右边的表。外部连接也是可能的。

但是除此之外,在 Spark 中,您可以更直接地执行 SQL。您可以从数据帧中创建时态视图

df.createOrReplaceTempView(“table1”)

然后在视图上执行查询

df2 = session.sql("SELECT column1 AS f1, column2 as f2 from table1")

这些查询将返回一个具有相应列名和值的新数据帧。

数据帧列操作

列抽象支持像算术这样的直接操作,例如,假设您想将列 1 相加,再加上列 2 和列 3 的乘积。那你可以

df3 = df.withColumn(
    'derived_column', df['column1'] + df['column2'] * df['column3']
)

聚合和快速统计

对于这个例子,我们需要从一个 CSV 文件中读取。我从https://archive.ics.uci.edu/ml/datasets/adult下载了成人数据文件

我将文件移动到我的存储库中的数据文件夹,并将其重命名为成人.数据. csv。

ADULT_COLUMN_NAMES = [
     "age",
     "workclass",
     "fnlwgt",
     "education",
     "education_num",
     "marital_status",
     "occupation",
     "relationship",
     "race",
     "sex",
     "capital_gain",
     "capital_loss",
     "hours_per_week",
     "native_country",
     "income"
 ]

读取文件后,我使用这个列表设置列名,因为文件没有标题。

csv_df = session.read.csv(
     'data/adult.data.csv', header=*False*, inferSchema=*True*
 )*for* new_col, old_col *in zip*(ADULT_COLUMN_NAMES, csv_df.columns):
     csv_df = csv_df.withColumnRenamed(old_col, new_col)

之后,您可以尝试下面的一些快速描述性统计

csv_df.describe().show()

若要获取聚合,请将 groupBy 与 agg 方法一起使用。例如,下面将为您提供一个数据框架,其中包含按年龄组划分的平均工作时间和标准偏差。我们也按年龄对数据帧进行排序。

work_hours_df = csv_df.groupBy(
    'age'
).agg(
    funcs.avg('hours_per_week'),
    funcs.stddev_samp('hours_per_week')
).sort('age')

连接到数据库

您很可能将数据保存在关系数据库中,由 MySQL 或 PostgreSQL 之类的 RDBMS 处理。如果是这样的话,不要担心,Spark 有办法与多种数据存储进行交互。我敢打赌,你可以通过谷歌搜索到你可能有的大多数 IO 需求。

要连接到 RDBMS,您需要一个 JDBC 驱动程序,这是一个 Spark 可以用来与数据库对话的 jar 文件。我将向您展示一个 PostgreSQL 示例。

首先你需要下载驱动

在我的 GitHub repo 中,我把 JDBC 驱动程序放在 bin 文件夹中,但是你可以在任何路径中找到它。此外,您应该知道本例中的代码位于 repo 中的另一个文件中。我必须这样做,因为与其他文件不同,这个文件会抛出错误,因为数据库凭证当然是假的。您需要用您的数据库来替换它们以使其运行。

现在,您将通过一个额外的步骤启动 Pyspark:

session = SparkSession.builder.config(
    'spark.jars', 'bin/postgresql-42.2.16.jar'
).config(
    'spark.driver.extraClassPath', 'bin/postgresql-42.2.16.jar'
).getOrCreate()

这将创建一个可识别驱动程序的会话。然后,您可以像这样从数据库中读取(用您的真实配置替换假配置):

url = f"jdbc:postgresql://your_host_ip:5432/your_database"
properties = {'user': 'your_user', 'password': 'your_password'}
*# read from a table into a dataframe* df = session.read.jdbc(
    url=url, table='your_table_name', properties=properties
)

然后,您可以以任何方式创建转换后的数据帧,并将数据写回数据库(可能在不同的表中)。

transformed_df.write.jdbc(
    url=url, table='new_table', mode='append', properties=properties
)

根据文档,写入模式有:

  • append:将此数据帧的内容追加到现有数据中。
  • 覆盖:覆盖现有数据。
  • 忽略:如果数据已经存在,则忽略此操作。
  • error 或“errorifexists”(默认情况):如果数据已经存在,则抛出异常。

结论

我希望你受到鼓励,马上开始学习 Pyspark。我的意思是,这将需要几周的时间来提高效率,这取决于你每天能花多少时间,但之后你就可以用 Pyspark 来执行大量的数据处理了。万一你不能选择你在工作中使用的,至少你可以在你的空闲时间学习它。我的介绍几乎没有触及表面,主要是希望给你一个诱人的咬。比熊猫或者 sklearn 难不了多少。

熟练掌握 Spark,它可以为您打开大数据的大门。

第 2 部分将介绍基本的分类和回归。

进一步阅读

PySpark 食谱作者 Raju Kumar Mishra。Apress,2018。

官方文件

https://spark.apache.org/docs/latest/api/python/

PySpark

原文:https://towardsdatascience.com/pyspark-f037256c5e3?source=collection_archive---------13-----------------------

Python、SQL、Spark 和分布式计算的结合使大数据上的机器学习成为可能

本·韦伯Unsplash 上拍照

Shilpa 对她的第一份工作非常满意,她是一家很有前途的初创公司的数据科学家。她喜欢 SciKit-Learn 图书馆,尤其是熊猫。使用熊猫数据框架进行数据探索很有趣。一个初露头角的数据科学家无法企及类似 SQL 的接口和快速的内存数据处理。

随着创业之旅的成熟,数据量也在增加,it 开始追求用更大的数据库和更强的处理能力来增强他们的 IT 系统。Shilpa 还通过会话池和多线程在她基于 Python 的 ML 程序中增加了并行性,然而,这还远远不够。很快,IT 部门意识到他们无法继续增加更多的磁盘空间和内存,并决定采用分布式计算(也称为大数据)。

希尔帕现在该怎么办?他们是如何让熊猫用分布式计算工作的?

这个故事你看着眼熟吗?

这就是我在本文中要带你经历的:Python 在大数据中的困境。答案是 PySpark

PySpark 是什么?

我可以有把握地假设,您一定听说过 Apache Hadoop:一种用于在计算机集群上分布式处理大型数据集的开源软件。Apache Hadoop 只能以批处理模式处理数据集,缺乏实时流处理。为了填补这个空白,Apache 推出了 Spark (实际上 Spark 是由 UC Berkley amplab 开发的):一个快如闪电的内存实时处理框架。Apache Spark 是用 Scala 编程语言编写的。为了用 Spark 支持 Python,Apache Spark 社区发布了 PySpark

PySpark 被数据科学和机器学习专业人士广泛使用。看了 PySpark 提供的功能,我并不惊讶它已经被网飞、沃尔玛、Trivago、赛诺菲、Runtastic 等组织使用。

下图显示了 Pyspark 的特性。

作者图片

在本文中,我将带您一步一步地在集群计算机上使用 PySpark。

环境准备

要真正实践 PySpark,您需要访问一组计算机。我建议通过下面的链接创建一个免费的计算机集群环境。

[## 数据块-登录

编辑描述

community.cloud.databricks.com](https://community.cloud.databricks.com/)

注册并确认电子邮件后,将显示“欢迎使用 databricks”页面。单击常见任务列表中的新建集群。

作者图片

  1. 在创建集群屏幕中输入详细信息。对于运行时版本,确保 Scala 版本高于 2.5,Python 版本为 3 及以上。

作者图片

2.单击创建集群。群集开始运行需要几分钟时间。

作者图片

3.单击集群名称可查看配置和其他详细信息。现在,不要对它做任何更改。

作者图片

恭喜你!!您的计算机集群已准备就绪。是时候将数据上传到您的分布式计算环境中了。

数据源

我将从下面的链接使用皮马-印第安人-糖尿病数据库。

[## 皮马印第安人糖尿病数据库

基于诊断方法预测糖尿病的发病

www.kaggle.com](https://www.kaggle.com/uciml/pima-indians-diabetes-database)

数据集包含几个医学预测变量(自变量)和一个目标变量(因变量),。独立变量包括患者的怀孕次数、身体质量指数、胰岛素水平、年龄等。

它有一个 diabetes.csv 文件。将其放在您的本地文件夹中,然后上传到 databrics 文件系统(DBFS)。下面是将文件上传到 DBFS 的导航。

  1. 点击左侧菜单中的数据选项
  2. 点击添加数据按钮

作者图片

3.在创建新表格屏幕中,单击浏览。

作者图片

4.它将指向本地磁盘上的目录路径。选择您从上面提到的 Prima-Indian-diabetes 链接下载的 diabetes.csv 文件。

作者图片

5.点击 DBFS。它将显示上传到 databrics 文件系统的文件(diabetes.csv)。

作者图片

恭喜你!!您已成功将文件上传至 databrics 文件系统。现在,您可以通过 pyspark 将它保存在集群中的不同节点上。

笔记本

Datbricks 提供了一个编写 pyspark 代码的在线笔记本。点击新笔记本打开它。

作者图片

数据帧

到目前为止,文件只在 DBFS。现在真正的行动开始了。在本文的这一部分,我将带您浏览 Pyspark 数据框架。

当我们说 dataframe 时,很明显会想到熊猫。Pandas 和 Pyspark dataframe 之间的主要区别在于 Pandas 将完整的数据放在运行它的一台计算机的内存中,Pyspark dataframe 与集群中的多台计算机一起工作(分布式计算),并将数据处理分配给这些计算机的内存。Pyspark 最大的增值是在多台计算机上并行处理一个巨大的数据集。

这是主要原因,Pyspark 在处理分布在不同计算机上的大型数据集时表现良好,Pandas 在处理可以存储在单台计算机上的数据集时表现良好。

但这并不是 Pandas 和 Pyspark 数据框之间的唯一区别。在 Pandas 和 Pyspark 之间,相同的操作在执行方式上有一些不那么细微的差异。

下表显示了其中的一些差异

既然熊猫和 Pyspark 的比较已经不在我们的讨论范围内,让我们来研究 Pyspark 数据框架。

以下代码行将根据 DBFS 的 CSV 数据创建一个 Pyspark 数据框,并显示前几条记录。注意如何

pyspark 数据帧上 show 命令的结果

像 Pandas 一样,很多操作都可以在 Pyspark 数据帧上执行。下面是一些例子。

printSchema: 显示数据帧的结构,即列和数据类型,以及是否接受空值。

Pyspark 数据帧上 printSchema 命令的结果

列:显示列名称。**

*df.columns*

pyspark 数据帧上 columns 命令的结果

计数:显示行数。

*df.count()*

产量:768

len( < dataframe >)。<列> ): 显示数据帧中的列数。

*len(df.columns)*

产出:9

<数据帧>。描述(<列名>)。show(): 描述提到的列。

以下代码描述了葡萄糖柱。

输出:显示葡萄糖值的统计值,如计数、平均值、标准差(stddev)、最小值(min)和最大值(max)。

pyspark 描述命令的结果

选择:显示从数据框中选择的列。

以下代码将仅从数据框中选择葡萄糖和胰岛素值。

pyspark 数据帧上 select 命令的结果

like: 它的作用类似于 SQL 中的 like 过滤器。“%”可以用作通配符来筛选结果。但是,与基于 like condition 中提到的条件过滤结果的 SQL 不同,这里显示的是完整的结果,表明它是否满足 like 条件。

下面的代码将显示数据帧中的怀孕和葡萄糖值,并指示单个行是否包含从 33 开始的身体质量指数值。

注意:通常,like 条件用于分类变量。然而,我使用的数据源没有任何分类变量,因此使用了这个例子。

数据帧上相似条件的结果

过滤:根据上述条件过滤数据。

以下代码过滤血压大于 100 的数据帧。

pyspark 数据帧上过滤器命令的结果

该筛选器可用于添加多个带有 and (&)或(|)条件的条件。

下面的代码片段过滤血压和胰岛素值大于 100 的数据帧。

pyspark 数据帧上过滤器命令的结果

orderBy: 对输出进行排序。

以下代码过滤血压和胰岛素值大于 100 的数据帧,并基于葡萄糖值输出。

pyspark 数据帧上过滤器命令的结果

Pyspark SQL

Hive 和 Spark SQL 可以用来查询 Hadoop 和 Spark 集群中存储的结构化数据。大多数情况下,Spark SQL 至少比 Hive 快 10 倍。当 Spark SQL 在另一个编程接口中运行时,它将输出作为数据帧返回。

在本文的这一部分,我将带您了解 pySpark 内置的 SQL 函数 pyspark.sql.function,它适用于 dataframe。

以下是一些主要功能:

when and other:评估特定列的值,并将值更改为更有意义的值。

下面的代码显示了如何评估血压水平并将其分类为高、低和正常。

当和否则命令时 pyspak 的结果

聚合函数:聚合函数,如平均值(avg)、最大值(max)、最小值(min)、总计(sum)、计数。

以下代码将显示糖尿病和非糖尿病患者的最大和最小葡萄糖值和计数。

pyspark SQL 聚合函数的结果

参考 pySpark SQL page 获得内置函数的完整列表。

以编程方式运行 SQL 查询

如果你像我一样有数据库经验并喜欢 SQL 查询,你会喜欢 PySpark 的这个特性。

如果我告诉你,你可以在 pySpark 中直接运行任何 SQL 查询,结果将以 dataframe 的形式出现,那会怎么样?

这是一个两步走的过程。

  1. 使用数据帧中的完整数据创建临时或全局视图。
  2. 在使用 Oracle、MySQL 等关系数据库时,可以像使用数据库视图一样在该视图上运行 SQL 查询。

pyspark SQL 程序的结果

好吧,我同意这太简单了。让我们用聚合函数和 group by、order by 编写一个 SQL。

下面的 SQL 将打印糖尿病数据库中每个年龄组的平均血糖和血压。结果将按平均血压排序。它将显示 5 条记录。

pyspark SQL 编程的结果

createOrReplaceTempiew 将创建一个临时视图,只要会话处于活动状态,该视图就会显示值。要创建跨会话的视图(类似于数据库实体化视图),请使用 createGlobalTempView。

在 pySpark 中,通过 SQL 编程可以做很多事情。在Spark 文档中获取可能性列表。

用户定义的函数(UDF)

上一节中的 SQL 包含预定义的 SQL 函数,如 format_number、avg。在实际项目中,数据科学家经常会遇到这样的情况,他们想要实现一些没有内置函数的东西。那是他们使用 UDF 的时候。

下面是一个 Python 函数的片段,它根据一个人的身体质量指数来指示这个人是体重不足、超重、正常体重还是肥胖。

为了在 Spark SQL 中使用这个 Python 函数,将其注册为 UDF。

现在,UDF BMIInd 可以在 Spark SQL 中使用,如下所示。

用 UDF 输出触发 SQL

pySpak ML

除非我们触及 Spark 的机器学习库 MLlib,否则这篇文章是不完整的。

下面是来自 Spark 网页

MLlib 是 Spark 的机器学习(ML)库。它的目标是让实用的机器学习变得可扩展和简单。在高层次上,它提供了一些工具,例如:

ML 算法:分类、回归、聚类、协同过滤等常用学习算法

特征化:特征提取、变换、降维、选择

管道:用于构建、评估和调整 ML 管道的工具

持久性:保存和加载算法、模型和管道

实用程序:线性代数、统计学、数据处理等。

我们将对糖尿病数据使用 Spark MLlib 来创建一个预测模型,该模型可以根据患者的身体质量指数、年龄、血糖水平和血压来预测他/她是否是糖尿病患者。

  1. Vectorassembler:第一步是使用 pyspark.ml.feature 中的 VectorAssemble 方法将所有特征组合成一个向量
  2. 然后将数据分成训练和测试数据集。

训练和测试中特征组合和数据分割的结果

3.为此,我将使用集成方法梯度引导分类器。

梯度增强分类器结果

不错,梯度推进分类器返回 75%的准确性。

浏览Spark ml lib页面,获取 Spark 提供的机器学习模型列表。

结论

这是一篇大文章。我认为 pySpark 值得拥有这个,因为它是分布式计算上数据科学和机器学习可用的最强大的工具。我和我的学生已经成功地使用了本文档中解释的每一个特性和命令,它们对我们来说工作得很好。但是,如果您遇到任何问题,请让我知道。

我期待你的反馈。

参考:

https://www . udemy . com/course/Apache-spark-for-data-engineers/?referral code = ca 92888 da 98 AEA 3315 AC

Pyspark —用熊猫 UDF 和 fb-prophet 进行预报

原文:https://towardsdatascience.com/pyspark-forecasting-with-pandas-udf-and-fb-prophet-e9d70f86d802?source=collection_archive---------8-----------------------

预测几个时间序列一次与先知和熊猫 UDF 没有循环。

https://upload . wikimedia . org/Wikipedia/commons/f/F3/Apache _ Spark _ logo . SVG

在开始任何与熊猫-udf 相关的工作之前,的先决条件

  • 火花≥ 2.4
  • pyarrow ≤ 0.14.1(高于此版本有一些问题)

然后我们需要为 pyarrow 设置一个环境变量为 1。(参见进口代码)

sudo pip3 install pyarrow=0.14.1

然后,我们可以继续库导入。

from pyspark.sql import SparkSession
from pyspark.sql.types import *
from pyspark.sql.functions import pandas_udf, PandasUDFType, sum, max, col, concat, lit
import sys
import os
# setup to work around with pandas udf
# see answers here [https://stackoverflow.com/questions/58458415/pandas-scalar-udf-failing-illegalargumentexception](https://stackoverflow.com/questions/58458415/pandas-scalar-udf-failing-illegalargumentexception)
os.environ["ARROW_PRE_0_15_IPC_FORMAT"] = "1"from fbprophet import Prophet
import pandas as pd
import numpy as np

如果一切顺利,我们可以通过“sc”调用 spark 上下文,并看到:

现在我们可以谈论有趣的部分,预测!

在本教程中,我们将使用 pyspark 的新功能:pandas-udf,就像以前的 pyspark UDF 一样。pandas-udf 是一个用户自定义函数,目标是在 spark 数据帧上应用我们最喜欢的库,如 numpy、pandas、sklearn 等,而不改变语法返回 spark 数据帧

特别是,我们将探索熊猫 UDF 的 GROUPED_MAP 属性,这些属性允许我们将 scikit-learn、statsmodels 和更多应用于我们的 Spark 数据帧。我们将使用熊猫 UDF 对我们数据集中的每个商品|商店应用脸书人工智能的流行 Prophet 分段回归,没有任何循环,也没有任何结果的串联,因为 Prophet 不会同时处理多个时间序列。

Pandas_udf 可以作为装饰器传递给基本函数,该装饰器用两个参数包装整个函数:预期的输出模式和 GROUPED_MAP 属性。

# define an output schema
schema = StructType([
        StructField("store", StringType(), True),
        StructField("item", StringType(), True),
        StructField("ds", DateType(), True),
        StructField("yhat", DoubleType(), True)
    ])

定义了装饰器之后,剩下的就非常简单和直观了;我们定义我们的函数来调整和预测我们的数据,就像我们对单个序列所做的那样。

我的功能非常简单,我接受 Spark 数据帧作为输入,该数据帧是训练集和测试集(目标初始化为 null)连接的结果,是我对任何项目的销售历史(格式是 Spark 数据帧)。该函数将被应用,就好像只有一个产品-商店对,并且作为一个熊猫数据帧,所以没有语法变化,所以我们定义训练和预测日期,并根据算法要求的约定重命名日期和销售列,然后我调用我的函数创建一个国家事件数据帧(格式:熊猫数据帧)。然后,我传递算法中的所有内容,进行预测,并附上我的预测数据帧,该数据帧仅包含与我的初始测试集相关的日期和预测,以便检索产品和商店 id。整个函数被包装在 pandas-udf 和..就是这样!

  • 名词(noun 的缩写)《预言家日报》上的假日只是笔记本上的一个“硬编码”假日熊猫数据框架。

我们可以训练我们的模型。

如果一切顺利,控制台应该记录每个用一些指标训练的时间序列。

然后,对每个序列进行预测,我们把它们放在一个单一的火花数据框架中,没有串联。

魔法起作用了!我们在一瞬间预测了大约 50 个时间序列,没有复杂,没有 for 循环,也没有检索结果。

最后

在这个简短的教程中,我们将看到如何使用 pandas udf 训练几个模型,以分布式方式一次预测几个时间序列。与允许我们跳过循环和连接部分的事实相比,pandas UDF 的主要优势是我们通过分布式框架获得的计算时间,每个时间序列都是在不同工作者的不同分区上形成的,整体在最后收集,这是与循环相比的真正优势,循环需要一些时间来运行数百万个包含实际数据的元素。

笔记本在我的 Github 这里有:https://github.com/AlexWarembourg/Medium数据在 Kaggle 上有(链接在笔记本和主物的评论下。 感谢!

数据科学家 Pytest

原文:https://towardsdatascience.com/pytest-for-data-scientists-2990319e55e6?source=collection_archive---------6-----------------------

适用于您的数据科学项目的 Pytest 综合指南

拍摄的照片来自 Pexels

动机

应用不同的 python 代码来处理笔记本中的数据是很有趣的,但是为了使代码可复制,您需要将它们放入函数和类中。当你把你的代码放到脚本中时,代码可能会因为一些函数而中断。即使你的代码没有崩溃,你怎么知道你的函数是否会像你期望的那样工作?

例如,我们用 TextBlob 创建一个函数来提取文本的情感,这是一个用于处理文本数据的 Python 库。我们希望确保它像我们预期的那样工作:如果测试结果是肯定的,函数将返回一个大于 0 的值,如果文本是否定的,函数将返回一个小于 0 的值。

要确定函数是否每次都会返回正确的值,最好的方法是将函数应用于不同的示例,看看它是否会产生我们想要的结果。这就是测试变得重要的时候。

一般来说,您应该对您的数据科学项目使用测试,因为它允许您:

  • 确保代码按预期运行
  • 检测边缘情况
  • 放心地用改进的代码替换现有的代码,而不用担心破坏整个管道
  • 你的队友可以通过查看你的测试来理解你的功能

有许多 Python 工具可用于测试,但最简单的工具是 Pytest。

Pytest 入门

Pytest 是一个框架,它使得用 Python 写小测试变得很容易。我喜欢 pytest,因为它帮助我用最少的代码编写测试。如果您不熟悉测试,pytest 是一个很好的入门工具。

要安装 pytest,请运行

pip install -U pytest

为了测试上面显示的函数,我们可以简单地创建一个以test_开头的函数,后面是我们想要测试的函数的名称,即extract_sentiment

在测试函数中,我们将函数extract_sentiment应用于一个示例文本:“我认为今天将是伟大的一天”。我们使用assert sentiment > 0来确保情绪是积极的。

就是这样!现在我们准备运行测试。

如果我们脚本的名字是sentiment.py,我们可以运行

pytest sentiment.py

Pytest 将遍历我们的脚本,并运行以test开头的函数。上面测试的输出将如下所示

========================================= test session starts ==========================================
platform linux -- Python 3.8.3, pytest-5.4.2, py-1.8.1, pluggy-0.13.1collected 1 itemprocess.py .                                                                                     [100%]========================================== 1 passed in 0.68s ===========================================

相当酷!我们不需要指定测试哪个函数。只要函数名以test,开头,pytest 就会检测并执行那个函数!为了运行 pytest,我们甚至不需要导入 pytest

如果测试失败,pytest 会产生什么输出?

>>> pytest sentiment.py========================================= test session starts ==========================================
platform linux -- Python 3.8.3, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
collected 1 itemprocess.py F                                                                                     [100%]=============================================== FAILURES ===============================================
________________________________________ test_extract_sentiment ________________________________________def test_extract_sentiment():

        text = "I think today will be a great day"

        sentiment = extract_sentiment(text)

>       assert sentiment < 0
E       assert 0.8 < 0process.py:17: AssertionError
======================================= short test summary info ========================================
FAILED process.py::test_extract_sentiment - assert 0.8 < 0
========================================== 1 failed in 0.84s ===========================================

从输出可以看出,测试失败是因为函数的情绪是 0.8,而且不小于 0!我们不仅能够知道我们的功能是否像预期的那样工作,还能知道它为什么不工作。从这种洞察力中,我们知道在哪里修复我们的函数,使其按照我们想要的那样工作。

同一功能的多次测试

我们可能想用其他例子来测试我们的功能。新测试函数的名称是什么?

如果我们想在带有负面情绪的文本上测试我们的函数,第二个函数的名字可以是类似于test_extract_sentiment_2test_extract_sentiment_negative的名字。任何函数名只要以test开头都可以

>>> pytest sentiment.py========================================= test session starts ==========================================
platform linux -- Python 3.8.3, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
collected 2 itemsprocess.py .F                                                                                    [100%]=============================================== FAILURES ===============================================
___________________________________ test_extract_sentiment_negative ____________________________________def test_extract_sentiment_negative():

        text = "I do not think this will turn out well"

        sentiment = extract_sentiment(text)

>       assert sentiment < 0
E       assert 0.0 < 0process.py:25: AssertionError
======================================= short test summary info ========================================
FAILED process.py::test_extract_sentiment_negative - assert 0.0 < 0
===================================== 1 failed, 1 passed in 0.80s ======================================

从输出中,我们知道一个测试通过了,一个测试失败了,以及测试失败的原因。我们期望句子‘我不认为这会变好’是否定的,但是结果是 0。

这有助于我们理解这个函数可能不是 100%准确的;因此,在使用该函数提取文本情感时,我们应该谨慎。

参数化:组合测试

上面的两个测试函数用于测试相同的函数。有没有什么方法可以把两个例子合并成一个测试函数?这就是参数化派上用场的时候

用样本列表进行参数化

使用pytest.mark.parametrize(),我们可以通过在参数中提供一个例子列表来执行不同例子的测试。

在上面的代码中,我们将变量sample分配给一个样本列表,然后将该变量添加到测试函数的参数中。现在每个例子将被一次测试一次。

========================== test session starts ===========================
platform linux -- Python 3.8.3, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
collected 2 itemssentiment.py .F                                                    [100%]================================ FAILURES ================================
_____ test_extract_sentiment[I do not think this will turn out well] _____sample = 'I do not think this will turn out well'[@pytest](http://twitter.com/pytest).mark.parametrize('sample', testdata)
    def test_extract_sentiment(sample):

        sentiment = extract_sentiment(sample)

>       assert sentiment > 0
E       assert 0.0 > 0sentiment.py:19: AssertionError
======================== short test summary info =========================
FAILED sentiment.py::test_extract_sentiment[I do not think this will turn out well]
====================== 1 failed, 1 passed in 0.80s ===================

使用parametrize(),我们能够在一次函数中测试 2 个不同的例子!

用一系列例子和预期输出来参数化

如果我们期望不同的例子不同的输出会怎样?Pytest 还允许我们向测试函数的参数中添加示例和预期输出!

例如,下面的函数检查文本是否包含特定的单词。

如果文本包含单词,它将返回True

如果单词是“duck ”,文本是“在这个文本中有一只鸭子”,我们期望这个句子返回True.

如果单词是“duck ”,文本是“There nothing here ”,我们希望句子返回False.

我们将使用parametrize(),但是使用元组列表。

我们函数的参数结构是parametrize(‘sample, expected_out’, testdata)testdata=[(<sample1>, <output1>), (<sample2>, <output2>)

>>> pytest process.py========================================= test session starts ==========================================
platform linux -- Python 3.8.3, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
plugins: hydra-core-1.0.0, Faker-4.1.1
collected 2 itemsprocess.py ..                                                                                    [100%]========================================== 2 passed in 0.04s ===========================================

厉害!我们两个测试都通过了!

一次测试一个功能

当脚本中测试函数的数量增加时,您可能希望一次测试一个函数,而不是多个函数。使用pytest file.py::function_name可以轻松做到这一点

例如,如果您只想运行test_text_contain_word,运行

pytest process.py::test_text_contain_word

pytest 将只执行我们指定的一个测试!

夹具:使用相同的数据测试不同的功能

如果我们想用相同的数据测试不同的功能呢?例如,我们想测试句子“今天我找到了一只鸭子,我很高兴”是否包含单词“鸭子”它的情绪是积极的。我们想对相同的数据应用两个函数:“今天我发现了一只鸭子,我很高兴”。这时候fixture就派上用场了。

pytest夹具是向不同测试功能提供数据的一种方式

在上面的例子中,我们用函数example_data.上面的装饰符@pytest.fixture创建了一个示例数据,这将把example_data变成一个值为“今天我找到了一只鸭子,我很高兴”的变量

现在,我们可以使用example_data作为任何测试的参数!

构建您的项目

最后但同样重要的是,当我们的代码变大时,我们可能希望将数据科学函数和测试函数放在两个不同的文件夹中。这将使我们更容易找到每个功能的位置。

test_<name>.py<name>_test.py来命名我们的测试函数。Pytest 将搜索名称以“test”结尾或开头的文件,并在该文件中执行名称以“test”开头的函数。多方便啊!

有不同的方法来组织你的文件。您可以将我们的数据科学文件和测试文件组织在同一个目录中,或者组织在两个不同的目录中,一个用于源代码,一个用于测试

方法 1:

test_structure_example/
├── process.py
└── test_process.py

方法二:

test_structure_example/
├── src
│   └── process.py
└── tests
    └── test_process.py

由于您很可能有多个数据科学函数文件和多个测试函数文件,您可能希望将它们放在不同的目录中,就像方法 2 一样。

这是两个文件的样子

只需添加sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))即可从父目录导入函数。

在根目录(test_structure_example/下,运行pytest tests/test_process.py或者运行test_structure_example/tests目录下的pytest test_process.py

========================== test session starts ===========================
platform linux -- Python 3.8.3, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
collected 1 itemtests/test_process.py .                                            [100%]=========================== 1 passed in 0.69s ============================

相当酷!

结论

恭喜你!您刚刚了解了 pytest。我希望这篇文章能够让您很好地了解为什么测试很重要,以及如何使用 pytest 将测试融入到您的数据科学项目中。通过测试,您不仅能够知道您的功能是否如预期的那样工作,而且能够自信地用不同的工具或不同的代码结构切换现有的代码。

本文的源代码可以在这里找到:

[## khuyentran 1401/数据科学

有用的数据科学主题以及代码和文章的集合— khuyentran1401/Data-science

github.com](https://github.com/khuyentran1401/Data-science/tree/master/data_science_tools/pytest)

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedInTwitter 上联系我。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

[## 使用 Python 和情感分析探索和可视化您的 LinkedIn 网络

希望优化您的 LinkedIn 个人资料?为什么不让数据为你服务呢?

towardsdatascience.com](/sentiment-analysis-of-linkedin-messages-3bb152307f84) [## 我收集了超过 1k 的顶级机器学习 Github 配置文件,这就是我的发现

从 Github 上的顶级机器学习档案中获得见解

towardsdatascience.com](/i-scraped-more-than-1k-top-machine-learning-github-profiles-and-this-is-what-i-found-1ab4fb0c0474) [## 使用这四种 Numpy 方法充分利用您的阵列

如何垂直拆分 Numpy 数组或查找特定范围内的元素。

medium.com](https://medium.com/swlh/get-the-most-out-of-your-array-with-these-four-numpy-methods-2fc4a6b04736) [## 如何有效地微调你的机器学习模型

发现为您的 ML 模型寻找最佳参数非常耗时?用这三招

towardsdatascience.com](/how-to-fine-tune-your-machine-learning-models-with-ease-8ca62d1217b1) [## 如何创建可重用的命令行

你能把你的多个有用的命令行打包成一个文件以便快速执行吗?

towardsdatascience.com](/how-to-create-reusable-command-line-f9a2bb356bc9)

爱上❤️的 Pytest 插件

原文:https://towardsdatascience.com/pytest-plugins-to-love-️-9c71635fbe22?source=collection_archive---------6-----------------------

我的前 5 名和 700+插件中的 50 名,以获得更好的输出和更快的执行速度

插件可以修改和扩展 pylint 的很多方面,包括输出是如何完成的。这个用 pytest-sugar 运行 pytest 的截图是由 Martin Thoma 拍摄的。

Pytest 是可扩展的,有很多插件。你不需要使用它们中的任何一个,但你可能会发现一些非常有用。我喜欢这一点,因为你有一个简单的时间开始单元测试,当你更有经验的时候,仍然会发现令人惊奇的东西🤩

在这篇文章中,我将向你展示我使用的插件的例子和我在写这篇文章时发现的插件。你可能想先介绍单元测试的基础知识,或者刷新测试细节,比如 fixtures。

如何添加插件?

本文介绍的所有插件都可以通过pip安装。他们中的大多数已经开始活动了。例如,当您通过

pip install pytest-sugar

你只要执行pytest插件就会自动工作。其他的需要更直接的使用。例如,安装完pytest-timeout后,您需要指定想要使用的超时参数:

pytest --timeout=1

别担心,我稍后会解释这两个插件🙂

存在多少 Pytest 插件?

在 pypi.org 上搜索 trove 分类器Framework :: Pytest,我找到了 668 个包。一个惊人的 1053 个包的名字中有“pytest”。461 包都有,名字和 trove 分类器。

为了这篇文章,我查阅了 700 多个 pytest 插件。我跳过了那些认为自己处于计划阶段、前 alpha 阶段或 alpha 阶段的插件。我也跳过了在自述文件中看到TODO的包,或者在 GitHub 上少于 10 颗星的包。

我发现的包使 pytest 闪耀✨,提高速度🏎,是专门针对特定的包,或者只是在他们的行为独特的❄️

最后但同样重要的是,有些插件我不确定它们是不是很棒,或者是不是个坏主意。让我们直接跳进去自己看一看吧!

旁注:可能你还记得我的错别字蹲坑的旁注?在写这篇文章的时候,我在 PyPI 上发现了一个可以修复的问题,希望可以提高社区的安全性🎉

闪亮的那些

照片由杰瑞米·托马斯Unsplash 上拍摄

pytest 的默认输出已经很好了,但是一些插件让它变得很神奇。[pytest-sugar](https://github.com/Teemu/pytest-sugar)是那些 plugins❤中的一个

Pytest sugar 将圆点变为对勾,百分比变为条形。图片由马丁·托马斯提供。

如果这些圆点或勾号对你来说太体面了,试试[pytest-emoji](https://pypi.org/project/pytest-emoji/)[pytest-emoji-out](https://pypi.org/project/pytest-emoji-output/)😃

汇总输出现在看起来不错,但是期望值和实际值之间的差异还可以改进。[pytest-icdiff](https://pypi.org/project/pytest-icdiff/)是我在研究这篇文章时发现的一个插件——它是🥰❤的一见钟情

图片作者:马丁·托马斯

非常相似的是[pytest-clarity](https://pypi.org/project/pytest-clarity/)——注意,pytest-clarity 仅在您执行pytest -vv时激活:

马丁·托马斯截图

一旦您对终端输出感到满意,您可能会考虑在浏览器中获取报告。一旦你不得不看很多东西,想要滚动和搜索,这可能会有所帮助。那么[pytest-html](https://pypi.org/project/pytest-html/)就是你的朋友。它会生成这样的报告:

马丁·托马斯截图

既然我们对输出结果感到满意,我们想让它快如闪电!

我们需要速度!

照片由丘特尔斯纳普Unsplash 上拍摄

插件可以加快速度。例如,您可以使用[pytest-instafail](https://pypi.org/project/pytest-instafail/)让 pytest 立即失败,而不是执行所有剩余的测试。对于那些可能需要很长时间甚至在出错时导致无限循环的测试,我使用[pytest-timeout](https://pypi.org/project/pytest-timeout/) ❤.当您应用突变测试时,这尤其有用。

我们也想通过使用[pytest-xdist](https://pypi.org/project/pytest-xdist/)来正确使用我们的机器。安装它,执行pytest -n auto,你的测试就可以并行运行了![pytest-parallel](https://pypi.org/project/pytest-parallel/)或许也值得一试。

最极端的加速是不执行你不需要的东西。[pytest-picked](https://github.com/anapaulagomes/pytest-picked)执行与未分级文件相关的测试,这些文件可能远少于您的完整测试套件。

换个方向,我们想确保算法有一些速度行为。通过[pytest-benchmark](https://pypi.org/project/pytest-benchmark/),我们可以使用benchmark fixture 来注释我们想要进行基准测试的测试部分:

def test_argmax(benchmark):
    assert benchmark(mpu.math.argmax, [1, 2, 3]) == 2

运行pytest也会给出这个输出,在这里你可以看到我已经添加了基准的三个函数。其中两个测试一个因式分解函数。因式分解 3072 比因式分解 1024 花费的时间更长,这并不奇怪,但是数字增长的速度之快总是让我吃惊。3 个例子的 argmax 非常快,但是因式分解需要更多的计算:

最小、平均和最大执行时间,以及标准偏差和四分位数范围,让您对执行时间分布有所了解。图片作者:马丁·托马斯

独一无二的

照片由 Darius CotoiUnsplash 上拍摄

有些插件是独特的,不适合任何其他类别:

  • [pytest-cov](https://pypi.org/project/pytest-cov):获取测试覆盖报告😍❤:我喜欢两个都生成,一个 HTML 报告和一个到终端的输出。在某些情况下,XML 报告也很有帮助。
  • [pytest-socket](https://pypi.org/project/pytest-socket/):确保不要查询任何非本地的东西。非常好的❤
  • [pytest-randomly](https://github.com/pytest-dev/pytest-randomly)[pytest-rng](https://pypi.org/project/pytest-rng/):如果你使用random.random,那么结果取决于随机种子。这个插件改变种子。
  • [pytest-random-order](https://pypi.org/project/pytest-random-order/):以随机的顺序执行测试,以确保您看到测试何时以不同的状态离开系统。
  • [pytest-lazy-fixtures](https://pypi.org/project/pytest-lazy-fixture/):使用@pytest.mark.parametrize中的夹具。
  • [pytest-freezegun](https://pypi.org/project/pytest-freezegun/):冻结时间!这也是我在我的补丁文章中提到过的。
  • [pytest-leaks](https://pypi.org/project/pytest-leaks/):发现资源泄露。这需要一个调试版的 Python!
  • [pytest-flake8](https://github.com/tholo/pytest-flake8):通过 pytest 运行 flake8。我这样做了很长时间,但是当我了解到如何更有效地使用持续集成管道时,我就停止了。还是可以直接执行 flake8。
  • [pytest-mypy](https://pypi.org/project/pytest-mypy/)pytest-mccabe:与 flake8 相同。对了,类型标注很牛逼!我喜欢在 CI 管道的 linter 步骤中使用那些静态代码分析工具。
  • [pytest-deadfixtures](https://pypi.org/project/pytest-deadfixtures/):指出哪些灯具没有被使用或复制。

17 个专用插件—如果您需要,您会知道的

下面的插件只有在你使用为其编写的应用程序时才会引起你的兴趣。他们通常提供固定装置/模型。

  • [pytest-cookie](https://pypi.org/project/pytest-cookies/):支持 cookiecutter 模板的测试。
  • [pytest-plt](https://pypi.org/project/pytest-plt/)[pytest-mpl](https://pypi.org/project/pytest-mpl/):为 matplotlib 提供夹具。
  • [pytest-responses](https://pypi.org/project/pytest-responses/):为[requests](https://requests.readthedocs.io/en/master/)提供夹具。
  • [pytest-asyncio](https://pypi.org/project/pytest-asyncio/):在开发异步函数时使用它。
  • [pytest-qt](https://pypi.org/project/pytest-qt/):通过 Qt / PySide / PySide2 进行 GUI 开发。

Web 开发

  • [pytest-djangoapp](https://pypi.org/project/pytest-djangoapp/) / [pytest-djangoqueries](https://pypi.org/project/pytest-django-queries/):为 Django 应用程序开发人员提供工具,以方便测试创作,包括设置覆盖、模板标签测试和用户创建。
  • [pytest-flask](https://pypi.org/project/pytest-flask/)[pytest-flask-sqlalchemy](https://pypi.org/project/pytest-flask-sqlalchemy/):为使用 Flask-SQLAlchemy 在事务中运行测试提供 fixtures。
  • [pytest-seleniumbase](https://pypi.org/project/pytest-seleniumbase/) / [pytest-sbase](https://pypi.org/project/pytest-sbase/) / [pytest-selenium](https://pypi.org/project/pytest-selenium/)

AWS 的模拟和固定装置

  • [moto](https://pypi.org/project/moto/):boto 3 的模拟——AWS 的东西。我不太喜欢这个,但是当你想测试使用 S3 的代码时,它肯定是你能做的最好的了。
  • [pytest-aws](https://pypi.org/project/pytest-aws/):测试 AWS 资源配置
  • [pytest-localstack](https://pypi.org/project/pytest-localstack/):通过 Localstack Docker 容器创建 AWS 集成测试

我不确定的插件

布鲁斯·马尔斯在 Unsplash 上拍摄的照片

当我第一次读到以下插件时,它们听起来很酷,但由于各种原因,我不确定它们是否真的是个好主意:

  • [pytest-check](https://github.com/okken/pytest-check):允许每次测试多次失败。起初,我喜欢这个想法。然后我意识到这可能会导致更糟糕的测试,因为测试开始做很多事情。另一方面,您可能想要测试一次“工作流”——所以不是单元测试,而是集成测试或者甚至是端到端测试。但是你也需要中间结果。
  • [pytest-docker-tools](https://pypi.org/project/pytest_docker_tools/)[pytest-docker-compose](https://github.com/pytest-docker-compose/pytest-docker-compose):我只是构建 Docker 映像并执行其中的内容。
  • [pytest-mock](https://pypi.org/project/pytest-mock/):提供了一个 mocker fixture,它是模拟包提供的补丁 API 的一个瘦包装器。它通过使 mock 成为一个固定设备来减少样板代码。
  • [pytest-spec](https://pypi.org/project/pytest-spec/)[pytest-pspec](https://pypi.org/project/pytest-pspec/)[pytest-testdox](https://pypi.org/project/pytest-testdox/)修改 pytest 输出。它们显示了测试的内容。测试应该以这样一种方式编写,即它们代表软件规范——所以测试是针对规范的一部分。
  • 它应该通过 VCR.py 记录网络交互,但我没有让它工作。
  • [pytest-dependency](https://github.com/RKrahl/pytest-dependency)允许您指定哪些测试需要成功,其他人才能成功。单元测试应该是独立的,依赖的代码应该被嘲笑…也许吧。我对此没有把握。

TL;速度三角形定位法(dead reckoning)

pytest是用 Python 运行测试的首选工具。虽然它有合理的默认值,但它广泛的插件系统允许你定制它,使它变得更好。

我喜欢[pytest-sugar](https://github.com/Teemu/pytest-sugar)[pytest-icdiff](https://pypi.org/project/pytest-icdiff/),因为它们使 pytest 的输出更容易阅读。[pytest-cov](https://pypi.org/project/pytest-cov/)生成线覆盖和分支覆盖,因此是发现需要更好测试的点的有价值的工具。下一步是运行测试。你真的不想不小心撞到生产环境。这就是[pytest-socket](https://pypi.org/project/pytest-socket/)发挥作用的地方。它只是屏蔽一切并向你报告。另一类问题是长期运行的测试,这些测试可能会陷入无限循环。pytest-timeout在指定的时间后终止那些测试。

其他插件那么多;许多人为特定的包添加了固定装置,这些包通常很难测试。您现在应该对 pytest 插件增加的许多可能性有了很好的了解——使用它们吧!

下一步是什么?

在这个系列中,我们已经有了:

如果您对使用 Python 测试的其他主题感兴趣,请告诉我。

Python+ 101:最有用的数据结构和算法

原文:https://towardsdatascience.com/python-101-most-useful-data-structures-and-algorithms-895d6bf2f1b3?source=collection_archive---------30-----------------------

一种使用鲜为人知的 python 特性的新方法

照片由内森·安德森Unsplash 上拍摄

Python 无疑是本世纪使用最广泛的编程语言之一,它在易用性和直观性方面为编程提供了一个全新的视角。除了拥有丰富的最常见的数据结构之外,它还提供了许多标准库,可以极大地减轻为不同领域的各种问题从头开始开发代码的负担。在本教程中,我将关注一些最常见的问题,或者我应该说,遭遇,以及使用标准 python 模块的数据结构和算法的解决方案。因此,让我们深入“Python+”的世界,这是关于在我们所了解的 Python 中加入更多的东西。

1。列表、元组、集合或 numpy 数组中的 n 个最大或最小元素

在许多场景中,我们需要提取集合中最大或最小的元素。python 的 heapq 模块的 nlargestnsmallest 方法可以用来获取一个列表中 N 个最大和最小的元素。nlargest(n,iterable)nsmallest(n,iterable)其中n是需要获取的最大或最小元素的个数,iterable可以是列表、元组、集合或 numpy 数组,使用如下。

图一。列表、元组和数组中最小和最大的元素

如果在一个集合中需要不止一个最大或最小的元素,这些方法会更快更有效。如果需要单个最大或最小的元素,python 中的minmax函数更有效。注意, *nlargest* *nsmallest* 函数总是返回一个列表,与集合的类型无关。

2。集合中最常见的元素和元素出现的次数

有时候,我们需要在一个集合中找到 N 个最常见的元素。集合库的Counter类是一种简单的方法,通过它的most_common方法提取列表或 numpy 数组中最常见的元素以及它们出现的次数。

图二。数组中最常见的元素

most_common方法将我们想要的最常见元素的数量作为参数,并返回一个元组列表,其第一个元素表示数组中最常见的元素,第二个元素是该元素的出现次数,按照出现次数递减排序。在图 2 所示的代码片段中,myarray中的1出现了 6 次,0出现了 3 次。

此外,特定元素的出现次数可以通过索引获得。例如,元素5myarray中出现 3 次,只需使用myarray[5].即可找到

Counter是一个非常有用的类(更准确地说是子类),用于统计可散列的项目。数组或列表的元素存储为字典键,它们的计数作为相应的字典值。

3。表格分类:将数组一分为二

有时,需要根据一些断点对数据进行分类/归类。平分模块的bisect方法是一个很好的工具,可以很容易地实现这种分类。考虑一下 100 分制考试中 10 个学生的分数。我们需要根据他们的分数是低于 25 分、在 25 分和 50 分之间、在 50 分和 75 分之间还是在 75 分以上,将他们分为 4 类。这可以按如下方式完成

图 3。数组二分法

根据breakpoints.将数组scores的每个元素放入各自在classes中的类中

4。排列和组合

在我对万亿字节数据的研究中,我经常在文件操作中遇到排列和组合的需要。itertools 库提供了一些不错的方法来计算数据的排列和组合(有和没有替换)。permutations(iterable, r)提供了iterabler长度排列的个数,可以是列表,也可以是数组。类似地,combinations()combinations_with_replacement()分别返回替换和不替换 iterable 的组合。后者允许单个元素连续重复。所有三个函数的参数都是相同的。

感谢阅读!

希望有帮助。欢迎任何评论或批评。

Python 3.9

原文:https://towardsdatascience.com/python-3-9-9c2ce1332eb4?source=collection_archive---------3-----------------------

有什么新的,下一步是什么?

法比奥·卢卡斯Unsplash 上拍摄的照片

Python 3.9 的完整版本发布了!

很明显,这个版本标志着 Python 进化旧路线的一个转折点,走上了一条新的道路。我们将涵盖:

**> Python's New Path**
  - Parser change
  - Development cycles**> New Features**
  - Type Hinting
  - String Methods
  - Dictionary Unions

让我们探索这些新特性,了解 Python 的发展方向。

Python 的新路径

这次更新中有两个重要的变化,我们看不到任何直接的影响——但我们将开始注意到 Python 作为一种语言的略微不同的演变。

简而言之,这归结为:

  • Python 的解析器限制
  • 更小但更频繁的发布

LL(1)和 PEG

大约 30 年前,吉多·范·罗苏姆写了 pgen。为 Python 编写的第一批代码之一——它至今仍被用作 Python 的解析器[1]。

Pgen 使用基于 LL(1)的语法的变体。这意味着我们的解析器从上到下、从左到右地读取代码,只对一个标记进行前瞻。

这实质上意味着 Python 开发受到了限制,因为:

  • 一个标记的前瞻限制了语法规则的表达能力。
  • Python 已经包含了非 LL(1)语法,这意味着当前的解析器使用了大量的变通方法,使过程过于复杂。
  • 即使有这些变通办法,也只能做到这一点。规则可以变通,但不能破坏。
  • 对于 LL(1),特定的左递归语法会导致解析树中的无限循环,从而导致堆栈溢出——正如这里的吉多·范·罗苏姆T12 所解释的。

基于 LL(1)的解析器的这些属性限制了 Python 中的能力。

Python 3.9 已经突破了这些限制,这要感谢一个闪亮的新 PEG 解析器,在 PEP 617 中有概述。

立刻,我们不会注意到这一点。在 Python 3.10 之前,不会利用新的解析器进行任何更改。但在那之后,这种语言将被从它的枷锁中释放出来。

开发周期

Python 发布时间表,它将从 18 个月的发布时间表切换到 12 个月。

在 3.9 之前,Python 的发布时间表是 18 个月。现在,我们看到了向 12 个月发布时间表的转变。

我们现在每年都会看到新版本的 Python,而不是一年半一次。这意味着:

  • 就新特性而言,发行版更小。
  • 变化更为渐进,但通过更快地发布新功能和修复程序来获益。
  • 更加一致的发布日历。我们现在知道新的 Python 将在每年十月到来!

因此,本质上,我们在这里看到的是在 12 个月的周期内专注于较小的增量变化,而不是每 18 个月的较大变化。与此同时,发展速度预计将保持不变。

新功能

除了这些幕后的变化,我们还可以看到一些新的 Python 特性!

类型提示

早在 2008 年,Python 3 引入了函数注释——类型提示的前身。它不是特别健壮,但它是一个开始。

Python 中类型提示的当前状态是随着时间的推移,对注释和类型的许多添加和修改的累积结果。

随后,随着时间的推移,更多的功能被添加进来。但是现在,3.9 将所有这些不同的特性和一个整洁的新语法结合在一起,产生了 Python 类型提示的最新发展。

我们可以很容易地指定变量的预期数据类型。如果我们写了一些没有意义的东西(比如我们把一个字符串传递给一个整数),那么我们的编辑器会标记这个问题。

不会出现任何错误(不幸的是),但是在处理复杂的代码库时,它非常有用。让我们来看看新的语法。

在 Python 中,用+将两个字符串加在一起绝对有效。因此,在这个add_int函数接收两个字符串的情况下,不会出现错误。

无类型提示(左),Python 3.9 类型提示(右)。

有了新的类型提示功能,我们只需在函数定义中将: int添加到我们的参数中,我们的编辑器就会立即注意到这个错误。

指定预期的输入和输出数据类型。

我们也可以使用-> type语法来确定函数输出的值的类型。

我们可以将不同的类型结合起来创建更复杂的注释。

我们也不局限于简单的预定义类型!

字符串方法

也许不像其他变化那样华丽,但我看到它被大量使用。我们有两种新方法来删除字符串前缀和后缀:

"foo bar".remove**prefix**("fo")

**[Out]**: 'o bar'

"foo bar".remove**suffix**("ar")

**[Out]**: 'foo b'

字典联盟

我们现在有两个新的操作符来执行字典联合。

第一个是合并操作符|:

a = {1: **'a'**, 2: **'b'**, 3: **'c'**}
b = {4: **'d'**, 5: **'e'**}c = **a | b**
print(c)

[Out]: {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}

以及更新操作符,执行合并就地:

a = {1: 'a', 2: 'b', 3: 'c'}
b = {4: 'd', 5: 'e'}**a |= b**
print(a)

[Out]: {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}

有很多值得期待的

作为一门语言,Python 的未来有很多值得期待的地方。看到这种语言如何随着新的发布时间表和解析器而发展将是非常有趣的。

点击这里获取下载链接!

如果您有任何问题或建议,请在 Twitter 或在下面的评论中告诉我。如果你想知道更多类似的内容,我也会在 YouTube 上发布。

感谢阅读!

资源

[1]吉多·范·罗苏姆, PEG 解析器 (2019)。

如果你对 Python 感兴趣——你可能会喜欢我的使用 Docker 将 Python APIs 部署到 Google Cloud 的指南:

[## 用 Python 和 Docker 部署 API

使用 Flask、Docker 和 Google Cloud 部署 API 的权威指南

towardsdatascience.com](/deploy-apis-with-python-and-docker-4ec5e7986224)

*所有图片均由作者制作,除非另有说明。

Python 3.9 —最新更新的实际操作

原文:https://towardsdatascience.com/python-3-9-hands-on-with-the-latest-updates-8137e2246119?source=collection_archive---------22-----------------------

比较 Python 3.9 和 Python 3.8 新推出的功能

Python 3 . 9 . 0——Python 的最新稳定版本发布了!

在过去的一年里,来自世界各地的开源爱好者一直致力于开发新的、增强的和不推荐的特性。尽管测试版已经推出很长时间了,Python 3.9.0 的正式发布是在 2020 年 10 月 5 日

官方文档包含了最新特性和变更日志的所有细节。通过这篇文章,我将带你了解一些很酷的特性,它们可能会在我们的日常编程任务中派上用场。

我们将了解以下内容:

  • 类型提示泛型和灵活函数以及变量注释
  • 字典中的联合运算符
  • **zoneinfo** —访问和计算时区
  • 去除前缀和后缀的字符串方法
  • 其他发布亮点

要跟随我或尝试新特性,您应该安装 Python 3.9。我使用了一个名为 pyenv 的环境管理器(或者,您可以使用 conda)来安装最新版本和我的当前版本。您也可以使用官方 docker 图像来运行它。

灵活的函数和变量注释

自 python 3.0 以来,函数注释就已经存在,它使我们能够向 python 函数添加元数据。那么,Python 3.9 有什么新特性?

Python 3.9 增加了 PEP 593 ,引入了一种机制来扩展PEP 484的类型注释,为注释提供了标准的语义,并建议将注释用于类型提示。

现在,除了类型提示之外,还有许多其他的注释用例,因此 PEP 593 引入了typing.Annotated,它允许我们向元数据添加更多的细节。

让我们通过一个 Python 3.8 和 3.9 的例子来更好地理解这一点。

Python 3.8

def currency_exchange(eur: "euros", rate: "exchange rate") -> "euro to USD": """Converting Euros to USD using the exchange rate""" return eur * rate

这是一个简单的函数,使用汇率将欧元转换成美元。我们使用注释作为用户的文档。

Python 3.9

from typing import Annotateddef currency_exchange(eur: Annotated[float, "euros"], rate: Annotated[float, "exchange rate"]) -> Annotated[float, "euro to dollars"]: """Converting Euros to Dollars using the exchange rate""" return eur * rate

这里,我们使用新引入的Annotated,它至少有两个参数。第一个参数(示例中的float)建立了类型提示,其余的参数是函数的任意元数据。

用户/开发者也可以使用__annotations__属性来检查这些注释:

我们也可以使用get_type_hint()功能检查类型:

标准集合中的类型提示泛型

intstrbool这样的基本数据类型很容易注释。早期的静态类型是在现有 Python 运行时之上逐步构建的,并受其约束。由于泛型,这导致了类型模块中重复的集合层次结构,即我们既有typing.List又有内置列表。

对于泛型,我们有参数化的问题,因为它们的存储结构是一个容器。由于这些原因,我们不能直接使用list(float)list[float]作为类型提示,而是需要类型模块来实现。

Python 3.9 中,不再需要这种重复的层次结构。我们可以直接注释它们:

scores: list(float)

合并和更新词典

Python 3.9 最酷、最有用的特性之一是添加到内置dict类中的 merge(|)和 update(|=)操作符。

现有的(3.8)合并两个字典的方法有许多缺点:

Python 3.8

  • Dict 拆包看起来很丑,不容易被发现。
python = {2000: "2.0.1", 2008: "2.6.9", 2010: "2.7.18"}
python3 = {2008: "3.0.1", 2009: "3.1.5", 2016: "3.6.12", 2020: "3.9.0"}##merging two dictionaries
{**python, **python3}

  • 另一种方法是 dict.update,它就地修改原始字典:

Python 3.9

PEP 584 为字典引入了两个新的操作符:

  • (|) union — 合并两个字典。它保留了原始词典。
  • (|=)更新— 这是用于字典的就地合并。
python = {2000: "2.0.1", 2008: "2.6.9", 2010: "2.7.18"}python3 = {2008: "3.0.1", 2009: "3.1.5", 2016: "3.6.12", 2020: "3.9.0"}##merging two dictionaries
python | python3

保留下来的原始格言:

python |= python3
python

更新操作符合并字典并更新操作符左边的字典,同时保留两个字典中重叠键的最后值

使用时区 ZoneInfo

日期和时间在大多数应用程序中扮演着重要的角色。Python 通过标准库中的datetime模块提供了全面的支持,但在将时区集成到这些时间戳方面一直存在差距。

到目前为止,我们已经有了像 dateutil 这样的第三方库来实现这样的时区特定规则,但是现在 Python 3.9 让 Paul Ganssle 加入核心团队来添加一个新的**zoneinfo**模块,该模块提供了整个互联网数字地址分配机构(IANA)时区数据库以供访问和使用。

Python 3.8

到目前为止,我们一直使用tzinfo参数访问时区感知时间戳,如下所示:

from datetime import datetime, timezonedatetime.now(tz=timezone.utc)

Python 3.9

但是随着 zoneinfo 的加入,我们现在可以访问 IANA 时区数据库

from zoneinfo import ZoneInfoZoneInfo("Asia/Kolkata")

我们可以根据时区进行一系列操作,相互转换变得非常容易:

from datetime import datetime
from zoneinfo import ZoneInfopost_date = datetime(2020, 10, 10, 18, 10, tzinfo=ZoneInfo("America/Vancouver"))post_date.astimezone(ZoneInfo("Asia/Kolkata"))

去除前缀和后缀的字符串方法

PEP 616 引入了从字符串中去除前缀和后缀的新方法。新方法包括:

  • removeprefix()
  • removesuffix()

围绕lstrip()rstrip()方法,所有主要论坛(如 StackOverflow)都有许多重复出现的问题。

Python 3.8

我们已经使用 strip()方法从字符串的两端剥离了字符,如下所示:

"Python 3.9 is out".strip(" Python")

这已经删除了出现在字符串末尾的子字符串。如果你仔细看,这已经删除了“python”中的单个字符,即“,“p”,“y”,“t”,“h”,“o”和“n”。

Python 3.9

为了去掉字符串的前缀,我们现在有了removeprefix()

"Python 3.9 is out".removeprefix("Python ")

您也可以使用removesuffix()方法通过许多其他排列和组合来检验这一点。

其他发布亮点

除此之外,还引入了许多其他功能。以下是 PEP IDs 列表:

  • PEP 617 ,CPython 现在使用了一个基于 PEG 的新解析器——Python 现在有了一个新的解析器,与旧的 LL(1)解析器并列。您可以使用以下命令选择使用任何解析器来运行您的程序:
python -X oldparser script_name.py

根据 Guido(Python 的创造者)的研究,PEG 解析器更加健壮和强大。PEG 解析器的目标是产生与旧的 LL(1)解析器相同的抽象语法树(AST)** 。**

  • ****多阶段初始化现在可以在多个 python 模块中使用([audioop](https://docs.python.org/3/library/audioop.html#module-audioop)_bz2_codecs_contextvars_crypt_functools_json_locale[math](https://docs.python.org/3/library/math.html#module-math)[operator](https://docs.python.org/3/library/operator.html#module-operator)[resource](https://docs.python.org/3/library/resource.html#module-resource)[time](https://docs.python.org/3/library/time.html#module-time)_weakref)

下面是一个使用数学库计算两个以上数字的 GCD/LCM 的示例:

  • CPython 现在采用新的年度发布周期——他们将与他们的发布更加一致,并将在每年 10 月推出新版本。
  • PEP 614 ,放宽了对装饰者的语法限制——一种更灵活的语法现在可供从事 PyQT 等 GUI 框架工作的人使用。这免除了由点号组成的装饰者的限制。更多详情可以在这里阅读

要了解更多关于这些特性的细节,请阅读官方文档。

结论

3.9.0 标志着 Python 开发之旅和社区的一个重要里程碑。正如我们所说的,新的增强功能正在增加,3.10 也将有一些有前途的特性。现在,您应该尝试一下 Python 3.9 中引入的这些即将被广泛使用的特性。

尝试使用 Python 3.9 运行您现有的程序,看看升级对您来说是否会很麻烦。

你应该尝试的另一件事是新的解析器,它声称是有前途的,但是我们只有在几个用例的大量测试之后才能弄清楚。

数据科学与 Harshit

通过这个渠道,我计划推出几个覆盖整个数据科学领域的系列。以下是你应该订阅频道的原因:

请随时在 Twitter 或 LinkedIn(T21)上与我联系。

Python 3.9 可用!您必须使用这些强大的功能…

原文:https://towardsdatascience.com/python-3-9-is-available-and-you-must-use-these-great-features-316387e1d3e5?source=collection_archive---------12-----------------------

2020 年 10 月 5 日,Python 发布了 3.9 版本。在本帖中,我们回顾了几个惊人的特性,并指出了相关的来源,以供进一步阅读。

快门架

简介

10 月 5 日周一,Python 发布了新的稳定版本,3.9.0rc2,如果你对 Python 的源码页面感兴趣,可以点击这个链接获得:whats new/3.9。在本帖中,我们回顾了该版本的亮点、新特性、新模块、优化,并提供了一些源代码,以便在您自己的环境中进行尝试。此外,我们还参考了一些额外的阅读和实现资料。

Python 网站-主页。

所以,让我们开始吧...

新功能

  1. 合并两本字典
a = {‘first’: 1, 'second’: 2, 'python’: 3}
b = {’first’: 'third’, 'forth’: 'python3.9’}
a | b
{’second’: 2, 'python’: 3, ’first’:’third’,  'forth’: 'python3.9’}
b | a
{’first’: 1,’second’: 2, 'python’: 3, 'forth’:’python3.9’ }

更多字典操作,请访问python.org/dev/peps/pep-0584/

2.新增模块:不需要第三方库更新时区:模块zoneinfo已经添加到标准库中。它支持IANA时区数据库,如下所示:

from datatime import datetime
#from pytz import timezone <<<<<<<<<< #No need it!!!
from zoneinfo import ZoneInfocurrent_t=datetime.now()
current_t_paris= datetime.now()print(current_t.astimezone(ZonInfo('Europe/Paris')))----------
2020-10-06 05:04:01.932145+06:00

3.不需要从输入导入列表。列表 是可订阅的。

#from typing import List <<<<<<<<<< #No need it!!!
thelist: list[int] = [2,4,6,8]
print(thelist)
thelist: '2468'
print(thelist)------------[2,4,6,8]
2468

4.一行仅删除前缀/后缀

professors = ['Prof. A', 'Prof. B', 'Prof. C']
names_only=[]
for professor in professors:
    names_only.append(professor.removeprefix('Prof. ')
print(names_only)-------------['A', 'B', 'C']

欲了解更多前缀和后缀操作,请访问:

[## PEP 616 -删除前缀和后缀的字符串方法

这是一个向 Python 的各种字符串的 API 添加两个新方法 removeprefix()和 removesuffix()的提议…

www.python.org](https://www.python.org/dev/peps/pep-0616/)

更多功能我在 Malik 的帖子上推荐:https://towardsdatascience . com/10-awesome-python-3-9-features-b 8 c 27 f 5 EBA 5c

一个多处理改进和一个新的解析器

Python 3.9 为 CPython 带来了一个新的基于 PEG 的解析器,作为以前基于 LL 的解析器的替代( LL(1) ),多处理改进,从 C 扩展类型的方法快速访问模块状态,以及许多其他解释器改进。PEG 解析器比 LL(1)解析器更强大,并且不需要特殊的修改。PEG 解析器在 Python 3.9 中实现。0.通常,PEG 解析器产生抽象语法树(AST) 作为旧的 LL(1)解析器。更多详情请访问 PEP 617 。总的来说,PEG 解析器稍微快一点,但是它也使用稍微多一点的内存。实际上,在使用这个新的解析器时,人们不会注意到性能有任何变化。

更多详细信息,请继续阅读/观看

  1. 我强烈推荐 YouTube 上 Pretty Printed 的一个很棒的视频,其中他演示了一些新功能(1-4):

2.如果你想发现所有新版本的特性,你肯定会在 Python 网站上找到它们:python.org/3.9/whatsnew

该不该升级到 Python 3.9?

如果你想尝试任何伟大的新功能,那么你需要使用 Python 3.9。因此,您可以升级,然后回到当前的 Python 版本。你必须记住,如果你在 Python 3.8 中运行代码没有任何问题,那么你在 Python 3.9 中运行同样的代码时可能会遇到一些问题。此外,新的 PEG 解析器自然没有像旧的解析器那样经过广泛的测试,只有时间才能告诉我们真相。和往常一样,如果你对这个版本不确定,并且想要相当保守,你可以等待第一个维护版本: Python 3.9.1。

摘要

这个 Python 3.9.0 似乎有非常酷的特性。尽管如此,这不是一个革命性的版本,但它可能会带来更好的用户体验。这个版本对于 Python 社区来说是一个伟大的里程碑。希望几年后,Python 3.9 会像现在的 Python 3.6 一样普及,因为观察 Python 如何发展新的特性和解析器总是很好的。

关于作者

Barak 获得了以色列理工学院的航空工程学士学位(2016 年)、硕士学位(2018 年)以及经济和管理学士学位(2016 年,成绩优异)。他曾在高通工作(2019-2020),在那里他主要研究机器学习和信号处理算法。巴拉克目前正在海法大学攻读博士学位。他的研究兴趣包括传感器融合、导航、深度学习和估计理论。

www.barakor.com

[## 巴拉克或-以色列海法大学| LinkedIn

在全球最大的职业社区 LinkedIn 上查看 Barak Or 的个人资料。巴拉克有 2 份工作列在他们的…

www.linkedin.com](https://www.linkedin.com/in/barakor/)

参考

[1] Python 网站:https://docs.python.org/3.9/whatsnew/3.9.html

[2]Python 3.9 的 10 个牛逼特性,中帖。法尔哈德·马利克

[3] Python 3.9。中等职位,詹姆斯·布里格斯

[4] Python 3.9:很酷的新特性供你尝试。 RealPython 。盖尔·阿恩·赫杰尔

[5]Python 3.9 中的一些新特性。YouTube 蛮印

Python 3.9 更新新功能

原文:https://towardsdatascience.com/python-3-9-update-new-features-e4a580fc5c2?source=collection_archive---------10-----------------------

Python 备忘单

少写代码,多成就!

当你阅读这篇文章时,你可能正在使用 Python 3.8。准备好!几个月后,我们将看到 Python 的新版本(计划在 2020 年 10 月)。由于我们目前是测试版,让我们看看这个版本有什么新的。这次更新有 4 个主要的新特性,它们是字典联合操作符、字符串方法、类型提示和 Python 解析器。但是,本文将只讨论前三个更新,因为它们是您最有可能遇到/使用的。

图片由法比奥Unsplash 上拍摄

Python 字典联合方法

  1. 更新方法
  • 老办法

直到 Python 3.8,人们仍然普遍使用update()方法更新字典。它看起来是这样的:

dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
dict1.update(dict2)print(dict1) #return {"a": 1, "b": 2, "c": 3, "d": 4}

真的能变好吗?是的,它可以!3.9 的更新绝对符合 Python 的精神,编写更少的代码!

  • 新的方式

要在 Python 3.9 中更新字典,可以使用这个新的更新操作符|=。与之前的update()方法相比,这将使你的代码看起来更加光滑。

dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
**dict1 |= dict2**print(dict1) #return {"a": 1, "b": 2, "c": 3, "d": 4}

2.合并方法

  • 老办法

到目前为止,合并 2 个字典的最好方法是使用双星号操作符**。我们是这样做的:

dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
dict3 = {**dict1, **dict2}print(dict3) #return {"a": 1, "b": 2, "c": 3, "d": 4}

上面的片段看起来不错。它短小精悍,更重要的是,做工作。然而,对包括我在内的大多数开发人员来说,它看起来有点丑,也没什么吸引力。终于!有一个更好的方法来解决这个问题。

  • 新的方式
dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
dict3 = **dict1 | dict2**print(dict3) #return {"a": 1, "b": 2, "c": 3, "d": 4}

你们应该记住的唯一一件事是当两个字典有相似的关键字时。合并后,公共键的值将从第二个字典中获取

dict1 = {"a": 1, "b": 2, **"same" : "old"**}
dict2 = {"c": 3, "d": 4, **"same": "new"**}
dict3 = **dict1 | dict2**print(dict3) #return {"a": 1, "b": 2, "c": 3, "d": 4, **"same": "new"**}

Python 字符串方法

在这些新的更新中,字符串方法增加了两项内容。他们增加了removeprefix()removesuffix()功能。这个特性并不能改变生活,但绝对值得一提。

  • removeprefix()
string = "New Python".**removeprefix("Ne")**print(string) #return ***"w Python"***
  • removesuffix()
string = "New Python".**removesuffix("on")**print(string) #return **"New Pyth"**

Python 类型提示

Python 在最好的时候不需要类型声明。然而,在某些情况下,它可能会导致混乱。下面是事情可能变得混乱的例子:

假设您想通过使用自己创建的奖金函数来确定办公室员工的年度奖金。

  • 没有类型提示:
def Bonus(base):
    print("Your Bonus is ${}".format(base*3))
Bonus(4000) #print "Your Bonus is **$12000**"

在上面的代码片段中看起来很好,但是如果您要求用户输入呢?

base = input("Enter the employee's base salary")
#for example you typed 4000Bonus(base) #print "Your Bonus is **$400040004000"**

和你想象的不太一样,对吗?这是因为 Python 输入函数将返回字符串类型。因为*操作符也可用于字符串,所以不会发生错误。*操作符,当应用于一个字符串时,将在指定的次数内连接该字符串。

string = "Hello"
print(**string*2**) #print "HelloHello"

*操作符之后,我们输入值 2。解释器将“Hello”字符串连接了两次,并输出“HelloHello”作为结果。

别担心,您可以通过使用新的 Python 类型提示特性来解决这个问题。

  • 使用类型提示
def Bonus(base: int):
    print("Your Bonus is ${}".format(base*3))base = input("Enter the employee's base salary")
#for example you typed 4000Bonus(base) #return "Expected type 'int', got 'str' instead"

类型提示实际上是从 Python 3.5 开始引入的。由于 Python 3.9 中的新更新,现在看起来干净多了!

最后的想法

Python 3.9 的新更新并没有那么重要。然而,总的来说,可以肯定地说,这将是一个不错的更新。Python 总是做对的一件事是为用户提供良好的可读性。

记住伙计们!将于 10 月上市。希望本文能帮助您过渡到新的 Python 3.9。

问候,

弧度克里斯诺

Python 和 AWS SSM 参数存储

原文:https://towardsdatascience.com/python-and-aws-ssm-parameter-store-7f0e211bb91e?source=collection_archive---------5-----------------------

保护应用程序秘密的一种方法是通过 AWS SSM 参数存储。我们将看看如何以编程方式检索和解密这个秘密。

照片由克里斯·帕纳斯Unsplash 拍摄

介绍

在任何应用程序中,拥有一些秘密是很常见的,我们的应用程序需要这些秘密来提供它想要的功能。禁止把那些秘密放在我们的项目文件夹里,提交给 Github repo。这是一个很大的不,不。🙅‍♂

有几个安全存储秘密的替代方法,但是,在本教程中,我将向您展示如何使用 AWS 密钥管理服务(KMS)和系统管理器的参数存储(SSM)来实现。我们将使用 Python 3.8 作为编程语言,并使用官方的 AWS Boto3 库来与 AWS 资源进行交互。

你将学到什么

本教程结束时,您将能够完成以下练习:

  • 用 KMS 创建一个密钥
  • 把一个参数/秘密作为进入 SSM 的安全措施
  • 检索并解密 SSM 秘密参数

本教程的 Github repo 可从这里获得。

先决条件

本教程假设您已经拥有一个 AWS 帐户,并且可以访问它。这是做 KMS 和 SSM 相关练习所必需的,特别是创建 KMS 键并将一个参数放入 SSM。我们将使用aws-cli来做这件事。你可以按照 AWS 官方文档来安装和设置凭证。

或者,您可以直接在 AWS 控制台上完成。

准备 Python 环境和依赖性

在本节中,我们将设置 SSM 参数解密所需的所有组件。

创建虚拟环境

让我们使用virtualenv创建一个虚拟环境来包含我们的项目依赖关系。从您的终端运行以下命令来创建虚拟环境并激活它。

$ ❯ mkdir -p ./demo/kms-ssm-decrypt$ ❯ cd ./demo/kms-ssm-decrypt$ ~/demo/kms-ssm-decrypt ❯ virtualenv ./venv
Using base prefix '/Library/Frameworks/Python.framework/Versions/3.8'
New python executable in /Users/billyde/demo/kms-ssm-decrypt/venv/bin/python3.8
Also creating executable in /Users/billyde/demo/kms-ssm-decrypt/venv/bin/python
Installing setuptools, pip, wheel...
done.$ ~/demo/kms-ssm-decrypt ❯ source ./venv/bin/activate$ ~/demo/kms-ssm-decrypt (venv) ❯

安装 Boto3 库

唯一需要的库是 Boto3。让我们创建一个文本文件来保持项目的依赖性,并将其命名为requirements.txt

requirements.txt

我们之所以有这个文本文件而不是直接安装库,是因为我们可以将它提交给 Github repo,而不是整个venv以保持 repo 大小紧凑。然后,任何人都可以克隆 repo,并通过pip在他们的机器上安装所有的需求。

让我们继续从我们的终端安装这个包。

$ ~/demo/kms-ssm-decrypt (venv) ❯ pip install -r requirements.txt
Collecting boto3==1.11.0
  Using cached boto3-1.11.0-py2.py3-none-any.whl (128 kB)
Collecting s3transfer<0.4.0,>=0.3.0
  Downloading s3transfer-0.3.2-py2.py3-none-any.whl (69 kB)
     |████████████████████████████████| 69 kB 1.5 MB/s
Collecting botocore<1.15.0,>=1.14.0
  Downloading botocore-1.14.9-py2.py3-none-any.whl (5.9 MB)
     |████████████████████████████████| 5.9 MB 4.6 MB/s
Collecting jmespath<1.0.0,>=0.7.1
  Using cached jmespath-0.9.4-py2.py3-none-any.whl (24 kB)
Collecting urllib3<1.26,>=1.20
  Using cached urllib3-1.25.8-py2.py3-none-any.whl (125 kB)
Collecting python-dateutil<3.0.0,>=2.1
  Using cached python_dateutil-2.8.1-py2.py3-none-any.whl (227 kB)
Collecting docutils<0.16,>=0.10
  Using cached docutils-0.15.2-py3-none-any.whl (547 kB)
Collecting six>=1.5
  Using cached six-1.14.0-py2.py3-none-any.whl (10 kB)
Installing collected packages: urllib3, six, python-dateutil, docutils, jmespath, botocore, s3transfer, boto3
Successfully installed boto3-1.11.0 botocore-1.14.9 docutils-0.15.2 jmespath-0.9.4 python-dateutil-2.8.1 s3transfer-0.3.2 six-1.14.0 urllib3-1.25.8

创建 KMS 键

既然我们要存储 secret/s,最好在静态时加密它,以提供额外的安全层。我们将创建一个 KMS 密钥,用于加密和解密我们的秘密参数

从您的终端,运行以下命令,这将创建一个 KMS 密钥。

$ ~/demo/kms-ssm-decrypt (venv) ❯ aws kms create-key --description "A key to encrypt-decrypt secrets"
{
    "KeyMetadata": {
        "AWSAccountId": "xxxxxxxxxxxx",
        "KeyId": "ca83c234-7e63-4d8d-1234-28603cb10123",
        "Arn": "arn:aws:kms:ap-southeast-2:xxxxxxxxxxxx:key/ca83c234-7e63-4d8d-1234-28603cb10123",
        "CreationDate": 1580217378.859,
        "Enabled": true,
        "Description": "A key to encrypt-decrypt secrets",
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "Enabled",
        "Origin": "AWS_KMS",
        "KeyManager": "CUSTOMER"
    }
}

很好,如果运行成功,该命令会将密钥元数据输出到控制台上。我们可以继续下一步了。

将秘密放入 SSM 参数存储中

我们将把一个秘密参数作为SecureString存储到 SSM 参数库中。SecureString参数类型仅仅表示我们存储的参数值将被加密。

为了放置一个秘密参数,让我们从终端执行下面的命令。

$ ~/demo/kms-ssm-decrypt (venv) ❯ aws ssm put-parameter --name "/demo/secret/parameter" --value "thisIsASecret" --type SecureString --key-id ca83c234-7e63-4d8d-1234-28603cb10123 --description "This is a secret parameter"
{
    "Version": 1,
    "Tier": "Standard"
}

该命令的参数是不言自明的,但是,我只想强调其中的几个:

  • --name:是你正在存储的参数的名称或路径,例如,它可能只是一个类似于“somesecretpathname”的名称,而不是上面的路径。
  • --value:您正在存储的参数值。
  • --type:参数的类型,在这个例子中是一个SecureString,告诉 SSM 在将值存储到参数存储之前加密它。如果你只是存储一个非秘密的参数,那么 SSM 参数类型应该是String
  • --key-id:您想要用来加密参数值的 KMS 密钥的 id。这是上一节中生成 KMS 键的KeyId的值。
  • --description:是您正在存储的参数的描述,以便您知道它的用途。

太棒了。现在,我们将秘密参数存储在 SSM 参数存储中。让我们看看如何以编程方式检索和解密它。

编写一个 Python 脚本来检索和解密机密

现在,是时候编写脚本来检索我们刚刚存储在 SSM 参数存储中的秘密参数,并解密它,以便我们可以在我们的应用程序中使用它。

让我们在项目目录中创建新的 Python 文件,并将其命名为retrieve_and_decrypt_ssm_secret.py

retrieve_and_decrypt_ssm_secret.py

注意get_parameter()函数名为WithDecryption的参数。在本练习中,我们将它指定为True,因为我们想要获得这个秘密值并在我们的应用程序中使用它。你可能会问,为什么我们不指定用来加密它的KeyId?答案是,KeyId信息实际上包含在加密的参数中,因此,SSM 知道用哪个密钥来解密这个秘密。

该脚本可从终端运行,它接受一个参数,即参数的名称或路径。像这样从终端执行它。(注意,Boto3 将在您的环境中寻找 AWS 凭证)

$ ~/demo/kms-ssm-decrypt (venv) ❯ python3 retrieve_and_decrypt_ssm_secret.py "/demo/secret/parameter"Secret is
thisIsASecret
=====
Parameter details
{'Parameter': {'Name': '/demo/secret/parameter', 'Type': 'SecureString', 'Value': 'thisIsASecret', 'Version': 1, 'LastModifiedDate': datetime.datetime(2020, 1, 30, 23, 26, 35, 169000, tzinfo=tzlocal()), 'ARN': 'arn:aws:ssm:ap-southeast-2:xxxxxxxxxxxx:parameter/demo/secret/parameter'}, 'ResponseMetadata': {'RequestId': '5ad11d35-axz6-42a0-90g5-0b7682a79321', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': '5ad07d20-ama6-43c0-90a4-0b7682a11267', 'content-type': 'application/x-amz-json-1.1', 'content-length': '239', 'date': 'Thu, 30 Jan 2020 12:48:53 GMT'}, 'RetryAttempts': 0}}

Tada!我们拿回了秘密参数— thisIsASecret。🙂

包裹

到目前为止,您已经掌握了如何使用 AWS KMS 和 SSM 参数库保护您的应用程序机密的基本技能和知识。您还学习了如何以编程方式检索机密,以便可以在您的应用程序中使用它。

我希望本教程是有用的,并帮助您了解一种方法来保护您的应用程序的秘密。

只是提醒一下,Github 回购在这里可用

Mauro Sbicego 在 Unsplash 上拍摄的照片

Python 和计算机视觉

原文:https://towardsdatascience.com/python-and-computer-vision-d0b4a1b49676?source=collection_archive---------60-----------------------

或者如何在你朋友的视频上画傻乎乎的脸

来源:数字摄影师,通过图片 (CC0)

在这篇文章中,我打算温和地向您介绍计算机视觉中的一些概念。不需要以前在该领域的知识,但你至少应该有 python 和机器学习的基本概念。

那我们怎么做?我们将拍摄某人面部的视频,将其分成帧,检测面部的面部标志(鼻子、嘴……),并在检测到的标志上绘制一些东西。听起来很简单,对吧?好吧,让我们开始吧。

首先,我要感谢 Adrian Rosebrock 和他令人惊叹的网站,如果你想了解更多关于计算机视觉的知识,我强烈推荐你浏览这个网站。

此外,本文假设您已经完成了dlib的安装。如果没有,不要担心,详情可以在这里找到。虽然 Adrian 在 Ubuntu 和 MAC OS上都这么做了,但我是在我的 windows10 机器上做的,步骤如下:

根据经验,如果这个包在 conda 仓库中,用 conda 安装它,而不是用 pip,否则就用 pip。截至 2020 年 3 月 30 日,康达提供以下所有套餐。

  • 如果你没有安装 anaconda,安装它。
  • 创建一个新的康达虚拟环境。在里面安装 jupyter 笔记本
  • 安装boostpy-boostcmake。如果你已经在 Windows 系统上,不用担心X11。确保在 v-env 中安装了所有的包。
  • 安装numpyscipyscikit-image。还要安装imutils,Adrian 开发的包。
  • 最后,安装dlib

上面提到的所有软件包都可以用 conda 安装,但是要用pip安装opencv-python

您可能仍然需要安装这些先前包所具有的一些其他依赖项。如果错误信息提示你有一些缺失的包,安装它。你还需要下载面部检测器shape_predictor_68_face_landmarks.dat,你可以从这篇文章下载,或者从这里克隆并提取它。

因为我更喜欢用笔记本的方式做事情,所以我编辑了 Adrian 在这篇文章中开发的代码。代码如下:

如果你把代码放在笔记本里运行,你就做对了。如果没有,请留下你的评论,我会尽力帮助你。第二步是运行下面的代码,该代码部分来自 Adrian 的帖子,它将向您显示一张脸上的面部标志。为此,如果您需要视频,只需用 windows 摄像头录制一小段即可。

在第 1–4 行,我们加载预测器和面部检测器,第 5–8 行,我们加载视频,在每帧的循环中,我们检测面部标志点,并在帧中绘制成圆圈。如果你想停止录像,就按“q”。

所以我们已经准备好了本文的第一部分,检测人脸。现在,我们应该能够检测面部的一部分,这非常简单,因为你看到的 68 个红点是有序的,很清楚哪些属于你面部的每个部分,所以你只需要定义一个字典,我们稍后将使用它来访问这些点。

下一步是画一些你想放在鼻子、嘴巴等上面的东西。我建议你使用 windows 10 中的 paint3D,因为我们将需要绘图有一个透明的背景。如果你知道用 python 和(可能)opencv 制作透明背景的方法,请告诉我,因为我花了太多时间来实现这个。

因此,打开 paint3D,选择“画布”并打开“透明背景”。现在画一些你想放在你的一个面部标志上的东西,例如嘴:

现在剩下的就是定义一些函数来为我们完成任务。第一个是一个简单的函数,从一个点的数组(或列表)中返回边界框角的坐标(稍微大一点)。

然后,我们要定义一个函数,从一张图片和四个点,计算变换,把原始图像投影到那个地方。你可以在这里找到更多信息。注意我们在这里使用的主要函数是如何来自 opencv 包的。我强烈推荐你阅读软件包文档,因为那里有很多东西要学。

我们需要的最后一个函数是一个拍摄两张图片并将其中一张叠加在另一张上面的函数。

这个最后的函数将两个图像对齐,一个在另一个的上面,但是因为我们要投影小的一个,它将被放置在我们想要的任何地方。

所以结合这三个函数,我们要在第一个循环中改变一点,结果会像我保证的那样愚蠢。

面向 Windows 10 的 Python 和 GDAL 自动安装

原文:https://towardsdatascience.com/python-and-gdal-installation-automated-for-windows-10-f22686595447?source=collection_archive---------18-----------------------

照片由像素皮克斯拜拍摄

你是地理空间处理 Python 的初学者吗?你觉得安装过程有点麻烦吗?那你来对地方了!对于该领域的专家来说,如果你正在使用 Windows 10,我希望这将为你节省一些手动工作。

好吧!我们开始吧!

这个 GitHub repo 下载 Python_GDAL_(32/64)。bat 文件,请确保将其保存为批处理文件(*。蝙蝠)。

右键点击下载的文件,选择“以管理员身份运行”

以管理员权限运行下载的文件。

该脚本将下载安装文件,并运行他们一个接一个,确保您连接到互联网。如果您的连接速度太慢或者下载服务器出现故障,脚本将会终止。在这种情况下,您可以简单地重新运行它。

文件下载完成后,Python 安装窗口会自动弹出,然后您必须选择“定制安装”,如下图所示。

选择自定义安装

按照说明继续安装,直到到达高级选项窗口。减少安装路径,如下所示。这是一个强制步骤,也是你在整个过程中唯一需要注意的事情。

缩短目录

单击安装按钮,等待安装完成。安装成功后会弹出 GDAL 安装窗口,不要做任何更改,一直点击下一步完成安装。当询问时,选择典型的安装。

最后,将开始安装 Python 的 GDAL 模块,保留所有默认设置,为所有用户安装,并检查安装是否针对正确的 Python 实例,如下图所示。

从注册表中选择 Python 3.7

如果这是系统上的第一次 Python 3.7 安装,并且没有冲突安装,那么这个过程将会很顺利。

完成后,安装程序将在 30 秒内自动关闭。从开始菜单打开命令提示符,键入 python37 启动 python,或者在开始菜单中搜索 Python 3.7 IDLE 并打开。在控制台中输入 import gdal ,理想情况下,它不应该在屏幕上打印任何东西。

如果它抛出错误,尝试从开始菜单或控制面板中的添加或删除程序选项卸载 Python 和 GDAL,并使用(*)重试安装。bat 档。如果你面临任何其他问题,请随意回复这篇文章。这个 YouTube 视频这个视频也演示了安装过程。

调试步骤(2021 年 4 月 14 日更新):

我们所有的计算机都是独一无二的,每一台都安装了不同的软件和反恶意软件防御程序。有时,这些甚至会使正常的流程变得繁琐。以下是到目前为止人们向我报告的错误列表(以及解决方案)。如果您的错误没有列在这里,不要担心。给我写信,评论这篇文章或 YouTube 视频,或者在 GitHub 上提出问题,我会在这里列出你的错误和解决方案。

1。ModuleNotFoundError:没有名为' _ gdal '【T19]的模块。当路径未被添加到系统变量中时,可能会出现此错误。 见此处 的步骤。

这个帖子到此为止。如果您想开始学习地理空间任务的机器学习方法,如 Landsat 多光谱分类,您可能会发现以下帖子很有用。

1.神经网络用于卫星数据分类使用 Python 中的 tensor flow
2。CNN 在中分辨率卫星数据上同样闪亮吗?

永远开心连接你— TwitterLinkedIn

分享开放知识!

如何用 Python 分析冠状病毒变异

原文:https://towardsdatascience.com/python-and-numpy-for-sars-cov-2-gene-mutation-analysis-805833fbb23f?source=collection_archive---------23-----------------------

基于 Python 和 NumPy 的新冠肺炎突变分析

马库斯·斯皮斯克在 Unsplash 上的照片

什么是冠状病毒变异?

新型冠状病毒 Sars Cov-2 在中国武汉首次被发现并被测序。任何生物的基因组都会由四个核苷酸碱基( A 腺嘌呤- AG 鸟嘌呤- GC 胞嘧啶- C、T 腺嘌呤- T )以特定的顺序排列在一个名为 DNA (D 脱氧核糖 N 细胞核的分子中这四个碱基的排列顺序至关重要。生物体基因中任何偏离这一序列的现象都被称为基因突变。在新型冠状病毒的情况下,它具有单链 RNA。在酶的帮助下,RNA 可以构成 DNA 分子。下面是新型冠状病毒 Sars Cov-2 的 M 膜基因的基因序列。如前所述,这是一个按特定顺序排列的序列。在我们的冠状病毒突变分析中,我们将比较新型冠状病毒的两种不同基因组序列。这两个序列是从 NCBI 基因库下载的。一个序列来自美国,另一个来自中国序列

作者图片

我们为什么要分析冠状病毒变异?

每种生物都在不断进化/经历突变,以更好地适应环境。同样,新型冠状病毒也将经历突变,以更好地适应人类。了解它变异的模式是非常重要的。理解这种模式对疫苗/药物开发工作有重大影响。例如,如果刺突蛋白正在经历突变,那么针对刺突蛋白开发的疫苗/药物可能不是在所有情况下都有效。这意味着我们将不得不重新开始寻找对抗新冠肺炎的新药/疫苗。

[## tonygeorge 1984/Python-Sars-Cov-2-突变-分析

这是为分析 Sars Cov-2 的各种基因的核苷酸突变而创建的报告。两种不同的…

github.com](https://github.com/tonygeorge1984/Python-Sars-Cov-2-Mutation-Analysis)

冠状病毒的背景

让我们从冠状病毒的一些背景开始。命名为SARST2【COV-2】的新型冠状病毒是当前新冠肺炎疫情的原因。这种病毒于 2019 年 12 月在中国武汉首次被鉴定和测序。这种病毒得名于它与之前已知的冠状病毒 SARS COV (这种病毒导致了 2002-2003 年的严重急性呼吸道综合征)的相似性。在写这篇文章的时候,科学家已经识别并研究了 500 多种不同的冠状病毒。在这 500 多种冠状病毒中, 7 种冠状病毒已知会导致人类感染。SARS COV-2 是名单中最新的一个。 SARS COVMERS COV(2012 年引起的MiddleEastRSSyndrome、 HKU1NL63OC43229E 是其他已知的冠状病毒

近距离观察 SARS COV-2

来自 NCBI 的医学博士 Rohan Bir Singh 的照片。图像信息:冠状病毒的特征、评估和治疗(新冠肺炎)。作者——马尔科·卡斯塞拉;迈克尔·拉杰尼克;阿图罗·科莫;斯科特·c·杜勒博恩;那不勒斯的拉斐尔。医学博士 Rohan Bir Singh 提供的数字;Biorender.com 制造

让我们仔细看看 SARS COV-2 。SARS COV-2 对人类细胞上的 ACE2 受体具有高亲和力。他们利用 ACE2 受体在细胞内吞作用前与人类细胞对接。从图中可以很清楚地看出,该病毒具有以下结构蛋白,即刺突蛋白、核壳蛋白、蛋白和包膜蛋白。疫苗/药物开发工作的目标是特定的病毒蛋白质结构/酶。在决定这样一个目标之前,我们了解病毒突变是非常重要的。如果靶蛋白结构发生突变,那么该药物/疫苗将来可能无效。这就是突变分析在创造药物/疫苗的努力中发挥关键作用的地方。SARS COV-2 的基因组由 11 个基因组成。每个基因及其表达(蛋白质)如下所列。

基因= ORF1ab 。编码蛋白质 ORF1a 和 ORF1ab 的开放阅读框 1。这也产生了几种非结构蛋白。

基因= S. 该基因编码 S pike 蛋白,该蛋白在内吞作用前与人体细胞的 ACE2 受体对接。这是一种具有 S1 和 S2 亚单位的三聚体蛋白质。

基因= ORF3a。开放阅读框 3 编码 ORF3a 蛋白。

E 。这个基因编码 E 包膜蛋白。

基因= M. 该基因编码为 M 膜蛋白。

基因= ORF6 。开放阅读框 6 编码 ORF6 蛋白。

基因= ORF7a。开放阅读框 7a 编码 ORF7a 蛋白。

基因= ORF7b 。编码 ORF7b 蛋白的开放阅读框 7b。

基因= ORF8 。开放阅读框 8 编码 ORF8 蛋白。

基因= N. 该基因编码 N 核衣壳磷蛋白。

基因= ORF10。开放阅读框 10 编码 ORF10 蛋白。

P ython 冠状病毒变异分析

链接到 Github 获取完整代码

在我们进入 Main.py 之前,让我们看看 dna 类、python 字典 numpy_image_dict 和辅助函数,如 read_dna_seqgene_mod。

班级 dna:

首先,我用 init 方法和重要的方法 numpfy 创建了一个新的类 dnainit 方法将检查所提供的基本序列是否有效。如果基本序列带有无效字符,将会抛出一个错误。该方法通过转换 A -0、T -255、G -200、C -100 和虚拟碱基 N -75 将碱基核苷酸序列转换成 numpy 阵列。

作者创建的要点

NCBI 网站收集了超过 4500 种不同的 SARS COV-2 病毒基因组序列。任何人都可以去 NCBI 网站下载基因组序列进行分析。或者,他们也提供 API 以编程方式访问基因库。在这个例子中,我已经下载了 2 个不同的核苷酸。第一个,是 2020 年 1 月发布的中国参考序列。另一个核苷酸序列来自美国,于 2020 年 4 月发布。通过分析这两个核苷酸,我们将在 3-4 个月内看到每个基因在不同地区的突变。

辅助函数 read_dna_seq:

阅读从 NCBI 下载的基因组序列。核苷酸碱基序列将有 A 腺嘌呤、 G 鸟嘌呤、 C 胞嘧啶和 T 腺嘌呤。下载的两个文件都有每个基因的碱基序列。下面的方法将读取文件,并找出元数据和每个基因的碱基序列。在这一步的最后,我们将得到名为 genome 的 python 字典。字典将基因名称作为关键字,值对将是该基因的碱基序列列表。

作者创建的要点

Python 字典 numpy_image_dict 和辅助函数 gene_mod:

我们已经创建了一个字典,其中预填充了为每个基因创建 numpy 数组所需的所有信息。这里,基因名是键,值对是一个列表。第一个元素是一个元组,该元组具有该基因的预定义数组形状。第二个元素是要添加到序列中的虚拟元素' N 的数量。比如基因 ORF1ab ,我计算过数组维数为 115 * 115 。这意味着 A、T、C 和 g 必须有 13225 个碱基序列。我所考虑的序列只有 13218 个碱基序列。为了弥补这个不足,我们在两个文件的基因序列中添加了 7 虚拟字符' N '。方法 gene_mod 将读取每个基因的字典 numpy_image_dict,并添加数字“N ”(如果字典中有指定)。

作者创建的要点

让我们浏览一下 Main.py 脚本

已经完成了所有需要的类、字典和助手函数,现在让我们完成主模块并开始使用所有前面提到的方法。我们需要导入 numpymatplotlib 来完成这项工作。再来导入上面提到的自定义构建的 dna 类、 numpy_image_dictionary 和 helper 函数( read_dna_seq,gene_mod )。导入所有需要的模块后,让我们读取从 NCBI 下载的两个文件,并对每个基因进行必要的修改,将它们转换成 numpy 数组。

作者创建的要点

作者创建的图像

为 11 个基因中的每一个创建 3 个 matplotlib 子图(来自文件 1 的基因,来自文件 2 的基因,结果突变图)。

f,ax = plt.subplots(nrows=11,ncols=3,figsize=(25,30))

从 read_dna_seq 方法返回的字典中创建所有 gene_name 的列表。

gene_name = list(numpy_image_dict.keys())

对于 gene_name 列表中的每个基因,创建一个 dna 对象并调用方法 numpfy 将其转换为 numpy 数组。这意味着对于序列中的每个基因,都将有一个 dna 对象,该对象将具有 numpy 数组属性。第二个列表中的所有基因也是如此。使用 matplotlib.pyplot 的 pcolor 方法将每个 numpy 数组转换为子图。

# Create the dna object for the USA sequence
gene_us = dna(dict_seq_1['gene=ORF10')# Call the numpfy method
numpfy_usa = gene_us.numpfy()# After numpfy do a reshape with numpy_image_dict tuple
numpfy_usa = numpfy_usa.reshape(numpy_image_dict['gene=ORF10'][0])# Create the matplotlib subplot
ax[row][col].pcolor(numpfy_usa)# Create the dna object for the CHINA sequence
gene_ch = dna(dict_seq_2['gene=ORF10')# Call the numpfy method
numpfy_china = gene_ch.numpfy()# After numpfy do a reshape with numpy_image_dict tuple
numpfy_china = numpfy_china.reshape(numpy_image_dict['gene=ORF10'][0])# Create the matplotlib subplot
ax[row][col].pcolor(numpfy_china)

最后我们发现了基因突变。这通过简单地从两个序列中减去相同基因的 numpy 阵列来完成。例如,来自美国序列的 ORF10 基因将有一个 numpy 阵列,来自中国序列的 ORF10 基因将有一个 numpy 阵列。要找到突变,只需减去 numpy 数组。在该减法之后,将检查结果 numpy 数组,以查看是否存在任何非零值。如果存在一个非零值,那就是我们要找的突变。我们将在 python 字典中捕获这种变异,以便进一步分析。变异的基因和具体位置会在 python 控制台打印出来。

作者创建的要点

Python 控制台打印出变异信息。

作者图片

matplotlib 子图将为所有 11 个有突变结果的基因创建。每行显示第一个序列中的一个基因,接着是第二个基因中的相同基因,接着是该基因上的突变。如果每行的第三个子图中有一个亮点,这意味着该基因至少有一个突变。如果没有突变,那么第三条支线剧情将是黑暗的,没有亮点。

作者图片

通过这种方法,整个基因组及其来自 2 个不同序列的突变可以在单个图像中可视化。这是市场上其他突变分析工具的显著区别。这只是一个开始,我们现在有了 numpy 数组形式的数据。这意味着我们可以在这些 numpy 数组上应用更多的变换,无论是对某个特定国家或地区的少数序列还是所有序列。这将帮助我们获得比其他工具更多的洞察力和预测。

这个项目是从头开始写的。我已经构建了这个项目的所有代码,除了 numpy 和 matplotlib 之外,没有使用任何其他库。如果你已经读到这里,我感谢你阅读这篇文章。

特别感谢马库斯·斯皮斯克。我在这篇文章开头使用的第一张图片是他创作的。

编者按:【towardsdatascience.com】是一家以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家。想了解更多关于疫情冠状病毒的信息,可以点击 这里

Python 和 Oracle 数据库

原文:https://towardsdatascience.com/python-and-oracle-database-c7b5d4d7fa4c?source=collection_archive---------10-----------------------

任何数据科学家都不能忽视这种组合

布鲁斯·马斯在 Unsplash 上的照片

在学习数据科学的同时,大部分时间我们使用的是 Excel,CSV 格式的开源数据。然而,现实世界的数据科学项目涉及从数据库中访问数据。如果需要存储和访问数据,就需要数据库。现代数据库的两种主要类型是关系数据库(RDBMS)和非关系数据库(也称为 NoSQL 数据库)。

RDBMS 数据库可以很好地处理存储在行和列中的数据。一致性和速度是 RDBMS 数据库的最大优势。

在本文中,我将带您了解最常用的 RDBMS 数据库——Oracle 数据库,并解释如何在 Oracle 数据库上使用 Python 应用程序的神圣组合。

连接策略

作者图片

数据库连接是应用程序和 oracle 数据库机之间的物理通信路径。一旦应用程序建立了数据库连接,该会话将从用户通过数据库验证开始一直持续到用户断开或退出数据库应用程序。

Python 有一个用于连接 Oracle 数据库的内置库 cx_Oracle。

我最喜欢 cx_Oracle 的一个特性是它为诊断任何与连接或数据访问相关的问题提供了透明性。下图显示了应用程序和数据库连接和操作的不同阶段的不同错误代码。

作者图片

下面的代码片段显示了如何使用 cx_Oracle 库连接 Oracle 数据库。用您的数据库详细信息替换下面代码中的 userid、密码、主机、端口和服务名。

除了直接在 python 程序中输入数据库登录详细信息,它还可以存储在 python 文件中,并可以像下面这样导入到程序中。

这里,oracbledbconnect 是存储数据库连接详细信息的文件的名称。

作者图片

连接池

在 python 应用程序和 Oracle 数据库之间设计一个合理的连接策略至关重要。在数据密集型应用程序中,单个独立连接可能不够,它可能需要一个连接池。

连接池是到 Oracle 数据库的连接的缓存。

在运行时,应用程序从池中请求一个连接。如果池包含可以满足请求的连接,那么它将连接返回给应用程序。应用程序使用连接在数据库上执行工作,然后将连接返回到池。然后,释放的连接可用于下一个连接请求。

下面的代码片段显示了如何创建连接池。

这段代码将在开始时创建五个连接会话,并将连接会话增加到 15 个。

Python 和 SQL

SQL 是基础,任何从事数据相关专业的人都必须掌握。

使用 cx_Oracle 在 Oracle 数据库上运行 SQL 一点也不困难。只需在连接对象上打开一个光标,执行 SQL,然后关闭连接。

下面的代码片段显示了如何连接到数据库,从一个表中选择所有记录,然后打印表中第一行第三列的记录。

Python 和 PLSQL

PLSQL 是 SQL 的过程扩展。可以在一个 PLSQL 程序中一起编写多个 SQL 语句,而不是编写如上所示的单个 SQL 语句,并且可以通过数据库连接游标中的 callfunc 方法在 Python 应用程序中调用该程序,如以下代码片段所示。

大型物体

数据以行和列的形式存储在 Oracle 数据库中。如果有些数据不能用行列格式表示,例如。文档、图像、视频,它不能直接存储在 Oracle 数据库中。

大型文档、图像等数据。在 Oracle 数据库中被称为大型对象。Cx_Oracle 有 CLOB、BLOB 之类的方法来处理大型对象。

下面的代码片段显示了如何在 Oracle 数据库表字段中存储图像。

系统综合

数据科学和机器学习包括从不同的来源获取数据。公共数据、网络废弃、来自服务提供商的文件等。使用 cx_Oracle 和 sqlalchemy 库,可以在 Oracle 数据库表中使用不同种类的数据。

下面的代码片段显示了如何将特定目录中所有文件的数据消耗到 oracle 数据库表中。

结论:

几乎每个大型企业都使用 Oracle、MySQL、IBM DB2 等关系数据库来存储业务关键数据。虽然 SQL 是处理大多数关系数据库的有效机制,并且 SQL 的声明式设计使其易于学习和使用,但在开发多样化的应用程序时,它的能力是有限的。这就是 Python 和 SQL 的结合大放异彩之处。作为一门数据科学,你不能忽视使用 Oracle 数据库学习 Python 的重要性。

参考

[## Python+ SQL + Oracle:集成 Python、SQL 和 Oracle

我是桑鲁沙的桑杰!我们是领先的信息技术教育提供商:数据集成和…

www.sanrushaacademy.com](https://www.sanrushaacademy.com/p/pythonsqloracle)

Python 与世界文学:使用 BeautifulSoup 的初级网络抓取

原文:https://towardsdatascience.com/python-and-world-literature-elementary-web-scraping-with-beautifulsoup-a43daaf46ab?source=collection_archive---------53-----------------------

数据科学提示

数据挖掘课程 101

Unsplash 上由 Daiga Ellaby 拍摄的照片

每一位新的数据科学家都希望创建壮观的可视化效果,构建渐进的预测模型,从数据中获得惊人的洞察力。好吧,这些东西很吸引人,也很漂亮。但有时人们会在每次分析过程开始时忘记很多“脏”工作。而且这还不是数据清理阶段。

在你开始处理数据之前,你需要…数据!

是的,认为数据分析从数据集清理开始是一个常见的错误,因为它指的是您已经拥有数据的事实。有人可能会相信你总是会神奇地从空气中获得数据。但是数据搜集、收集、挖掘和收集是你需要不断提高的技能。您必须能够处理不同的源代码、格式,有时甚至是语言,而这个事实假设您有足够的技能。基本技能之一是网络抓取——从网站和网络应用程序中加载数据。

当然,蜘蛛和爬虫的创作有很多技巧和方法。今天我想从最原始但非常有效的工具开始— BeautifulSoap parser 。这是一个非常强大的 HTML 解析器,结合适当的请求逻辑,可以自动完成数据收集过程。所以,不再多言——让我们开始编码吧。

准备会话

我将重复文章的第一个想法:使用您需要的数据…数据!所以,我们需要加载一些内容。我想创建自己的数据集用于进一步分析,它是献给诺贝尔奖的。起点是获奖者的名单,我选择了文学类别来工作。我想保持简单,所以我将使用适当的维基百科页面。是的,它并不完美,但仍然是一个很好的起点,因为它有很多交叉链接,我将使用这些链接来获得额外的信息。

但是首先我们应该为请求准备引擎。我创建了一个简单的会话(因为我想保持与同一台主机的稳定连接)和一个简单的适配器(用于超时或网络切换的情况)。

您可以在请求库页面上了解其他设置。这很简单,让我们继续。

获取内容

这里仍然没有什么有趣的东西:只需加载页面并创建适当的BeautifulSoup parser:

现在我们为下一步做准备,这包括一些探索。

找到信息

这听起来可能很奇怪,但是在我们强制脚本自动搜索信息之前,我们应该手动找到它。而且不,这和文章的目的并不矛盾!我们必须研究数据,探索其内部结构,并将这些知识应用于 scrapper 的创建。换句话说,我们应该为 scrapper 找到一些定向器来解析想要的 HTML-tag。我们可以在页面上看到一个包含数据的大表,但是我们需要挖掘 HTML 代码来查看该表的实际位置。我们不能引用位置,因为更多的表可能会被插入到所需的表之前。出于同样的原因,我们不能从本章开始就查阅行数。但是我们可能依赖于章节名称和不同的标签属性。因此,让我们“找到”带有“桂冠诗人”姓名和id属性的标签,并在它下面找到所需的表。每个 BeautifulSoup 标签都可以使用find_all()方法来遍历其内容(所有内部标签):

这就是了。根据我们知道的标准维基页面结构,它是标题的子标签。幸运的是,每个被解析的标签都有一个指向parent标签的指针:

tag = laureates_tag.parent

我们使用该信息来查找所需的表。每个 BeautifulSoup 标签不仅有parent指针,还有next_siblingprevious_sibling指针。所以,我们可以走遍“邻居”标签。正如我们在页面代码中看到的,我们的表格就在 found 标题下面。

while tag.name != ‘table’:
    tag = tag.next_sibling
tag.name # <table>

我们准备好解析了!

解析数据

这是棘手的部分。我们看到,该表有许多行,有些行的所有单元格都已填充,但有些行有常见的字符串“Not award”。但这还不是最困难的部分:有些年份有两位获奖者。但是我们配备了一些美丽的乐器:

  • 访问内部标签:tag.internal_tag
  • 检查标签是否有属性:tag.has_attr(‘attr’)
  • 访问属性:tag[‘attr’]
  • 从标签中获取文本:tag.text

还有很多其他的,你可以在文档中找到

主要思想是遍历每一行,用<tr>标记表示,并获取所有单元格,用<td>标记表示。由于表可能非常大,我们可能不想一次复制和遍历它的所有行。不过,BeautifulSoup 为我们提供了所选标签的所有内部标签的tag.children访问器生成器:

你可以在我的 GitHub 上的完整代码中查看解析函数本身。其实是纯解析逻辑,应该包括一些异常情况。所以,经过一些尝试,我们收集了数据。但对我们来说还不够!

附加数据

除了我们需要的数据,我们还取消了每个作者个人页面的链接。我们将使用这些信息来构建刮板的下一部分。实际上,这是爬行器的最基本层次,因为我们将重用废弃的链接到新页面。

我们有很多行,当然,我们不会检查每一行的每一页。因此,我们将依赖于这样的假设,即每个作者的页面都有传记元素。该元素是我们的目标,因为它包含大量附加数据:

再来一个循环,再来一个解析函数:数据集就准备好了!

然而,这只是长期数据分析过程的第一步。数据是原始的,需要大量清理。但是,这是一个非常不同的故事。

一如既往(老读者已经知道了,新读者——你的乐趣),这里是我的 GitHub 工作示例的链接。

[## 中级/中等 _jupyter_notes

github.com](https://github.com/Midvel/medium_jupyter_notes/blob/master/bs_scrapping/bs-scrapping.ipynb)

此外,由于下一个合乎逻辑的步骤是数据清理,请确保您没有错过我关于丢失数据处理的文章:

[## 每个数据科学家都应该知道的获取缺失值的 7 个习惯用法

你应该把命令自动化

towardsdatascience.com](/7-idioms-to-acquire-missing-values-every-data-scientist-should-know-2edf4224360c) [## 用 R: 10 日常习惯用法处理缺失数据

你应该把命令自动化

towardsdatascience.com](/handle-missing-data-with-r-10-daily-used-idioms-13d849d01690)

Python args 和 * kwargs 数据科学版

原文:https://towardsdatascience.com/python-args-and-kwargs-data-science-edition-978e16c7c2fc?source=collection_archive---------21-----------------------

使用参数和关键字参数使您的代码更加优雅

如果您在查看函数定义后偶然发现了*args 和**kwargs,并且想知道它们到底是什么,那么您就在正确的地方。今天,我们将浏览这两者,并展示它们在一般机器学习任务中的用例。

照片由 Aaron BurdenUnsplash

args 和kwargs 都允许将多个参数(因此是 args)和关键字参数(因此是 kwargs)传递给一个函数。我们稍后将对此进行更详细的探讨。

理想的读者是熟悉 Python 编程语言基础并对数据科学感兴趣的人。第二部分是可选的,因为文章的前三分之二只围绕编程语言本身。

这篇文章的结构如下:

  1. *参数
    • *克瓦查
  2. 在机器学习任务中的实际应用
  3. 结论

说到这里,让我们从第一个概念开始——* args。

*参数

假设您想要声明一个对数字求和的函数。默认情况下,这个函数有一个问题—它只接受固定数量的参数。当然,你可以只使用一个类型为 list 的参数来解决这个问题,这是一个可行的替代方法。让我们探索一下。

下面是对数字求和的常规函数,需要一个 list 类型的参数:

def sum_numbers(numbers):
   the_sum = 0
   for number in numbers:
       the_sum += number
 return the_sum

我们可以用它来计算总和:

numbers = [1, 2, 3, 4, 5]
sum_numbers(numbers)**>>> 15**

但是如果你不想使用列表呢?*救援参数:

def sum_numbers(*args):
   the_sum = 0
   for number in args:
       the_sum += number
   return the_sumsum_numbers(1, 2, 3)
**>>> 6**sum_numbers(1, 2, 3, 4, 5)
**>>> 15**

是的,我听到了——这不是最好的用例,因为我们可以用列表来代替。但是我们还有几个例子——第一个是打开

列表解包

解包的思想是解包任何可迭代的对象。单星号*用于解包任何 iterable,双星号仅用于字典**。你很快就会明白它的要点。

假设我们有以下列表:

num_arr = [1, 2, 3, 4, 5]

解包的过程很简单,并且已经包含在我们漂亮的 sum_numbers() 函数中:

print(*num_arr)**>>> 1 2 3 4 5**

一分钟左右,我们将讨论字典解包——现在,让我们用列表连接来包装这一部分。

列表连接

*args 的另一个有用的方面是列表连接。假设我们有两个列表:

nums1 = [1, 2, 3]
nums2 = [4, 5, 6]

我们如何将它们连接成一个列表呢?如果您的答案是沿着遍历这两个列表并将值存储到第三个列表的路线,那么您没有错(本质上),但是有一个更容易和更优雅的选择。看一下下面的代码:

nums = [*nums1, *nums2]
nums**>>> [1, 2, 3, 4, 5, 6]**

这就是它的简单之处。让我们继续讨论**kwargs,它更适用于您的日常数据科学任务。

* *克瓦查

如前所述,**kwargs 用于打开字典。事不宜迟,让我们看看如何使用它们。

对于这个简单的例子,假设您想要将 3 个数字相乘,但是这些数字来自于某个外部源,并且被存储为键-值对。键总是相同的(很明显),但是值会改变。

下面是你超级复杂的后端代码:

def multiply(a, b, c):
    return a * b * c

这是你得到的数据:

d = {‘a’: 3, ‘b’: 2, ‘c’: 5}

现在,人们可以采取一种天真的方法,做这样的事情:

multiply(a=d[‘a’], b=d[‘b’], c=d[‘c’])**>>> 30**

但是一如既往,有一个更简单的解决方案。让我们花点时间来欣赏下面这段代码的美妙之处:

multiply(**d)**>>> 30**

这是简单、干净和优雅的——正如 Python 的初衷。我敢肯定,一些关于数据科学任务的潜在用例的想法已经浮现在您的脑海中,但在进入正题之前,让我们快速浏览一下字典串联。

词典拼接

这个想法基本上和列表一样。下面我们有两本字典:

d1 = {‘a’: 1, ‘b’: 2}
d2 = {‘c’: 3, ‘d’: 4}

要将它们连接成一个字典,我们所要做的就是:

d = {**d1, **d2}
d**>>> {'a': 1, 'b': 2, 'c': 3, 'd': 4}**

你应该知道的唯一问题是密钥复制。如果在两个或更多字典中有相同的关键字,则在连接时使用梯形的值。

现在是你一直在等待的部分——日常机器学习任务中的一个具体例子。

在机器学习任务中的实际应用

按照承诺,我们将使用kwargs 来模拟模型训练的过程。让我们想象以下场景——你已经收集并准备好数据,现在想要做一些回归任务——让我们用随机森林**算法来说。

下面是您的导入和初始化:

from sklearn.ensemble import RandomForestRegressorrf = RandomForestRegressor()

由于您不知道超参数的最佳值,您决定进行网格搜索。我们在这里不会这样做,但是在执行之后,您将在 best_params_ 属性中拥有最佳参数。下面的字典模仿它:

best_params = {
   ‘bootstrap’: True,
   ‘criterion’: ‘mse’,
   ‘max_depth’: 100,
   ‘min_samples_leaf’: 2,
   ‘n_estimators’: 400
}

这里最简单的方法是在另一个随机森林初始化中重写参数名和值。

我们比这聪明。我们知道**kwargs 以及如何使用它们来解包字典,因此我们可以执行以下操作:

rf = RandomForestRegressor(**best_params)

你看到那有多优雅了吗?

不仅如此,您还减少了在其他项目中可能出现错误的机会,以防您只是复制粘贴代码而忘记更改值。

故事到此结束——至少今天是这样。我们已经讲了很多,所以让我们快速回顾一下。

结论

作为一名数据科学家,知道自己选择的编程语言能提供什么是一个不错的奖励。本文涵盖的例子并不具有开创性,但是我们确信它们将帮助您减少代码量,或者使代码看起来更优雅——或者两者兼而有之。

感谢你花几分钟时间阅读,直到最后。和往常一样,请在下面的评论区留下你的想法。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@radecicdario/membership)

Python + Azure Cosmos DB

原文:https://towardsdatascience.com/python-azure-cosmos-db-f212c9a8a0e6?source=collection_archive---------6-----------------------

创建数据集和容器。查询数据。用 Python 探索 Cosmos DB。

额外收获:Azure CLI 命令。

布兰登·肖在 Unsplash 上的照片

Azure Cosmos DB 是什么?

Azure Cosmos DB 是一个全球分布式、多模型的数据库服务,具有弹性可伸缩性和极快的速度。事实上,它是全球分布的,这意味着它是数据需要靠近用户的应用程序的优秀解决方案,并且能够针对峰值使用快速扩展。它被作为 web、移动、游戏和 IOT 应用程序的解决方案进行营销,这些应用程序具有海量输入数据和全球实时即时查询的需求。作为一个例子,它是光晕 5 的社交游戏的数据库!

本文的目标

在本文中,我们将创建一个 Azure Cosmos DB 帐户,并使用 Azure Cosmos Python SDK 创建一个数据库,创建一个容器,用数据填充容器,并使用 SQL API 查询容器。我们将使用的数据来自联合国人类发展指数——国家以下一级指数,因此人类发展指数的前缀是资源。

查看本文的 Github repo,您可以使用 Jupyter 笔记本查看可执行的 python 脚本。

创建一个 Azure Cosmos DB 帐户

使用 Azure 时,将资源放在一个资源组中总是一个好主意。最简单的方法是从 Azure CLI 或云 shell:

首先,使用以下命令登录 Azure CLI:

az login

接下来,使用az Group create命令创建一个名为 HDI-cosmosdb-group 的资源组。

az group create --location eastus \
                --name HDI-cosmosdb-group \
                --subscription MySubscription

az cosmosdb create 命令创建一个名为 hdicosmosdb(必须全小写)的 Cosmos DB。这大约需要 10 分钟才能完成。

az cosmosdb create --name hdicosmosdb \
                   --resource-group HDI-cosmosdb-group \
                   --locations regionName=eastus \
                   --subscription MySubscription

完成后,您将在新创建的资源组中看到一个 Cosmos DB 资源。

现在已经创建了 Cosmos DB 帐户,我们需要 URI 端点和主键来与我们的帐户进行交互。你可以找到你的 URI 和访问密钥,方法是进入你的 Cosmos DB 账户,在左边向下滚动找到设置>>密钥。将 URI 和主键复制到安全文件中。

自该屏幕截图以来,新密钥已重新生成。

设置 Python 环境

将我们需要的两个包安装到您的 python 环境中。

pip install azure-cosmos
pip install pandas

导入包并初始化 Cosmos 客户机

现在,从 azure-cosmos-python github 示例和微软官方文档中获取技巧,我们将开始使用 python 与我们的 Cosmos DB 进行交互。我们将从导入必要的包和创建 Cosmos 客户机开始。通过用我们的 URI 端点和访问密钥初始化 Cosmos 客户端,我们将能够使用 azure-cosmos API 与我们的 Cosmos DB 帐户进行交互。

创建数据库

使用初始化为我们的帐户的客户机,创建一个 Cosmos DB 数据库。这个数据库将存放容器,容器存放物品。项目是组成数据库的单个文档或记录/行。

创建一个容器

容器,也称为集合,存放构成数据库记录的项目(文档)。分区键路径('/country ')是容器的一个属性,Cosmos DB 将使用它在后台对数据集进行分组和分区。这篇 C#Corner 文章很好地解释了如何使用分区键按“部门”对记录进行分组在我们的数据集中,列“country”将用于对分区中的记录进行分组,分区由记录的“country”值定义。

下载并准备要上传的数据

现在,下载人类发展指数——使用熊猫的地方指数。Azure Cosmos DB 需要一列来标识每个记录/行的唯一 id。我们将基于熊猫数据帧的索引创建一个列“id”。此外,由于每一行在 Cosmos DB 中都以 json 文档的形式结束,我们需要将“id”列转换为 string 类型。

将数据上传到宇宙数据库

这里,我们将迭代熊猫数据帧的行,并为每一行创建一个字典。该字典已经为 json 提取进行了良好的格式化,这是通过 json.dumps()完成的。 当 for 循环执行时,每一行都被写入 Cosmos DB。对于一个 45,000 条记录的数据集,这大约需要 15 分钟。

查询宇宙数据库

既然我们的数据集已经植入了数据,让我们运行一个测试查询。

我们想要查询阿富汗国家的所有国家级数据。

我们所有的努力都得到了回报。 。head() 方法显示数据已经成功返回,并且在一个 pandas DataFrame 中。

让我们用三个主要指数——健康、收入和教育指数——的折线图来庆祝一下。

感谢你远道而来!Azure Cosmos DB 非常容易设置,它面向 json 的记录对于 python 和 pandas 来说轻而易举。

Python 基础知识-2:使用列表、元组和字典

原文:https://towardsdatascience.com/python-basics-2-working-with-list-tuples-dictionaries-871c6c01bb51?source=collection_archive---------36-----------------------

机器学习 100 天的第 2 天

照片由埃米尔·佩龙Unsplash 上拍摄

内容

  • 使用列表
  • 列表理解
  • 高级列表操作:切片列表,遍历切片列表,复制列表
  • 元组
  • 基本元组操作:修改元组,遍历所有元组值
  • 字典
  • 基本的字典操作:修改字典,从字典中删除键值
  • 通过字典循环
  • 嵌套词典

使用列表

制作号码列表

在 python 中,我们可以使用range()函数创建一系列数字。让我们来看看如何使用range()函数创建列表。

遍历列表

在数据分析中,您经常需要遍历列表中的每一项。让我们看一看。

range()功能同 for 循环

我们也可以在 for 循环中使用range()函数——有时需要循环遍历一系列数字。让我们来看看代码。

带列表的基本统计

可以用min()max()sum()等列表进行简单的统计。

列表理解

列表理解是一种生成列表的高级方法。列表理解允许你组合 for 循环来创建一个列表。假设您必须创建一个包含 1 到 10 的立方体的列表。首先,让我们看看如何在不理解列表的情况下做到这一点。

现在让我们用列表理解法列出同样的列表。

预先列表操作

切片列表

要对列表进行切片,必须传递起始索引和最后一个元素索引。像range()函数一样,slice 也在一个元素前停止。如果你想要元素从开始到第 5 个元素,你必须传递 0(第一个元素索引)到 5(第六个元素索引)。让我们来看看如何用代码实现它。

遍历切片列表

之前,我们已经看到了如何循环遍历列表以及如何对列表进行切片。甚至我们可以循环遍历切片列表。让我们看看如何做到这一点。

复制列表

在进行数据分析时,可能需要对现有列表和现有列表的副本进行操作。让我们看看如何复制列表。

现在我们有两个列表,我们可以根据需要修改它们。让我们应用我们在之前的博客中学到的基本操作。

元组

和列表一样,元组也是 python 中的集合类型。然而,元组是不可变的,这意味着不可变列表的值不能改变。在 python 中,元组使用括号“(”。让我们来看看如何在 python 中定义元组。

基本元组操作

修改元组

我们知道,元组是不可变的列表类型,这意味着它不能被修改。但是,我们可以覆盖元组,这意味着我们可以完全改变元组值。

遍历所有元组值

在 python 中,我们可以像处理列表一样遍历元组。

与列表相比,元组是简单的数据结构。当程序员希望存储一些在整个程序中不能改变的值时,通常会用到它们。

字典

在 python 中,字典是键和值对的集合。在字典中,每个键都与值相关联。要访问任何值,我们必须使用与值相关联的键。我们可以在字典中使用任何数据对象作为键或值。让我们创建一个简单的字典。

基本字典操作

修改字典

像列表数据收集方法一样,我们也可以修改字典。让我们来看看代码。

从字典中删除键值

我们可以从字典中删除不需要的信息。

通过字典循环

像列表和元组一样,我们可以使用循环来检查字典的每个键和值。

在字典中,只能循环访问键或值。让我们来看看代码。

嵌套词典

在 python 中,可以在列表中存储字典,反之亦然。首先,让我们看看如何创建字典列表。

现在让我们来看看如何在字典中创建列表。

甚至你可以在字典里储存一本字典。

今天我们从 python 速成教程的书中学习了 Python 的基础知识(第 4 章和第 6 章)。我参加这个 100 天机器学习挑战的目标是从零开始学习机器学习,并帮助其他想开始机器学习之旅的人。很多概念我都知道,但我是从零开始,帮助机器学习社区的初学者,修正概念。

感谢阅读。

如果你喜欢我的工作并想支持我,我会非常感谢你在我的社交媒体频道上关注我:

如果你错过了我的前一部分系列。

我希望你会喜欢我的其他文章。

初学者的 Python 基础

原文:https://towardsdatascience.com/python-basics-for-beginners-5fac8dd4fe43?source=collection_archive---------37-----------------------

Python 简介

像素上的 Kaboompics 拍摄的照片

Python 是一种高级解释编程语言,用于各种任务,如数据分析、机器学习和 web 开发。在这篇文章中,我们将介绍 python 中的一些基本概念。具体来说,我们将讨论如何定义列表和字典,迭代列表和字典,以及定义函数。

我们开始吧!

python 列表是一种重要的 python 数据结构。python 列表只是对象的集合。对象可以是字符串、整数、浮点数等..一个例子是姓名列表。为了在 python 中定义名称列表,我们执行以下操作:

names = ['Bob', 'Sarah', 'Ted', 'Nicole']
print("Names: ", names)

名称列表包含字符串对象。我们还可以定义一个浮动对象列表,比如每个人的身高(厘米):

heights = [180.0, 160.0, 190.0, 150.0]
print("Heights: ", heights)

现在假设我们需要一种方法来将名字映射到以厘米为单位的高度值。例如,假设 Bob 的身高是 180 cm,有没有一种方法可以可靠地得到他的身高。我们可以使用字典来实现这一点。为了构建这个字典,我们做了以下工作:

names_height = {'Bob':180.0, 'Sarah':160.0, 'Ted':190.0, 'Nicole':150.0}
print("Names & Heights: ", names_height)

现在,我们可以通过以下方式获得 Bob 的身高:

print("Bob's Height (cm): ", names_height['Bob'])

如果我们想要妮可的身高:

print("Nicole's Height (cm): ", names_height['Nicole'])

我们还可以使用“zip()”和“dict()”方法构建相同的字典:

names_height_2 = dict(zip(names, heights))
print("Names & Heights using dict() & zip(): ", names_height_2)

现在假设我们想将高度列表中的高度转换为英尺。为了把厘米换算成英尺,我们除以 30.48。我们可以在 for 循环中这样做:

heights_feet = [] #initialize empty list
for height in heights:
    heights_feet.append(height/30.48)
print("Height in Feet: ", heights_feet)

我们也可以使用叫做列表理解的东西来完成同样的任务:

heights_feet_2 = [height/30.48 for height in heights]
print("Height in feet list comprehension: ", heights_feet_2)

类似地,字典理解可以用于构造具有以英尺为单位的姓名和高度的字典:

names_height_feet = {name:height/30.48 for name, height in names_height.items()}
print("Names & Heights in Feet Dictionary Comprehension: ", names_height_feet)

最后,我们可以定义一个函数,它获取一个包含姓名/身高(cm)对的字典,并打印一个包含姓名/身高(ft)对的新字典:

def convert_to_feet(height_cm_dict):
   height_feet_dict = {}
   for key, value in height_cm_dict.items():
       height_feet_dict[key] = value/30.48
   print("Names & Heights in Feet Function Conversion: ", height_feet_dict)

让我们用包含厘米高度的字典调用我们的函数:

convert_to_feet(names_height)

我就讲到这里,但是您可以自己随意摆弄代码。

结论

总之,在这篇文章中,我们讨论了如何在 python 中定义列表和字典。我们讨论了如何使用“dict()”和“zip()”方法从列表中构造字典。我们还展示了如何使用 for 循环、列表的列表理解和字典的字典理解来迭代这些对象。最后,我们展示了如何定义一个函数,将字典中的厘米高度值转换为英尺,并将新值存储在一个单独的字典中。这篇文章的代码可以在 GitHub 上找到。我希望你觉得这篇文章有用/有趣。感谢您的阅读!

2021 年必读的 Python 书籍

原文:https://towardsdatascience.com/python-books-you-must-read-in-2020-a0fc33798bb?source=collection_archive---------2-----------------------

看看吧,你为什么要读它们?

照片由来自佩克斯克里斯蒂娜·莫里洛拍摄

Python 是程序员需要多大自由的一个实验。太多的自由,没人能读懂别人的代码;太少,表现力受到威胁。

吉多·范·罗苏姆

Python顶级编程语言 之一,适用于多种多样的任务和领域。Python 的用户友好性、高级特性、对简单性的强调和增强的代码可读性使它成为全世界许多开发人员的首选。如果这还不能让你接受 Python,我相信超过 25.5 万个第三方包的详尽的生态系统会让你接受。

类似这些的特性让 Python 的需求无处不在,无论是应用开发、 数据科学、 人工智能 还是其他任何行业。这篇文章背后的目标是收集一些最好的 Python 书籍,帮助您获得关于这种令人惊叹的编程语言的知识和信心。

根据 Stackoverflow 的说法,python 是最受欢迎的语言,这意味着大多数开发人员都使用 Python。

[## 2020 年大一新生热门 Python 面试问答

这里列出了大一新生最常被问到的 python 面试问题和答案,涵盖了核心…

blog.digitalogy.co](https://blog.digitalogy.co/python-interview-questions-and-answers-for-freshers/)

Python 书籍

书籍很可能是几乎任何主题的顶级信息来源之一,在这一部分,我们收集了十多本顶级书籍来帮助你熟悉和获得一些关于 Python 的实用知识。这些书中有些涵盖了关于编程语言的全面知识,而有些则在方面非常优秀,给你实际操作的体验

不管你以前有没有 Python 或任何编程语言的经验,我们相信你会从这些书中为你的下一个项目找到一些非常有用的技巧。

[## 给 Python 开发者的 10 个很酷的 Python 项目想法

您可以使用 Python 构建的有趣想法和项目列表

towardsdatascience.com](/10-cool-python-project-ideas-for-python-developers-7953047e203)

免责声明: 那些附属链接仅供参考。

1. Python 速成班

作者:埃里克·马特斯

出版社 —无淀粉出版社

难度等级:初学者

在这里获得两本书——亚马逊亚马逊

《Python 速成教程》一书的封面

顾名思义,作者写这本书是为了给几乎没有编程经验的读者提供一个快速速成班。作者已经把所有的介绍性概念做得对初学者来说像 ABC 一样简单,这样他们就可以开始在有趣的项目中运用他们的知识。这本书的介绍性质也使它成为学者的合适选择。

这本分为两部分的书在第一部分涵盖了编程介绍,而在第二部分,它采用了项目驱动的方法,鼓励读者完成任意或所有三个编程项目。这些项目包括编码一个 2D 游戏,创建一个数据可视化程序,以及最后一个用于笔记的在线学习日志。

2.学习 Python

作者:马克·卢茨

出版商 —奥莱利传媒

难度等级:初学者

在这里获取图书——亚马逊

《学习 Python》一书的封面

在 Python 的思维方式中,显式比隐式好,简单比复杂好。
――马克·卢茨

学习 Python 涵盖了编程语言的所有基础知识,旨在为寻求 Python深度介绍的初学者提供一站式解决方案。与上一本书一样,本书也是由两部分组成的,作者马克·卢茨试图在这一部分用 Python 创建一个坚实的基础,而另一部分则更多地关注于真实的例子和更好的实际编程暴露的情况

本书最新版本涵盖了 Python v3.3 及其所有最新改进连同 老版本 v2.7 。顺便说一句,如果你对编程一窍不通,给这本书补充一些介绍性的参考资料是个好主意。

[## 2020 年你必须使用的最好的 Python IDEs 和代码编辑器

具有显著特性的顶级 Python IDEs 和代码编辑器

towardsdatascience.com](/best-python-ides-and-code-editors-you-must-use-in-2020-2303a53db24)

3.Python 技巧:令人敬畏的 Python 特性自助餐

作者:丹·巴德

出版人 —丹·巴德(dbader.org)

难度等级:初学者

在这里获取图书——亚马逊

《Python 技巧:令人敬畏的 Python 特性自助餐》一书的封面

"应该有一种——最好只有一种——显而易见的方法来做这件事。"丹·巴德

顾名思义,Python Tricks 汇集了一系列方便的特性、技巧和诀窍,让你高效地使用 Python。

用作者的话来说——“一开始是一个有趣的 twitter 实验,后来变成了一系列值得注意和有用的技巧,并附有一个清晰的代码示例,帮助数百名 Python 开发人员理解了 Python 各个方面背后的思想。”

这本书涵盖了 Python 中各种主题的大量技巧,并且以一种解释清楚的风格呈现,但是要充分利用这本书,您仍然需要有很强的 Python 基础。

4.艰难地学习 Python

作者:泽德·肖

出版商 —艾迪生-卫斯理

难度等级:初学者

在这里获取图书——亚马逊

《艰难地学习 Python》一书的封面

"慢慢来,不要伤到你的大脑。"

如果你被标题中的吓倒了,不要害怕。那只是作者使用说明的方式,让你彻底的通读章节,练习你所学的东西。

把标题放在一边,作者已经完成了一项惊人的工作,以一种更加初学者友好的速度呈现 Python 的基本概念,为你准备复杂的主题。这本书还包括大量的教学视频和练习来增强你的 Python 知识。如果你想知道,是的,这本书已经更新了一个新版本,支持 Python 3

5.用 Python 自动化枯燥的东西

****作者:阿尔·斯威加特

出版社 —无淀粉出版社

****难度等级:初学者

****在这里获取图书——亚马逊

“用 Python 自动化枯燥的东西”这本书的封面

据作者-

不要把时间花在一只训练有素的猴子能做的工作上。即使你从来没有写过一行代码,你也可以让你的电脑做一些繁重的工作。了解如何用 Python 自动化枯燥的东西。

标题说明了一切。时不时地,你一定会遇到一个无聊或重复的任务,让你说“不要再这样了。”本书想要消除的正是这些时刻。作者在本书中介绍了编程语言的必要基础知识,以帮助您创建一些漂亮的 Python 片段,这些片段可以在几秒钟内而不是几小时内自动完成一项简单但枯燥的任务。****

虽然这本书对于那些想快速解决无聊任务的人来说是个奇迹,但没有编程背景,它并没有全面涵盖 Python 的每个方面。对于创建方便的一次性代码来说已经足够了,但是对于一个完整的介绍来说还不够。

6.用于数据分析的 Python****

****作者:韦斯·麦金尼

出版商 —奥赖利

****难度等级:中级

****在这里获取图书——亚马逊

《用于数据分析的 Python》一书的封面

Python 可以用于各种任务,其中之一就是数据分析。如果你经常发现自己忙于分析和操作结构化数据或者只是热衷于了解 Python 对于数据分析任务的效率,你可能会发现这本书很有用。

作者以一种非常全面的方式解释了处理数据的基本原理,同时也触及了科学计算的话题。Python for Data Analysis 还涵盖了一些最流行的用于数据分析的库,比如【NumPy】熊猫matplotlibIPython和** SciPy**********

“无为而为;不费力地工作。把小的看成大的,把少的看成多的。在困难还容易的时候去面对它;通过一系列小行动完成大任务。——老子”
——韦斯·麦金尼

**** [## 10 家使用 Python 的世界级公司

Python 正被 IT 界的一些巨头积极使用

towardsdatascience.com](/10-world-class-companies-using-python-26cde24919a8)

7.Python 机器学习简介

作者:安德里亚斯·穆勒和萨拉·圭多

出版商 —奥赖利

难度等级:中级

在这里获取图书——亚马逊

《用 Python 进行机器学习入门》一书的封面

机器学习的发展速度令人着迷。为了能够充分利用这项技术,Python 是胶合语言的首选。针对有志于寻找现实世界机器学习问题解决方案的机器学习专业人士,这本书不需要任何机器学习经验。

这本书没有深入算法和模型背后的数学,而是采取了一种更温和的方法,解释了背景和它们的重要性。尽管它确实需要一些使用 Python 实现书中所涉及的大量算法和模型的知识,如scikit-learn、NumPy 和 matplotlib。****

8. Python 数据科学手册

作者:杰克·范德普拉斯

出版商 —奥莱利传媒

****难度等级:中级

****在这里获取图书——亚马逊

****Git Hub—https://github.com/jakevdp/PythonDataScienceHandbook

《Python 数据科学手册》的封面

最近,数据科学越来越成为各个领域的必备技能,因为它提供的好处是无价的。本手册的作者更加强调将数据科学作为一种技能来学习,而不是一个新的知识领域,因为它可以证明在将技能应用于手头的问题时是有利的。

本书的内容已经被组织成由 Python 提供的五个不同的库,用于广泛覆盖,即 IPython、NumPy、Pandas、Matplotlib、Scikit-Learn 。该手册确实需要对 Python 有一定程度的精通,才能按照作者的意图阅读,并且不适合初学者。****

9. Head First Python:一个对大脑友好的指南

****作者:保罗·巴里

出版商 —奥莱利传媒

****难度等级:中级

****在这里获取图书——亚马逊

“Head First Python:对大脑友好的指南”一书的封面

“代码读的比写的多。这个"
――保罗·巴里

虽然这本书没有详细介绍编程语言及其整体,但它仍然设法以一种更实用和有趣的方式教你 Python。这本书与众不同的是作者用来与读者建立联系的有趣和随意的风格,更重要的是滑稽地使用图片** 来保持学习过程的直观性。**

对于那些刚刚开始学习 Python 或任何其他编程语言的人来说,你可能很难理解所涉及的主题。如果你知道编程的基本知识,那就来吧。

10.流畅的 Python

****作者:拉马尔霍

出版商 —奥莱利传媒

****难度等级:专家

****在这里获取图书——亚马逊

《流畅的 Python》这本书的封面

当有效使用时,Python 可以是一种非常通用和强大的编程语言,这一动机是《流利的 Python》这本书的唯一驱动因素。很明显,学习 Python 和熟练掌握 Python 是两码事。大多数开发人员通常会用 Python 实现他们想要的东西,但这是以牺牲其全部潜力为代价的。

作者强调了一些很少使用的特性和技术,以使充分利用 Python 成为可能。如果你最近开始学习 Python,这本书可能不适合你,因为你可能会觉得很难理解。

11.有效的 Python

****作者:布雷特·斯拉特金

出版商 —艾迪生-卫斯理

****难度等级:专家

****在此获取图书——亚马逊

《有效的 Python》一书的封面

Python 是一种编程语言,它高度强调创建清晰且可读性极强的代码,但仍有一些情况下无法实现这一点。这就是《有效的 Python》这本书的由来。作者涵盖了一些常见错误,并提供了宝贵的见解和实践如何首先避免它们,以编写更干净、可重用和更有效的 Python 代码。如果你一直在努力寻找优化代码的方法,这本书可能是适合你的。

12.Python 食谱

作者:大卫·比兹利&布莱恩·k·琼斯

出版商 —奥赖利媒体

****难度等级:专家

****在这里获取图书——亚马逊

“Python 烹饪书”的封面

Python 有一个 优秀的社区 ,这本书从社区面临的许多独特挑战中获取灵感,这些挑战被称为 Python 食谱中的食谱。食谱附有相关的例子和详细的背景研究来自一些最有见地的社区成员。

为了让这一点非常清楚,作者将这本书的目标读者定为有经验的 Python 开发人员,他们希望加强对 Python 中各种现代技术的理解。建议初学者在开始阅读 Python 指南之前,先阅读一些关于 Python 入门部分的内容。****

更多的 Python 书籍可以阅读—

  • Python 袖珍参考
  • Python 机器学习
  • 使用 Python 进行深度学习
  • Python 编程:计算机科学导论
  • 用 Python 进行自然语言处理
  • 一言以蔽之,Python
  • 思考 Python:如何像计算机科学家一样思考
  • Django 初学者:用 Python 和 Django 构建网站

结论

Python 是一种优雅而强大的编程语言,如果使用得当,它可以创造奇迹。这篇文章中涉及的书籍应该为您提供足够的知识,让您开始使用 Python,并提供一些额外的技巧和诀窍,以编写清晰、优化且运行良好的代码。总结一下,如果你热衷于从头开始学习 Python 或者只是想温习一下,我们强烈推荐你阅读这些书籍。

注: 为了消除各种各样的问题,我想提醒你一个事实,这篇文章仅代表我想分享的个人观点,你有权不同意它。

更多有趣的阅读—

我希望这篇文章对你有用!以下是一些有趣的读物,希望你也喜欢

** [## 面向所有人的顶级谷歌人工智能工具

使用谷歌人工智能中心将想法变为现实

towardsdatascience.com](/top-google-ai-tools-for-everyone-60346ab7e08) [## 2020 年必读的机器学习书籍

看看吧,你为什么要读它们?

towardsdatascience.com](/machine-learning-books-you-must-read-in-2020-d6e0620b34d7) [## 2020 年必读的数据科学书籍

看看吧,你为什么要读它们?

towardsdatascience.com](/data-science-books-you-must-read-in-2020-1f30daace1cb) [## 面向数据科学的顶级 Python 库

面向数据科学的流行 Python 库概述

towardsdatascience.com](/top-python-libraries-for-data-science-c226dc74999b) [## 用于自然语言处理的 Python 库

用于自然语言处理的流行 python 库概述

towardsdatascience.com](/python-libraries-for-natural-language-processing-be0e5a35dd64)

关于作者

克莱尔 D 。在Digitalogy是一个内容制作者和营销人员,这是一个技术采购和定制匹配市场,根据全球各地的特定需求,将人们与预先筛选的&顶尖开发人员和设计师联系起来。在LinkedinTwitterinsta gram**。****

Python 类继承

原文:https://towardsdatascience.com/python-class-inheritance-62fdb33ede47?source=collection_archive---------53-----------------------

Python 继承简介

来源

类和对象构成了 python 编程语言的核心功能。类提供了一种组织属性(数据)和方法(作用于数据的函数)的便捷方式。面向对象编程中的一个重要概念是类继承。继承允许我们定义一个从父类获取所有功能的类,同时添加额外的数据和/或方法。在这篇文章中,我们将定义一个父类和子类,并演示继承的用法。

我们开始吧!

首先,让我们定义一个名为“Spotify_User”的类。该类将包含一个“init()”方法,该方法允许我们初始化用户对象值,如名称、电子邮件和高级用户状态:

class Spotify_User:
    def __init__(self, name, email, premium):
        self.name = name
        self.email = email
        self.premium = premium 

接下来,让我们定义一个允许我们检查用户是否是高级用户的方法:

def isPremium(self):
        if self.premium:
            print("{} is a Premium User".format(self.name))
        else:
            print("{} is not a Premium User".format(self.name))

现在,让我们定义两个“Spotify_User”对象:

user_1 = Spotify_User('Sarah Phillips', 'sphillips@gmail.com', True)
user_2 = Spotify_User('Todd Grant', 'tgrant@gmail.com', False)

我们可以使用“isPremium”方法检查用户是否为“高级用户”:

user_1.isPremium()
user_2.isPremium()

现在我们已经定义了父类,让我们定义一个名为‘Premium _ User’的子类。类名遵循“ChildClass(ParentClass)”结构,其中父类是子类的一个参数。让我们假设 Spotify 有不同的订阅层级。子类构造函数将初始化属性“subscription_tier”:

class Premium_User(Spotify_User):
    def __init__(self, subscription_tier):
        self.subscription_tier = subscription_tier

接下来,我们将使用“super()”方法,该方法允许子类调用父类构造函数:

class Premium_User(Spotify_User):
    def __init__(self, subscription_tier, name, email, premium):
        self.subscription_tier = subscription_tier
        super(Premium_User, self).__init__(name, email, premium)

现在,让我们向‘Premium _ User’类添加一个额外的类方法。此方法将检查实例的“subscription_tier”值,并打印该层可用的内容:

class Premium_User(Spotify_User):
    ...
    def premium_content():
        if self.subscription_tier == 'Tier 1':
            print("Music streaming with no advertisements")
                if self.subscription_tier == 'Tier 2':
            print("Tier 1 content + Live Concert Streaming")

现在,让我们定义一个拥有“第 1 层”订阅的新用户:

user3 = Premium_User('Tier 1', 'Megan Harris', '[mharris@gmail.com](mailto:mharris@gmail.com)', True)

让我们使用父类方法“isPremium”来检查我们的新用户是否是高级用户:

user3.isPremium()

接下来,我们可以使用子类“premium_content”中的方法来查看“第 1 层”订阅者可以获得哪些内容:

user3.premium_content()

我们还可以定义“2 级”订户:

user4 = Premium_User('Tier 2', 'Bill Rogers', '[brogers@gmail.com](mailto:mharris@gmail.com)', True)

并检查可用的内容:

user4.premium_content()

我将在这里停下来,但是您可以随意摆弄代码。

结论

总之,在这篇文章中,我们演示了 python 中父类和子类继承的用法。在我们的例子中,我们能够看到,通过继承,一个子类如何可以获得父类的所有数据和方法,同时向子类添加额外的数据和方法。我希望你觉得这篇文章有用/有趣。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

Python 从头编码:没有任何机器学习库的矩阵乘法!

原文:https://towardsdatascience.com/python-coding-from-scratch-matrix-multiplication-without-any-machine-learning-libraries-463624fe8726?source=collection_archive---------15-----------------------

从零开始了解如何在没有任何机器学习库的情况下实现矩阵乘法!

照片由 Unsplash 上的 Dhru J 拍摄

你曾经想象过在没有任何复杂的令人敬畏的机器学习库的情况下处理机器学习问题吗?

由于这些模块,我们可以在眨眼之间完成某些操作。

为了真正欣赏这些模块的美丽和优雅,让我们在没有任何机器学习库或模块的情况下从头开始编写矩阵乘法代码。虽然这不是一个极其复杂的任务,但这将帮助我们更好地学习核心概念,也理解 NumPy 的意义,它可以在短短几行代码中完成相同的任务。

所以,事不宜迟,让我们动手开始编码吧!

我解决这个问题的方法是从用户那里获取所有的输入。这些是第一和第二矩阵的行数和列数。同样,根据每个矩阵的行数和列数,我们将相应地分别填充备选位置。

在做任何矩阵乘法之前,第一步是检查两个矩阵之间的运算是否实际可行。这可以通过检查第一矩阵的列是否匹配第二矩阵的行的形状来完成。这可以表述为:

→矩阵 1 中的列数=矩阵 2 中的行数

使用这个策略,我们可以制定我们的第一个代码块。这可以如下图所示完成—

好吧,这部分很简单。我们制定了一个计划,只在需要的时候执行矩阵运算。现在,让我们看看如何相应地接收相应行和列的输入。

在继续之前,让我们明确一个我们试图解决的问题。下图代表了我们需要解决的问题。我采用了更简单的 33 和 33 矩阵组合,但我保证这种方法将适用于匹配第一个矩阵的列和第二个矩阵的行的任何复杂问题。

作者截图

下图显示了相应的行数和列数。

既然我们已经制定了我们的问题陈述,让我们从用户那里获取想要的输入,并开始着手解决这个问题。这可以通过下面的代码块来完成:

在这里,我展示了如何遍历行和列来输入第一个矩阵的值。同样,您也可以对第二个矩阵重复这些步骤。完成此步骤后,您的输出应该如下所示:

好了,现在我们已经成功地获取了所有需要的输入。是时候遍历这些值并开始计算它们了。为了阐明矩阵乘法的工作原理,我们将行和它们各自的列相乘。

矩阵的第一个值必须如下:

(1 * 1)+(2 * 4)+(3 * 7)=(1)+(8)+(21)= 30

这可以使用以下代码来完成:

这段代码相应地计算结果,我们得到的最终输出如下:

下图显示了已完成的相同计算。

作者截图

好极了。我们现在已经完成了矩阵的工作。然而,我很好奇这将如何在 numpy 上工作。让我们看一看👀

使用 Numpy:

在仅使用 python 成功地格式化了矩阵乘法的工作之后,我们现在可以看看使用 numpy 模块的类似公式是什么样子的。这可以通过以下方式完成:

Welp!看起来这就是我们要做的一切。

来自剪贴画的 Gif

这几乎没有任何工作,我坐在这里用 Python 编码。嗯!至少我们学到了一些新东西,现在可以欣赏我们使用的机器学习库有多棒了。

照片由安托万·道特里Unsplash 上拍摄

结论:

我们发现,如果不使用现有的令人惊叹的机器学习库,即使是像矩阵乘法这样简单的任务,也需要花费更长的时间来执行,否则只需几行代码就可以完成。

然而,尽管如此,理解核心基础知识和理解这些操作是如何执行的仍然很重要,我们在本文中正是这样做的。在本文中,我们研究了如何在不使用任何库的情况下编写矩阵乘法代码。

如果你想让我做更多这样的“没有机器学习库的 Python 编码”那么请随意提出你希望我在接下来的文章中尝试的更多想法。

你可以通过下面的链接查看我最近的文章:

[## 10+牛逼 Python 编辑器的简明指南,以及如何选择最适合你的编辑器…

帮助您在各种 python 开发环境中进行选择的简明指南

towardsdatascience.com](/a-concise-guide-of-10-awesome-python-editors-and-how-to-choose-which-editor-suits-you-the-best-465c9b232afd) [## 5 个常见的 Python 错误以及如何避免它们!

从初学者到专家,每个人在 python 和机器学习中都容易出现这些错误。

towardsdatascience.com](/5-common-python-errors-and-how-to-avoid-them-63d9afc1a58f)

请随意查看下面的文章系列,这些文章将从头开始涵盖对机器学习的全部掌握。该系列将持续更新,该系列将从头开始涵盖与 python 进行机器学习相关的每个主题和算法。

[## 开始使用 Python 掌握机器学习的旅程

了解精通机器学习的基本要求

towardsdatascience.com](/starting-your-journey-to-master-machine-learning-with-python-d0bd47ebada9) [## 机器学习所需的 Python 基础知识及其库模块

学习 python 数据结构的基础知识,对机器所需的每个库有直观的理解…

towardsdatascience.com](/basics-of-python-and-its-library-modules-required-for-machine-learning-51c9d26026b8)

谢谢大家看完这篇文章,祝大家有美好的一天!

Python 理解及其实现

原文:https://towardsdatascience.com/python-comprehensions-with-implementation-852e17811bac?source=collection_archive---------53-----------------------

列表|词典|集合理解

图片作者:Unsplash.com|王思然

简介:

Python 是一种流行的语言,允许程序员编写优雅、易于编写和阅读的代码,就像普通英语一样。Python 的独特之处在于不同类型的理解。

在 Python 中,有三种理解类型,即。列表、字典和集合。

在这篇博客结束时,你将理解 Python comprehensions 的全部功能,以及如何轻松地使用它的功能。

  1. 列表理解

List: List 是由方括号包围的数据集合,每个元素由逗号分隔。

列表理解:也被方括号包围,但是它包含类似 for 循环&的表达式,或者后跟 if 子句。

示例:

a.创建一个 1 到 100 之间的数字平方列表。

# Without List comprehension
SquaresWithoutComprehension = []
for i in range(1,101):
    SquaresWithoutComprehension.append(i**2)## List Comprehension
SquaresWithComprehension = [i**2 for i in range(1,101)] 

b.列出对条件的理解。

# Suppose we have List consist movie names with released year.MoviesYear = [('Star Wars',2019),('Glass',2020),('The Upside',2018), ('The LEGO Movie 2',2020),('Cold Pursuit',2017),
         ('Hotel Mumbai',2020)]## Problem: Create List of movies released in 2020?Movies_20 = [title for (title, year) in MoviesYear if year == 2020]

c.列表理解-数学应用。

# Suppose we have List of numbers 1 to 10.Numbers = [1,2,3,4,5,6,7,8,9,10]## Problem 1: Perform scalar multiplication i.e multiply each number with 2 and store result into the List.ScalarMultiplication  = [4*X for X in Numbers]### Problem 2: Perform cartesian multiplication between List A and B.A = [1,2,3,4]
B = [10,11,12,13]CartesianProduct = [(a,b) for a in A for b in B]##Output:[(1, 10), (1, 11), (1, 12), (1, 13), (2, 10), (2, 11), (2, 12), (2, 13), (3, 10), (3, 11), (3, 12), (3, 13), (4, 10), (4, 11), (4, 12), (4, 13)]

说明:

上面会产生相同的结果,但是当我们使用列表理解时,代码行减少了,同样的操作只用一行代码就完成了。

2.字典理解

字典:字典是一个无序、可变、索引的集合。用花括号写的 Python 字典,它们有键和值对。

dictionary example = { " IDE ":" JupyterNotebook "," Language": "Python "," Version": 3}

词典理解:词典理解也是一个无序的、可变的、有索引的集合,其中的键值对借助表达式生成。

词典理解示例:

a.创建字典,其中键为字母,值为字母在句子中出现的次数(字典定义)。

# SentenceDictDefination = "A dictionary is a collection which is unordered, changeable and indexed. In Python written with curly brackets, and they have keys and values."## Dictionary comprehensionAlphabetDictionary = {
        key: DictDefination.count(key) for key in DictDefination
                     }

b.词典理解—数学应用

# Problem: Create dictionary where Key as number and Value as cube of key i.e. number.## Dictionary comprehensionNumSquareDictComprehension = {key:key**3 for key in range(1,10)}ORNumSquareDictComprehension = {f"The square of {key} is":key**3 for key in range(1,10)} 

3.设定理解

集合:Python 集合中的唯一的、无序的、可变的元素集合。设置用花括号括起来的元素和用逗号分隔的元素。

SetExample = {'Python ',' Java ',' R'}

集合理解:类似于列表理解,但是由一组唯一的、无序的、可变的元素组成,其中的字典元素包含一个表达式。

集合理解的例子:

a.创建由 1 到 10 之间的数字组成的方块集。

SquareSet = {num**2 for num in range (1,11)}

b.创建列表中可用的唯一元素集。

# Suppose list having duplicate elementsCarBrands = ['BMW','Chevrolet','Bentley','BMW']

## Set comprehension only give unique elements from the above ListCarBrandDict = {Brand for Brand in CarBrands} 

理解的优势:

  • 容易实现。
  • 减少代码行数。
  • 执行速度更快,使用的资源更少。

理解的弊端:

  • 程序中使用更多的理解会增加代码的复杂性。
  • 理解表达工作很复杂。

结论:

如上所述,Python 中有不同类型的理解。上面实现的是基本的例子,理解中使用的表达式可以用来调用函数。最常见的是,列表和字典理解用来简化代码。

希望,这个博客能帮助你了解一些有效且易于使用的 Python 技术。

感谢您的阅读!!

对象、类型和值

原文:https://towardsdatascience.com/python-data-model-part-1-objects-types-and-values-cb9316f57e8?source=collection_archive---------13-----------------------

Python 数据模型

Python 数据模型—第 1 部分

克里斯里德在 Unsplash 上的照片

Python 最好的品质之一就是它的一致性。在使用 Python 一段时间后,您能够开始对新特性做出明智、正确的猜测。****

“Python 数据模型,它描述了 API,您可以使用该 API 使您自己的对象与最惯用的语言特性配合良好。—流畅的 Python,卢西亚诺·拉马尔霍****

**Python 数据模型可以定义为“Python 框架”“Python 设计哲学”。这种语言的开发者已经开发了相当大的文档,乍一看可能有点模糊、吓人或者含糊不清。

然而,简单地说,术语数据模型是不言自明的——它处理 Python 如何在内部组织一切以处理和处理数据,以及其核心设计和哲学的一些高级概念。它讨论了语言本身的基本构造块、构造块的设计/结构以及与它们相关的基本代码块。**

在本章中,我们将讨论对象类型和值

在 Python 中——一切都是对象。每个对象都有一个身份、类型和值

在 Python 中——一切都是对象。每个对象都有一个标识,一个类型,一个。那么,身份类型、值有什么大惊小怪的?我们将编写一些简单的代码—

**>>> player_1 = "Maradona"
>>> id(player_1)
139780790567600
>>> age = 53
>>> id(age)
9753824**

我们可以认为身份是一个对象在内存中的地址

在这里, id() 给出了我们正在谈论的标识,它是一个惟一的整数,在一个对象的生命周期中不会改变。我们可以认为身份是一个对象在内存中的地址。我们可以用操作符检查两个对象是否相同。

**>>> player_2 = "Pele"
>>> player_1 is player_2     #They are not referring the same object
False >>> player_copy = player_1
>>> player_1 is player_copy   #They are referring the same object
True>>> id(player_2)
139780790567984
>>> id(player_copy)
139780790567600**

现在,如果我们想检查这些对象的类型,我们可以使用 type()

**>>> type(age)
<class ‘int’>
>>> type(player_1)
<class 'str'>**

物体的类型不能改变

对象的类型不能改变

在某些情况下,在某些受控条件下,可以改变对象的类型。但这通常不是一个好主意,因为如果处理不当,它会导致一些非常奇怪的行为。

类型指定了两件事:
–允许哪些操作
–对象可以保存的一组值

如果对象是可变的对象的值可以改变,如果对象是不可变的对象的值不能改变。****

并且,一个对象的是该对象在其中保存的内容。这里53age的值,Maradonaplayer_1的值。如果对象是 可变 对象的可以改变,如果对象是 不可变 对象的值不能改变。

**age = 53** 是一个值为 53 的整型对象,id 为 9753824

这意味着age = 53是一个整数类型的对象,值为53,id 为9753824,如果我们现在将age改为54,它将引用一个不同的对象****

**>>> age = 54 # here, age is referring to a different object
>>> id(age)  # showing different **identity** than the previous one 
9753856**

因此,如果我们想改变player_1的值,那么对象player_copyplayer_1将不会显示相同的标识

**>>> player_1 = "Messi" # assigning new value to 
>>> player_copy
'Maradona'
>>> player_1 is player_copy
False**

因此,player_1又名字符串age又名整数都是不可变类型。还有其他不可变类型。如— 整数、浮点数、字符串、元组。另一方面,可变类型是列表字典集合。现在,看看可变类型****

**>>> players = ["Messi", "Maradona", "Pele"]
>>> players_copy = players     # Coping the reference to the list
                                object,not the list object itself.>>> players is players_copy
True>>> players[0]="Ronaldo"          # Changing the first element
>>> players
['Ronaldo', 'Maradona', 'Pele']
>>> players_copy
['Ronaldo', 'Maradona', 'Pele']   # They refer to same list object.>>> players.append("Pirlo")       # Appending a new element
>>> players
['Ronaldo', 'Maradona', 'Pele', 'Pirlo']
>>> players_copy
['Ronaldo', 'Maradona', 'Pele', 'Pirlo']>>> players_copy.append("Cruyf")
>>> players_copy
['Ronaldo', 'Maradona', 'Pele', 'Pirlo', 'Cruyf']
>>> players
['Ronaldo', 'Maradona', 'Pele', 'Pirlo', 'Cruyf']**

由于 **players** **players_copy** **引用同一个列表对象,一个列表的变化会影响另一个变量。******

在上面的例子中,我们通过改变第一个值并使用append()方法来变异players 列表。由于playersplayers_copy引用同一个列表对象,一个列表的变化会影响另一个变量。****

**>>> id(players)
139780790567040
>>> id(players_copy)
139780790567040**

注意,如果我们改变一个变量所引用的列表,它将创建一个新的列表对象。我们不应该混淆突变和改变变量。****

**>>> players = ["Messi", "Maradona", "Pele"]
>>> id(players)
139780790567040>>> players = ["Messi", "Maradona", "Pele", 'Pirlo', 'Cruyf']
>>> id(players) 
139780790568064**

在这里,这一行players = [“Messi”, “Maradona”, “Pele”, ‘Pirlo’, ‘Cruyf’]创建了一个新的列表并将players变量引用到其中。我们可以通过检查两个身份证来判断。

为了更清楚地理解可变性不变性,让我们把元组带到射击区。我们前面说过,元组不可变的,突变元组 类型应该不可能。****

**>>> players_tuple = ("Kaka", "Buffon")
>>> players_tuple
('Kaka', 'Buffon')
>>> type(players_tuple)
<class 'tuple'>
>>> id(players_tuple)
139780790517248>>> players_tuple[0]
'Kaka'
>>> players_tuple[0]="De Bruyne"     # can't mutate in tuples
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment>>> players_tuple= players_tuple +("De Bruyne",) # adding a new data
>>> players_tuple
('Kaka', 'Buffon', 'De Bruyne')
>>> id(players_tuple)                # it's creating a new tuple
139780766363584**

在这一部分,我们试图清楚地理解一个对象如何在 pythonic 世界中保持其本质,以及可变性不变性之间的区别。在后面的章节中,我们将更深入地研究 python 数据模型。

参考文献:
1。https://docs.python.org/3/reference/datamodel.html2。卢西亚诺·拉马尔霍的流畅 Python。这是每一个 python 爱好者都应该读的书,以提高他们的 python 技能。

Python 数据结构转换(列表、集合和字典)

原文:https://towardsdatascience.com/python-data-structures-conversions-ec9d56649e3b?source=collection_archive---------41-----------------------

不使用内置 Python 命令的 Python 数据结构(列表、集合和字典)及其转换指南

马库斯·斯皮斯克在 Unsplash 上的照片

在 Python 中,主要有两种数据类型,主要是原子集合。原子数据类型是不可分的,它只代表一个数据值。一些例子是整数( int )、浮点( float )和布尔( bool )。集合数据类型则是多个数据值的集合,由字符串( str )、列表( list )、元组( tuple )、集合( set )和字典( dict )组成。本文将重点介绍列表集合字典,以及在没有任何内置 python 命令的情况下在它们之间进行转换的方法。

目录

Python list 是一种数据类型,用于通常相关的集合项,它们可以保存任何数据类型(即 string、int、bool)的数据对象,如下所示。它们通常用方括号表示(例如 [ ] )

a_list = [1, 'two', 3.0, '4']

一些常见有用的列表命令如下。注意,Python 中的索引从 0 开始,而不是像 r 这样的其他编程语言中的 1。

# define empty list
a_list = []# append new item into list at the end of the list
a_list.append(new_item)
# append new item into list at a specific index
a_list.insert(index, new_item)# remove an item from the list based on index
a_list.pop(0)
# remove an item from the list based on item value
a_list.remove('two')# sort the items in ascending order, note that the data types must be similar
a_list.sort()
# reverse the order of the items
a_list.reverse()

一组

集合是一种数据类型,用于表示唯一的、无序的项的集合。它们通常被捕获在一个花括号中(即 { } )。由于集合是唯一且无序的,所以在 Python 中我们无法基于索引或项目分配来访问单个项目。一些常用设置命令如下:

# define an empty set
a_set = set()
# define a set
a_set = {'one', 2}# adding item to a set
a_set.add('c')# removing an item from a set, raise keyError if item does not exist
a_set.remove('one')
# removing an item from a set, no keyError if item does not exist
a_set.discard('one')
# remove the first item from a set and return it
a_set.pop()
# remove all items from a set
a_set.clear()

词典

字典是一种映射数据类型,它将一个键与一个值相关联,这在某种程度上解释了什么是字典(即查找一个单词,它会提供一个含义)。每个数据项表示为 key : value。注意,键值必须是不可变的类型,这意味着它们应该是不变的,而数据值可以是任何数据类型。一些常见的有用的字典命令如下:

# define an empty dictionary
a_dict = {}# define a dictionary
a_dict = {"one":1, "two":2}# adding new items to the dictionary
a_dict[new_key] = new_value# removing items from the dictionary
del a_dict[a_key]# display the keys in the dictionary
a_dict.keys()
# display the values in the dictionary
a_dict.values()
# display the items in the dictionary
a_dict.items()

要设置转换的列表

我们可以很容易地使用set[a_list]将一个列表转换成一个集合。然而,我个人认为了解数据结构如何工作的最好方法是尝试从头开始创建它们。下面的函数将首先定义一个空集,然后使用for循环遍历给定列表中的每个值,将它添加到一个集合中。请记住,集合是唯一的数据结构,即使在给定的列表中有重复的值,它也不会被添加到集合中。

def list_to_set(int_list):
    my_set = set()
    for each in int_list:
        my_set.add(each)

    return my_set

按作者分类的图像 list _ to _ set 函数的 Python 输出

列表到词典的转换

请记住,字典是一个键-值对,这就是为什么如果我们要从头开始创建字典,我们将需要两个单独的列表,一个用于键,另一个用于值。该函数将首先创建一个空字典,然后使用带有range选项的for循环,它将遍历两个列表中的每个元素,并将其标记为键值对。请记住,这两个列表中的顺序很重要,因为我们要根据位置索引将一个键标记为值列表中的一个值。此外,两个列表的长度必须相似。

def list_to_dict(key_list, value_list):
    my_dict = {}
    for i in range (0, len(key_list)):
        my_dict[key_list[i]] = value_list[i]

    return my_dict

作者图片 list _ to _ dict 函数的 Python 输出

设置为字典转换

对于这一部分,我们将引入一种新的数据类型,称为元组,这在前面没有介绍过。元组是括号中的多个数据项(即 ( ) ),元组集只是多个唯一元组的集合。具有两个项目的元组的例子是 (1,2) ,而元组集合可以是 {(1,2),(1,3)} 。对于两个数据项的元组,这似乎表明我们可以从元组集构建一个字典。

像往常一样,我们首先定义一个空字典。然后,我们将使用一个for循环来遍历每个元组。由于每个元组中有两个数据项,第一个值将是我们的字典键,而第二个值将是我们的 it 值。

def set_to_dict(tuple_set):
    my_dict = {}
    for each in tuple_set:
        my_dict[each[0]] = each[1]

    return my_dict

作者图片 set _ to _ dict 函数的 Python 输出

摘要

在本文中,我们介绍了 Python 中三种最常见的集合数据类型(即列表、集合、字典)以及一些常见的有用的 Python 命令。然后详细讨论了数据转换,从头开始在它们之间转换,而不使用内置的 Python 命令。我希望这篇文章能给 Python 爱好者一个熟悉 Python 数据结构的开端,并决定哪种数据结构最适合不同的问题/业务需求,干杯!

使用 Matplotlib 实现 Python 数据可视化—第 2 部分

原文:https://towardsdatascience.com/python-data-visualization-with-matplotlib-part-2-66f1307d42fb?source=collection_archive---------4-----------------------

实践教程,Matplotlib 简介

完成了从基础到高级的 Python 绘图的 Matplotlib 教程,包含 100 多个示例

T 他的故事是使用 Matplotlib 的 Python 数据可视化的下一部分——第 1 部分。在第 1 部分中,我们学习了如何生成和定制散点图、折线图、直方图和条形图。本故事将继续研究使用 Matplotlib 进行 Python 绘图,包括生成和定制箱线图、小提琴图、饼图、极坐标图、地理投影、3D 图和等高线图。

和第 1 部分一样,我告诉您我已经在 Matplotlib 中定制了默认参数。这是我的绘图风格

import numpy as np
import matplotlib.pyplot as pltplt.rcParams['text.usetex'] = True
plt.rcParams['font.size'] = 15
plt.rcParams['font.family'] = "serif"tdir = 'in'
major = 5.0
minor = 3.0
plt.rcParams['xtick.direction'] = tdir
plt.rcParams['ytick.direction'] = tdirplt.rcParams['xtick.major.size'] = major
plt.rcParams['xtick.minor.size'] = minor
plt.rcParams['ytick.major.size'] = major
plt.rcParams['ytick.minor.size'] = minor

我使用乳胶字体作为我的默认衬线系列字体。如果您在激活 LaTeX 字体时遇到错误,您需要阅读这个故事以找到解决方案。我还定制了 xtick 和 ytick 设置,将刻度方向从“向外”改为“向内”,并调整刻度的大小。可以看这个故事了解一下。我们开始吧。

01.箱形图

你知道盒子情节吗?维基百科将箱线图定义为一种通过四分位数图形化描述数字数据组的方法。它用于描述性统计。您可以在图 1 中看到一个箱形图的例子。

图一。方框图元素(图片由作者/ Rizky MN 提供)。

一般来说,箱线图代表一个分布图。它由一个盒子、胡须和离群值构成。在图 1 中,没有异常值。在 box 元素中,您可以显示分布的中值或平均值。我们可以在图 1 中看到中间值。该框受 Q1(第一个四分位数)和 Q3(第三个四分位数)值的限制。Q1 和 Q3 的差值称为四分位数(IQR)。默认情况下,触须显示分布的边界、最小值和最大值。

图二。方框图元素(图片由作者/ Rizky MN 提供)。

在图 2 中,您可以看到有一个异常值。箱线图如何检测异常值?当其值小于 Q1-1.5 倍 IQR 或大于 Q3+1.5 倍 IQR 时,在箱线图中检测到异常值。

在用 Matplotlib 创建一个方框图之前,我将使用下面的代码生成模拟数据

N = 50
np.random.seed(100)
box1 = np.random.randn(N) * 2 + 1

要以方框图的形式显示变量 box1,可以使用以下代码

plt.figure()
plt.boxplot(box1)

当您运行上面的代码时,您可以在图 3 中看到结果

图 3。Matplotlib 中的默认盒图(图片由作者/ Rizky MN 提供)。

水平箱形图

如果您想要水平更改盒状图的方向,您需要在 plt.boxplot()代码中应用以下参数。

vert = False

您可以在图 4 中看到水平方框图的结果。

图 4。Matplotlib 中的水平方框图(图片由作者/ Rizky MN 提供)。

在下一个例子中,我将通过改变种子数量来创建一个带有异常值的分布,如下面的代码所示

N = 50
np.random.seed(140)
box1 = np.random.randn(N) * 2 + 1plt.boxplot(box1, vert=False)

如果您运行上面的代码,您将得到一个方框图,如图 5 所示。

图 5。箱形图中的异常值(图片由作者/ Rizky MN 提供)。

我将向您展示 Matplotlib 如何通过计算 Q1 值(1.5 倍 IQR,Q3+1.5 倍 IQR)来检测异常值,并使用此代码对分布进行排序

q1 = np.quantile(box1, .25)
q3 = np.quantile(box1, .75)
iqr = q3-q1
lower_boundary = q1 - 1.5 * iqr
upper_boundary = q3 + 1.5 * iqr
sort = np.sort(box1)

为了可视化我需要的值,我运行下面的代码

如果您运行上面的代码,它会显示一个图,如图 6 所示。

图 6。箱线图中异常值的解释(图片由作者/ Rizky MN 提供)。

在图 6 中,你可以看到我用红点生成的随机数。下限(Q1-1.5 x IQR)等于-3.69,分布的最小值是-2.41。因此,图 6 中的左晶须极限处于最小值-2.41。上限(Q3 + 1.5 x IQR)为 5.98,因此值为 7.0 的数据被定义为异常值。右须限制将在 5.47 中结束,在上限之前的最大值上。要将图例放在图的外部,您需要阅读这个故事

在下一个例子中,我将展示四个分布的平均值。我需要使用下面的代码为四个发行版创建模拟数据

np.random.seed(1214)
data = [np.random.normal(0, std, 100) for std in range(10, 14)]

展示意味着价值

可变数据将生成 mu 为 0 的四个正态分布,每个分布具有不同的 sigma 值(10、11、12 和 13)。要在箱线图中显示平均值,您需要使用以下代码

plt.boxplot(data, showmeans=True)

如果您运行上面的代码,它将生成一个方框图,如图 7 所示。绿色三角形代表每个箱线图的平均值。

图 7。Matplotlib 中的自定义方框图(图片由作者/ Rizky MN 提供)。

您还可以使用以下代码在水平方框图中显示它

plt.boxplot(data, showmeans=True, vert = False)

上面的代码将生成一个图形,如图 8 所示。

图 7。在水平方框图中显示平均值(图片由作者/ Rizky MN 提供)。

您可以通过添加此参数来更改平均值的符号

meanline=True

或者使用此参数隐藏方框形状

showbox=False

图 8 显示了方框图中的一些定制。

图 8。在 Matplotlib 中自定义方框图(图片由作者/ Rizky MN 提供)。

你想改变盒子的颜色吗?你可以用这些设置来做。首先,您需要激活补丁艺术家,如下面的代码所示

patch_artist=True

然后,准备您的颜色,并使用此代码将其应用到方框图中

colors = ['royalblue', 'lightblue', 'lightgreen', 'pink']
for patch, color in zip(box['boxes'], colors):
    patch.set_facecolor(color)

这是完整的代码

np.random.seed(123)
all_data = [np.random.normal(0, std, 100) for std in range(10, 14)]box = plt.boxplot(all_data, notch=False, patch_artist=True)colors = ['royalblue', 'lightblue', 'lightgreen', 'pink']
for patch, color in zip(box['boxes'], colors):
    patch.set_facecolor(color)plt.ylim(-50, 50)

上面的代码将生成一个图形,如图 9 所示。

图 9。在 Matplotlib 中自定义方框图颜色(图片由作者/ Rizky MN 提供)。

激活槽口

您可以使用此参数在箱形图中显示凹口,如图 10 所示

notch=True

图 10。在 Matplotlib 中嵌入凹口(图片由作者/ Rizky MN 提供)。

您可以用这段代码重现图 10

np.random.seed(123)
all_data = [np.random.normal(0, std, 100) for std in range(10, 14)]box = plt.boxplot(all_data, notch=True, patch_artist=True)colors = ['royalblue', 'lightblue', 'lightgreen', 'pink']
for patch, color in zip(box['boxes'], colors):
    patch.set_facecolor(color)plt.ylim(-50, 50)

02.小提琴情节

Violin 图与 box 图非常相似,但没有定义异常值。分布中的所有数据都显示在一个内核函数中。为了创建一个小提琴情节,我使用了以下代码

N = 50
np.random.seed(140)
viol = np.random.randn(N) * 2 + 1plt.figure()
plt.violinplot(viol)

该代码将向您展示一个小提琴图,如图 11 所示。

图 11。Matplotlib 中的默认小提琴情节(图片由作者/ Rizky MN 提供)。

要水平显示它,您可以在方框图中使用相同的参数

vert=False

默认情况下,violin 图不显示中值和平均值。如果你想展示它,你需要插入这些参数

showmeans=True, showmedians=True

如果我结合上面的参数并运行它,我将看到如图 12 所示的 violin 图。

图 12。Matplotlib 中带有中值和平均值的小提琴图(图片由作者/ Rizky MN 提供)。

在图 12 中,我认为你不能区分哪里是中间值,哪里是平均值,因为它们有相似的颜色。要更改 violin 绘图中每个元素的颜色,如条形的颜色、中值、平均值、最小值和最大值,您需要将盒绘图代码定义为一个变量,如以下代码所示

violin_parts = plt.violinplot(data, showmedians=True, 
                              showmeans=True)

我生成四种不同的正态分布,定义为 数据 变量。

要更改中值、平均值、条形图、最小值和最大值的颜色,可以使用以下代码

vmedian = violin_parts['cmedians']
vmedian.set_edgecolor('r')vmean = violin_parts['cmeans']
vmean.set_edgecolor('k')vbars = violin_parts['cbars']
vbars.set_edgecolor('k')vmax = violin_parts['cmaxes']
vmax.set_edgecolor('darkorange')vmin = violin_parts['cmins']
vmin.set_edgecolor('darkorange')

定制的小提琴图如图 13 所示。

图 13。Matplotlib 中定制的小提琴剧情(图片由作者提供)。

下面是生成图 13 的完整代码。

np.random.seed(1214)
data = [np.random.normal(0, std, 100) for std in range(10, 14)]plt.figure(figsize = (10, 6))
violin_parts = plt.violinplot(data, showmedians=True, 
                              showmeans=True)vbars = violin_parts['cbars']
vbars.set_edgecolor('k')vmedian = violin_parts['cmedians']
vmedian.set_edgecolor('r')vmean = violin_parts['cmeans']
vmean.set_edgecolor('k')vmax = violin_parts['cmaxes']
vmax.set_edgecolor('darkorange')vmin = violin_parts['cmins']
vmin.set_edgecolor('darkorange')

要改变身体(轮廓)的颜色,你需要使用这个代码

for vp in violin_parts['bodies']:
    vp.set_facecolor('orange')
    vp.set_edgecolor('k')
    vp.set_linewidth(3)

上面的代码将把主体颜色改为橙色,黑色作为边缘颜色,并将线条宽度调整为 3,如图 14 所示。

图 14。在 Matplotlib 中自定义小提琴情节的主体颜色(图片由作者/ Rizky MN 提供)。

在图 14 中,我只显示了每个分布的中值。您可以用下面的代码重现图 14

np.random.seed(1214)
data = [np.random.normal(0, std, 100) for std in range(10, 14)]plt.figure(figsize = (10, 6))
violin_parts = plt.violinplot(data, widths=0.9, showmedians=True)for vp in violin_parts['bodies']:
    vp.set_facecolor('orange')
    vp.set_edgecolor('k')
    vp.set_linewidth(3)

我创建了一个完全定制的小提琴图,如图 15 所示。

图 15。在 Matplotlib 中自定义小提琴剧情(图片由作者/ Rizky MN 提供)。

您可以使用这段代码生成图 15

np.random.seed(1214)
data = [np.random.normal(0, std, 100) for std in range(10, 14)]# Create violin plot objects:
plt.figure(figsize=(10, 6))
violin_parts=plt.violinplot(data, showmedians=True, showmeans=True)# Make the violin body blue with a red border:
for vp in violin_parts['bodies']:
    vp.set_facecolor('royalblue')
    vp.set_edgecolor('k')
    vp.set_linewidth(2)
    vp.set_alpha(.8)colors = ['k', 'red', 'red', 'w', 'k']
part = ['cbars','cmins','cmaxes','cmeans','cmedians']for i in range(len(part)):
    vp = violin_parts[part[i]]
    vp.set_edgecolor(colors[i])
    vp.set_linewidth(2)

03.圆形分格统计图表

在生成饼图之前,我使用这段代码创建了一些动物的数量数据

labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
numbers = [15, 30, 45, 10]

要在饼图中可视化它,您可以使用以下代码

plt.pie(numbers)

上面的代码将生成一个饼状图,如图 16 所示。

图 16。Matplotlib 中的默认饼图(图片由作者/ Rizky MN 提供)。

图 16 显示了一个简单的饼图。您可以使用此参数为每个动物数据指定标签

labels = labels

如果你想显示每种动物的数量,你需要插入这个参数

autopct='%1.1f%%'

您可以在图 17 中看到添加标签和数字后的饼图结果。

图 17。在 Matplotlib 中自定义饼图(图片由作者/ Rizky MN 提供)。

下面是创建图 17 的完整代码。

labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]plt.figure()plt.pie(sizes, labels = labels, autopct='%1.1f%%')

您可以使用此参数更改饼图的起始角度

startangle=90

默认起始角度为 0,应用于第一个数据(青蛙)。我在两个不同的角度自定义了起始角度,如图 18 所示。

图 18。在 Matplotlib 中自定义饼图的起始角度(图片由作者/ Rizky MN 提供)。

下面是生成图 18 的代码

labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]
explode1 = (0, 0.1, 0, 0)
explode2 = (0, 0, 0.1, 0)plt.figure(figsize=(10, 10))
plt.subplot(121)
plt.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=90)
plt.title('Startangle = 90$^\circ$')plt.subplot(122)
plt.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=180)
plt.title('Startangle = 180$^\circ$')

您还可以为特定的饼图留出空白,如图 19 所示。

图 19。在 Matplotlib 中自定义饼图分解(图片由作者/ Rizky MN 提供)。

您可以使用下面的代码重现图 19

labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]
explode1 = (0, 0.1, 0, 0)
explode2 = (0, 0, 0.1, 0)plt.figure(figsize=(10, 10))plt.subplot(121)
plt.pie(sizes, explode=explode1, labels=labels, 
        autopct='%1.1f%%', startangle=90)plt.subplot(122)
plt.pie(sizes, explode=explode2, labels=labels, 
        autopct='%1.1f%%', startangle=180)

您可以通过调整变量 explode 中的值来更改边距。

在饼图中应用不同的样式

是否希望以不同的样式在饼图中显示数据?Yups,你可以看到图 20。

图 20。在饼图 Matplotlib 中应用不同的样式。

与之前的饼图不同的是,我将标签放在了图例中。要做到这一点,你需要使用这个论点

textprops={'color':"w"}

这个代码

plt.legend(labels, bbox_to_anchor = (1., .95),  title="Labels Name")

您可以使用下面的代码重现图 20

labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]
explode = (0, 0.05, 0, 0)plt.figure(figsize=(7, 7))plt.pie(sizes, autopct='%1.1f%%', textprops={'color':"w"}, 
        explode = explode, startangle = 90)

饼图中的阴影

您可以使用此参数在饼图中添加阴影

shadow=True

结果如图 21 所示。

图 21。在 Matplotlib 中的饼图中添加阴影(图片由作者/ Rizky MN 提供)。

我想我知道你在想什么:d .影子很丑吧?为此我尝试过很多替代方案;他们在这里

a.如果您正在使用 Jupyter,您可以通过右键单击图形来手动保存您的饼图。然后,点击 Save Image As,如图 22 所示。

图 22。在 Jupyter 中手动保存图像(图片由作者/ Rizky MN 提供)。

保存的图像如图 23 所示。

图 23。Jupyter 和 Matplotlib 中的备选保存图像(图片由作者/ Rizky MN 提供)。

b.另一种方法是添加白色笔画作为前景。要应用它,您需要使用以下代码从 Matplotlib 导入 path_effects

import matplotlib.patheffects as path_effects

然后,定义饼图的变量名,如下面的代码所示

patches, texts, autotexts = plt.pie(sizes, autopct='%1.1f%%', 
                                    textprops={'color':"w"}, 
                                    explode = explode, 
                                    startangle = 90, shadow=True)

接下来,用下面的代码定制 path_effects

for patch in patches:
    patch.set_path_effects([path_effects.Stroke(linewidth=2.5, 
                                                foreground = 'w')])

这是完整的代码

如果您运行上面的代码,它将创建一个饼图,如图 24 所示。

图 24。在饼图 Matplotlib 中添加前景笔划(图片由作者/ Rizky MN 提供)。

它并不完美,但我认为它比没有添加笔画更漂亮。您还可以将第一个和第二个选项结合起来,得到如图 25 所示的饼图。

图 25。自定义饼图 Matplotlib 中的阴影。

圆环图

从 Matplotlib 中的饼图特性,您可以创建一个圆环图,如图 26 所示。

图 26。Matplotlib 中的简单圆环图(图片由作者/ Rizky MN 提供)。

下面是生成图 26 数据的代码。

size = 0.3
vals = np.array([[60.], [37.], [29.]])cmap = plt.get_cmap("tab20c")
outer_colors = cmap(np.arange(3)*4)
inner_colors = cmap(np.array([1, 2, 5, 6, 9, 10]))

圆环图与饼图相似,但没有中心的完整半径。在图 26 中,我设置半径等于 0.3。下面是生成图 26 的代码。

plt.figure(figsize=(10,10))plt.pie(vals.sum(axis=1), radius=1, colors=outer_colors,
       wedgeprops=dict(width=size, edgecolor='w'))

我还创建了两个不同的半径大小,如图 27 所示。

图 27。圆环图 Matplotlib 中两种不同的半径大小(图片由作者/ Rizky MN 提供)。

您可以用下面的代码重现图 27。

vals = np.array([[60.], [37.], [29.]])plt.figure(figsize=(10,10))plt.subplot(121)
plt.pie(vals.sum(axis=1), radius=1, colors=outer_colors,
       wedgeprops=dict(width=.3, edgecolor='w'))
plt.title('Size = 0.3')plt.subplot(122)
plt.pie(vals.sum(axis=1), radius=1, colors=outer_colors,
       wedgeprops=dict(width=.5, edgecolor='w'))
plt.title('Size = 0.5')

您还可以创建一个双圆环图,如图 28 所示。

图 28。Matplotlib 中的双圆环图(图片由作者/ Rizky MN 提供)。

下面是生成图 28 的代码。

plt.figure(figsize=(10, 10))size = 0.3
vals = np.array([[60., 32.], [37., 40.], [29., 10.]])cmap = plt.get_cmap("tab20c")
outer_colors = cmap(np.arange(3)*4)
inner_colors = cmap(np.array([1, 2, 5, 6, 9, 10]))plt.pie(vals.sum(axis=1), radius=1, colors=outer_colors,
       wedgeprops=dict(width=size, edgecolor='w'))plt.pie(vals.flatten(), radius=1-size, colors=inner_colors,
       wedgeprops=dict(width=size, edgecolor='w'))

如果你阅读 Matplotlib 站点中的甜甜圈图文档,你会遇到一个漂亮的甜甜圈图,如图 29 所示。

图 29。Matplotlib 中一个漂亮的圆环图(图片由作者/ Rizky MN 提供)。

您可以使用这段代码创建图 29。

04.极区图

在平面投影中,您将有一个 x 轴和 y 轴。在极轴投影中,你需要用半径和角度的形式来定义它,如图 30 所示。

图 30。极射投影和平面投影的比较(图片由作者/ Rizky MN 提供)。

在极轴投影中,半径轴以圆半径的大小显示,角度以每个 0 度圆的角度为起点进行投影。要生成极轴投影,需要将投影类型定义为极轴,如以下参数所示。

projection='polar'

下面是生成图 30 的完整代码。

r = np.linspace(0, 2, 100)
theta = 2 * np.pi * rfig = plt.figure(figsize=(13, 4))ax1 = plt.subplot(121, projection='polar')
ax1.scatter(theta, r, label = 'Polar Projection', s = 10)
ax1.legend(bbox_to_anchor = (.85, 1.35))ax2 = plt.subplot(122)
ax2.scatter(theta, r, label = 'Planar Projection', s = 10)
ax2.legend(bbox_to_anchor = (0.85, 1.35))
ax2.set_xlabel('R')
ax2.set_ylabel(r'$\theta$')

您还可以在极轴投影中以绘图线样式显示您的数据,如图 31 所示。

图 31。在极投影中创建一条绘图线(图片由作者/ Rizky MN 提供)。

您可以用这段代码重现图 31

接下来是在极坐标投影中创建一个条形图,如图 32 所示。

图 32。极坐标投影中的条形图(图片由作者/ Rizky MN 提供)。

当你看到图 32 时,也许你正在记起 Matplotlib 😄 的徽标。为了创建图 32,你需要使用以下代码生成数据

np.random.seed(10130)N = 20
theta = np.linspace(0.0, 2 * np.pi, N, endpoint=False)
radii = 10 * np.random.rand(N)
width = np.random.rand(N) * .8 - .1
colors = plt.cm.Spectral(radii / 10)

要将其可视化,您可以使用以下代码

plt.figure(figsize=(7, 7))ax = plt.subplot(111, projection='polar')
ax.bar(theta, radii, width=width, bottom=0.0, 
       color=colors, alpha=0.5)

如果您对使用极坐标条形图生成 Matplotlib 徽标感兴趣,可以阅读此文档。

[## Matplotlib 徽标- Matplotlib 3.1.0 文档

编辑描述

matplotlib.org](https://matplotlib.org/3.1.0/gallery/misc/logos2.html)

05.地理投影

要可视化您的地理数据,您可以使用 Matplotlib 提供的地理投影。有四种类型的投影:Aitoff、Hammer、Mollweide 和 Lambert 投影。为了理解它,我将使用这段代码创建一个模拟数据

N = 100np.random.seed(157)
long = np.random.random(N) * 360 - 180
lat = np.random.random(N) * 180 - 90

要在 Aitoff 投影中将其可视化,可以使用以下代码

plt.figure(figsize=(12, 7))
plt.subplot(111, projection="aitoff")
plt.scatter(long, lat, marker = '*', color = 'red', s = 40)
plt.title("Aitoff")
plt.grid(True)

代码将向您显示一个图形,如图 33 所示。

图 33。Matplotlib 中的 Aitoff 投影(图片由作者/ Rizky MN 提供)。

在艾托夫投影中,您需要确保您的数据以度为单位。

接下来是锤子投影。您可以使用此代码在 Hammer 投影中显示您的数据

plt.figure(figsize=(12, 7))
plt.subplot(111, projection="hammer")
plt.scatter(long, lat, marker = '*', color = 'red', s = 40)
plt.title("Hammer")
plt.grid(True)

锤子投影中显示的经度和纬度变量的单位是度。上面的代码将生成一个图形,如图 34 所示。

图 34。Matplotlib 中的锤子投影(图片由作者/ Rizky MN 提供)。

我不确定艾托夫投影和锤子投影有什么区别。如果你需要一些解释,你可以阅读这些链接。

[## 艾托夫投影

Aitoff 投影是由 David A. Aitoff 于 1889 年提出的一种改进的方位地图投影。基于…

en.wikipedia.org](https://en.wikipedia.org/wiki/Aitoff_projection) [## 锤子投影

哈默投影是恩斯特·哈默在 1892 年描述的一种等面积地图投影。使用相同的 2:1 椭圆…

en.wikipedia.org](https://en.wikipedia.org/wiki/Hammer_projection)

在 Mollweide 投影中,数据单位需要转换为弧度。下面是生成弧度数据的代码。

N = 100np.random.seed(157)
long = np.random.random(N) * 2 * np.pi  - np.pi
lat = np.random.random(N) * np.pi - (np.pi / 2)

要在 Mollweide 投影中将其可视化,可以使用以下代码

plt.figure(figsize=(12, 7))
plt.subplot(111, projection="mollweide")
plt.scatter(long, lat, marker = '*', color = 'red', s = 40)
plt.title("Mollweide")
plt.grid(True)

如果您运行上面的代码,它将创建一个图形,如图 35 所示。

图 35。Matplotlib 中的 Mollweide 投影(图片由作者/ Rizky MN 提供)。

最后一个投影是 Lambert 投影,如图 36 所示。

图 36。Matplotlib 中的 Lambert 投影(图片由作者/ Rizky MN 提供)。

数据的单位是弧度。您可以使用这段代码重现图 36。

N = 100np.random.seed(157)
long = np.random.random(N) * 2 * np.pi  - np.pi
lat = np.random.random(N) * np.pi - (np.pi / 2)plt.figure(figsize=(12, 12))
plt.subplot(111, projection="lambert")
plt.scatter(long, lat, marker = '*', color = 'red', s = 40)
plt.title("Lambert")
plt.grid(True)

06.三维绘图

要创建 3d 绘图,需要将投影类型定义为 3D,如以下参数所示

projection = '3d'

3D 投影将给出如图 37 所示的结果。

图 37。Matplotlib 中的 3D 投影(图片由作者/ Rizky MN 提供)。

我用这段代码生成模拟数据。

N = 250np.random.seed(124)
x = 15 * np.random.random(N)
y = np.sin(x) + 0.25 * np.random.random(N)
z = np.cos(x) + 0.25 * np.random.random(N)

要可视化 3D 散点图中的数据,可以使用以下代码。

plt.figure(figsize=(9, 6))
ax = plt.axes(projection = '3d')
ax.scatter3D(x, y, z, color = 'r')ax.set_xlabel('x', fontsize = 20, labelpad = 20)
ax.set_ylabel('y', fontsize = 20, labelpad = 20)
ax.set_zlabel('z', fontsize = 20, labelpad = 20)

代码将生成一个 3d 绘图,如图 38 所示。

图 38。Matplotlib 中的 3D 散点图(图片由作者/ Rizky MN 提供)。

据我所知,在最新的 Matplotlib 版本中,每个轴的纵横比总是相同的。要更改它,您可以使用以下代码

ax.set_box_aspect((2., 1.5, 1.2))

我将 x 轴、y 轴和 z 轴的纵横比更改为 2:1.5:1.2。应用上面的代码后,您将有一个图,如图 39 所示。

图 39。在 Matplotlib 中自定义 3D 散点图的特征。

三维绘图线

您可以创建一个 3D 绘图线,如图 40 所示。

图 40。Matplotlib 中的 3D 绘图线(图片由作者/ Rizky MN 提供)。

您可以用这段代码重现图 40。

N = 100np.random.seed(124)
xline = np.linspace(0, 15, N)
yline = np.sin(xline) 
zline = np.cos(xline)fig = plt.figure(figsize=(9, 6))
ax = plt.axes(projection = '3d')
ax.plot3D(xline, yline, zline)ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')ax.set_box_aspect((2, 1.5, 1.2))

你可以用这个代码改变视角

ax.view_init(10, 180)

view_init 中的第一个参数是仰角,第二个参数是方位角。您可以看到不同角度的不同表示,如图 41 所示。

图 41。在 3D 绘图中自定义视角(图片由作者/ Rizky MN 提供)。

三角形 3D 表面

要在 Matplotlib 中生成一个三角形的 3D 曲面,可以使用下面的代码。

ax.plot_trisurf()

我用这段代码生成了要在三角形 3D 表面中可视化的数据

N = 2000np.random.seed(124)
r = 2 * np.pi * np.random.random(N)
theta = 20 * np.pi * np.random.random(N)xdata = np.ravel(r * np.sin(theta))
ydata = np.ravel(r * np.cos(theta))
zdata = np.sin(xdata) + np.cos(ydata)

您可以从上面图 42 中的数据看到三角形 3D 表面图。

图 42。Matplotlib 中的三角形 3D 表面绘图(图片由作者/ Rizky MN 提供)。

您可以用这段代码重现图 42

3D 等高线图

Matplotlib 提供 3D 等高线图。您可以使用以下代码创建它

ax.contour3D()

我使用下面的代码生成模拟数据

N = 100
np.random.seed(3124)
x = np.linspace(-2, 2, N) + np.random.random(N)
y = np.linspace(-2, 2, N) + np.random.random(N)X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)

为了形象化它,我运行以下代码

fig = plt.figure(figsize=(9, 6))ax = plt.axes(projection = '3d')
ax.contour3D(X, Y, Z, cmap = 'Spectral')

定制之后,我的 3D 轮廓图如图 43 所示。

图 43。Matplotlib 中的默认 3D 等高线图(图片由作者/ Rizky MN 提供)。

您可以使用这段代码重现图 43

默认情况下,Matplotlib 在 7 个计数的等高线中生成 3D 等高线图。您可以通过在 ax.contour3D()的第四个参数中写下您想要的计数来更改它,如下面的代码所示

ax.contour3D(X, Y, Z, 256, cmap = 'Spectral')

您可以在图 44 中看到不同的 3D 等高线图。

图 44。在 Matplotlib 中自定义 3D 等高线图(图片由作者/ Rizky MN 提供)。

下面是生成图 44 的完整代码。

要显示颜色条,您可以使用以下代码

plt.colorbar()

需要的参数是您的 3D 等高线图。所以,如果你把你的图定义成一个变量,那是最好的。在我的代码中,它被定义为变量 p。

您可以使用前面图中应用的相同代码来改变视角,如图 45 所示。

图 45。在 Matplotlib 中使用颜色条自定义 3D 等高线图(图片由作者/ Rizky MN 提供)。

3D 等高线 Matplotlib 中的错误

我觉得 Matplotlib 3D contour 有 bug,如图 46 所示。

图 46。3D contour Matplotlib 中的一个 bug(图片作者/ Rizky MN)。

要创建图 46,您需要在前面的代码(创建图 45 的代码)中更改仰角和方位角的值。你明白我说的虫子是什么意思吗?如果你仔细分析图 46,你会得到一个奇怪的特征。您可以在图 47 中看到它。

图 47。3D contour Matplotlib 中的一个 bug(图片作者/ Rizky MN)。

蓝线覆盖的区域位置不对。我们看不到它,因为它被放在后面。我不确定是不是 bug,但是我觉得需要 Matplotlib 来修复。

为了更详细地理解它,我在 Matplotlib 中引入了两种不同的轮廓表示,ax.contour()和 ax.contourf(),如图 48 所示。

图 48。Matplotlib 中 3D 等高线图的两种不同表示法(图片由作者/ Rizky MN 提供)。

contourf 在 ax.contourf 中的意思是填充轮廓。因此,您可以在图 48 中看到 ax.contour()和 ax . contour()之间的区别。ax.contour 具有与 ax.contour3D()相似的默认轮廓计数,即 7 个计数。但是,ax.contourf()有不同的计数,它是 8。您可以用这段代码重现图 48

N = 100
np.random.seed(3124)
x = np.linspace(-2, 2, N) + np.random.random(N)
y = np.linspace(-2, 2, N) + np.random.random(N)X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)plt.figure(figsize=(14, 6))ax1 = plt.subplot(121, projection = '3d')
ax1.contour(X, Y, Z, cmap = 'Spectral')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_zlabel('z')ax1.set_box_aspect((3, 3, 1))
ax1.view_init(10, 100)
ax1.set_title('Contour Default, elevation = 10, azimuth = 100')ax2 = plt.subplot(122, projection = '3d')
ax2.contourf(X, Y, Z, cmap = 'Spectral')
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_zlabel('z')ax2.set_box_aspect((3, 3, 1))
ax2.view_init(10, 100)
ax2.set_title('Contourf Default, elevation = 10, azimuth = 100')

您可以在图 48 的右图中仔细观察(contourf 图)。我在 3D 轮廓中提到的错误没有被检测到。您可以在图 49 中看到更多细节。

图 49。ax.contur()和 ax.contourf()在检测 Matplotlib 的 bug 方面的比较(图片由作者/ Rizky MN 提供)。

您可以看到,如果 ax.contour()会给出相同的错误,但对于 ax . contour()则不会。所以,如果你想在 3D 投影中可视化等高线图,我推荐你使用 ax.contourf()。

线框绘图

您可以使用以下代码在 Matplotlib 中生成一个线框绘图

ax.plot_wireframe()

下面是生成在线框图中可视化的模拟数据的代码

N = 100
np.random.seed(3124)
x = np.linspace(-2, 2, N) + np.random.random(N)
y = np.linspace(-2, 2, N) + np.random.random(N)X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)

默认的线框图表如图 50 所示。

图 50。Matplotlib 中的默认线框绘图(图片由作者/ Rizky MN 提供)。

您可以用下面的代码重现图 50

N = 100
np.random.seed(3124)
x = np.linspace(-2, 2, N) + np.random.random(N)
y = np.linspace(-2, 2, N) + np.random.random(N)X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)fig = plt.figure(figsize=(10, 10))ax = plt.axes(projection = '3d')
ax.plot_wireframe(X, Y, Z, color = 'k', alpha = .2)

定制的线框图表如图 51 所示。

图 51。Matplotlib 中的自定义线框绘图(图片由作者/ Rizky MN 提供)。

我将线框层数改为 5,将仰角设为 60 度,方位角设为 100 度。您可以使用这段代码生成图 51。

N = 100
np.random.seed(3124)
x = np.linspace(-2, 2, N) + np.random.random(N)
y = np.linspace(-2, 2, N) + np.random.random(N)X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)fig = plt.figure(figsize=(9, 6))ax = plt.axes(projection = '3d')# 3d contour plot
ax.plot_wireframe(X, Y, Z, 5, color = 'k', alpha = .2)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')ax.set_box_aspect((2, 2, 1))
ax.view_init(60, 100)ax.set_title('Wireframe counts = 5, elevation = 60, azimuth = 100')

如果您想检查我们是否在 ax.contour()和 ax.contour3D()中遇到类似的错误,您可以将仰角更改为 10 度,将方位角更改为 100 度,如图 52 所示。

图 52。Matplotlib 中的自定义线框绘图(图片由作者/ Rizky MN 提供)。

我们没有遇到线框图中的错误。

3D 表面图

您可以使用此代码在 Matplotlib 中生成 3D 曲面图。

ax.plot_surface()

定制的 3D 表面图如图 53 所示。

图 53。Matplotlib 中的自定义 3D 表面图(图片由作者/ Rizky MN 提供)。

您可以用这段代码重现图 53

N = 100
np.random.seed(3124)
x = np.linspace(-2, 2, N) + np.random.random(N)
y = np.linspace(-2, 2, N) + np.random.random(N)X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)fig = plt.figure(figsize=(8, 8))ax = plt.axes(projection = '3d')# 3d contour plot
ax.plot_surface(X, Y, Z, )
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')ax.set_box_aspect((2, 2, 1))
ax.view_init(10, 100)ax.set_title('Plot surface Default, elevation = 10, azimuth = 100')

您可以使用此参数设置 cstride 和 rstride 的值

rstride = 1, cstride = 1

您可以在图 54 中看到默认 cstride 和 rstride 值与自定义值之间的差异。

图 54。Matplotlib 中的自定义 3D 表面图(图片由作者/ Rizky MN 提供)。

要生成图 54,您可以使用以下代码

你不会遇到你在等高线图中遇到的 bug,如图 55 所示。

图 55。在 Matplotlib 中检查 3D 表面图中的 bug(图片由作者/ Rizky MN 提供)。

在 Matplotlib 中创建球

您可以在 Matplotlib 中创建一个球,如图 56 所示。

图 56。在 Matplotlib 中创建球(图片由作者/ Rizky MN 提供)。

您可以用下面的代码创建图 56

u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)
x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))plt.figure(figsize=(10, 10))
ax = plt.subplot(projection = '3d')
ax.plot_surface(x, y, z, cmap = 'inferno')

您可以为它定制视角,如图 57 所示。

图 57。在 Matplotlib 中自定义球(图片作者/ Rizky MN)。

您可以使用这段代码重现图 57

07.2D 等高线图

我要展示的最后一种绘图类型是 2D 等高线图。您可以使用此代码生成 2D 等高线图

plt.contour()

虽然名称是 2D 等高线图,但它显示的是 3D 数据。我使用这段代码创建模拟数据

N = 100
np.random.seed(100)x = np.linspace(-2, 2, N) + np.random.random(N)
y = np.linspace(-2, 2, N) + np.random.random(N)X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)

我将模拟数据呈现在等高线图中,如图 58 所示。

图 58。Matplotlib 中的默认 2D 等高线图(图片由作者/ Rizky MN 提供)。

您可以用下面的代码重现图 58

N = 100
np.random.seed(100)x = np.linspace(-2, 2, N) + np.random.random(N)
y = np.linspace(-2, 2, N) + np.random.random(N)X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)plt.figure(figsize=(7, 5))
plt.contour(X, Y, Z)
plt.title('Contour 2D Default', pad = 10)

我生成了两个定制的等高线图,如图 59 所示。

图 59。Matplotlib 中的两个自定义 2D 等高线图(图片由作者/ Rizky MN 提供)。

要创建图 59,您可以使用以下代码

N = 100
np.random.seed(100)x = np.linspace(-2, 2, N) + np.random.random(N)
y = np.linspace(-2, 2, N) + np.random.random(N)X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)plt.figure(figsize=(15, 5))plt.subplot(121)
plt.contour(X, Y, Z, 256)
plt.title('Contour 2D counts = 256, cmap = viridis', pad = 10)
plt.colorbar()plt.subplot(122)
plt.contour(X, Y, Z, 256, cmap = 'Spectral')
plt.colorbar()
plt.title('Contour 2D counts = 256, cmap = Spectral', pad = 10)

同样,你可以生成填充到 2D 投影中的等高线,如图 60 所示。

图 60。Matplotlib 中的默认轮廓图(图片由作者/ Rizky MN 提供)。

您可以用下面的代码生成图 60

N = 100
np.random.seed(100)x = np.linspace(-2, 2, N) + np.random.random(N)
y = np.linspace(-2, 2, N) + np.random.random(N)X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)**3plt.figure(figsize=(7, 5))
plt.contourf(X, Y, Z, cmap = 'Spectral')
plt.colorbar()plt.title('Contourf 2D Default', pad = 10)

这里我生成了两个不同的 contourf 图,如图 61 所示。

图 61。Matplotlib 中两个自定义的 confourf 图(图片由作者/ Rizky MN 提供)。

您可以使用这段代码生成图 61

N = 100
np.random.seed(100)x = np.linspace(-2, 2, N) + np.random.random(N)
y = np.linspace(-2, 2, N) + np.random.random(N)X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)**3plt.figure(figsize=(15, 5))plt.subplot(121)
plt.contourf(X, Y, Z, 50, cmap = 'inferno')
plt.colorbar()plt.title('Contourf 2D counts = 50', pad = 10)plt.subplot(122)
plt.contourf(X, Y, Z, 200, cmap = 'inferno')
plt.colorbar()plt.title('Contourf 2D counts = 200', pad = 10)

结论

在技术时代,数据可视化对于从小数据或大数据中分析数据具有重要意义。我们需要它来全面了解我们的数据。可以与 Matplotlib 一起使用的各种类型的可视化。这只是 python 用 Matplotlib 绘图的一小部分。在这个 Matplotlib 指南系列(第 1 部分和第 2 部分)中,我生成了 101 个图形。如果你读完了所有的部分,你需要花你的 48 分钟:D,我希望这个故事可以帮助你把你的数据可视化成各种各样的情节类型。

如果你喜欢这篇文章,这里有一些你可能喜欢的其他文章:

[## 使用 Matplotlib 可视化数据的 5 个强大技巧

如何使用 LaTeX 字体,创建缩放效果,发件箱图例,连续错误,以及调整框填充边距

towardsdatascience.com](/5-powerful-tricks-to-visualize-your-data-with-matplotlib-16bc33747e05) [## 用于科学绘图的 Matplotlib 样式

为您的科学数据可视化定制 Matplotlib

towardsdatascience.com](/matplotlib-styles-for-scientific-plotting-d023f74515b4) [## 在 Matplotlib 中创建色彩映射表

从颜色列表中创建和定制自己的色彩映射表的指南

towardsdatascience.com](/creating-colormaps-in-matplotlib-4d4de78a04b8) [## 在 Matplotlib 中自定义多个子情节

使用 subplot、add_subplot 和 GridSpec 在 Matplotlib 中创建复杂 subplot 的指南

towardsdatascience.com](/customizing-multiple-subplots-in-matplotlib-a3e1c2e099bc) [## Vaex 大数据简介—读取 12.5 亿行的简单代码

用 Python 高效读取和可视化 12.5 亿行星系模拟数据

towardsdatascience.com](/introduction-to-big-data-a-simple-code-to-read-1-25-billion-rows-c02f3f166ec9)

仅此而已。感谢您阅读这个故事。喜欢就评论分享。我还建议您关注我的帐户,以便在我发布新故事时收到通知。

Python 装饰器:从简单装饰器到嵌套多重

原文:https://towardsdatascience.com/python-decorators-from-simple-decorators-to-nesting-multiple-33bbab8c5a45?source=collection_archive---------22-----------------------

米尔蒂亚迪斯·弗拉基迪斯在 Unsplash 上拍摄的照片

如何用多个参数化的 decorators 修改一个函数?

装饰器对象是修改一个装饰的对象的功能的一种方式。用 python 实现装饰器有多种方法。在这篇文章中,我们将讨论一些以及如何将多个 decorators 链接在一起以真正增强一个对象的功能。在 python 中,函数/方法只是对象,所以在这篇文章中,我们将同时研究实现 decorators 的类和方法。

简单装饰

在我们开始嵌套之前,让我们看一个简单的装饰器。我将首先从一个简单的 add 方法开始。

上面的方法只是取了两个参数 ab 。上述方法的功能是将这两个输入参数相加,并返回相加的结果。

现在我要装饰这个方法,这样方法 add 的结果就会乘以 2。

为了实现这一点,我创建了一个方法乘 2。multiply_by_two 采用另一种方法作为输入。它创建了另一个方法 _multiply_by_two ,该方法接受两个参数,这两个参数随后被传递给输入法,其结果乘以 2。乘二返回这个构造的方法_ 乘二

我所做的是创建了一个装饰器 multiply_by_two ,它基本上是通过将输入法乘以 2 来装饰输入法的功能(顾名思义)。现在让我们来看看它的作用。

上面的代码,修饰了方法乘 2。这样做的构造是将@符号与正在修饰的方法一起使用(乘 2)在正在修饰的方法之前()。

在上面的代码中,相同的 decorator 被应用于 subtract 方法。在这种情况下,输出是-8。所以很容易看出装修工是多才多艺的。它们可以相当普遍地应用。

参数化装饰器

在上面的例子中,我演示了乘 2,但是如果我们想给开发者一个选择乘任意数的机会呢?在这种情况下,我们希望将装饰器参数化。

这可能看起来让人不知所措,让我们来分解一下。方法乘 _ 乘取一个输入数。如果你仔细观察,方法 _multiplymultiply_by_two 非常相似。唯一的区别是现在 num 被用来乘,而不是硬编码 2。

在 decorator 中使用参数的方法是在使用@ symbol 和 decorator 方法的名称之后发送它们。在这种情况下,它是 @multiply_by ,我们传递 3。这种情况下的输出是预期的 18。

嵌套参数化装饰器

现在让我们来看看装饰器的嵌套,一个接一个的装饰器可以被应用到一个方法上。与算术主题保持一致,我现在将创建另一个方法 divide_by ,它与 multiply_by 相同,只是它使用输入 num 来划分修饰方法的结果。

要嵌套 decorators,需要在实际的被修饰方法之前使用与 symbol @之前使用的相同机制一次指定一个。

在上面的代码中,我装饰了方法 add by multiply_by ,然后 divide_by 。因为乘法和除法都发生在同一个数字 3 上,所以该方法的结果是 6。

我在这里所做的只是首先用参数 3 指定 decorator divide_by ,然后用相同的参数 3 指定 multiply_by 。这产生了嵌套,因为首先乘以然后除以装饰器被应用。应用程序的顺序与它们在代码中出现的顺序相反,注意这一点很重要。

奖金

如上面的代码所示,装饰器也可以应用在方法内部。我会让你决定以上的结果。也可以放在评论/回复里。

结论

在这篇文章中,我解释了如何在 python 中使用 decorator,方法是引入一个简单的 decorator,然后将其参数化,最后将多个 decorator 嵌套在一起。我希望你喜欢它!

在 LinkedIn 上与我联系或在 Medium 上关注我。如果你喜欢这个故事,你可能会喜欢我关于 python decorators 的其他故事:

[## Python 装饰者与数据科学:随机抽样

使用 python decorator 进行随机采样

towardsdatascience.com](/python-decorators-with-data-science-random-sampling-177962cae80c) [## 装饰模式和 Python 装饰器

为什么它们不一样?

medium.com](https://medium.com/better-programming/decorator-pattern-and-python-decorators-b0b573f4c1ce)

Python 装饰者与数据科学:随机抽样

原文:https://towardsdatascience.com/python-decorators-with-data-science-random-sampling-177962cae80c?source=collection_archive---------56-----------------------

来源:https://en.wikipedia.org/wiki/Inverse_transform_sampling

使用 python decorator 进行随机采样

这篇文章在一起学习一些概念方面更有教育意义。我想知道如何将 python decorators 与特定的数据科学概念结合使用,于是就有了写这篇文章的想法。让我们先看看随机抽样是如何做到的。

随意采样

逆变换是从一些众所周知的分布中生成随机样本的方法之一。逆变换取 0 和 1 之间的均匀样本 u ,并从分布 P(X)返回最大数 x ,使得 X 低于 x 的概率小于等于 u

概率积分变换陈述了如果 x 是一个连续随机变量具有累积分布函数 Fₓ,那么随机变量 Y=Fₓ(X 在【0,1】上具有均匀分布。逆概率积分变换正好与此相反:具体来说,如果 y 在[0,1]上具有均匀分布,并且如果 x 具有累积分布 Fₓ,则随机变量 Fₓ⁻ (Y)具有与 x 相同的分布

来源:https://en.wikipedia.org/wiki/Inverse_transform_sampling

维基百科关于逆变换采样的文章对此有更详细的解释。在这篇文章中,我不会深入讨论这个问题,只是使用逆变换来计算一些分布的随机样本。

根据这篇文章,逆变换采样方法的工作原理如下:

  1. 从区间[0,1]中的标准均匀分布生成一个随机数 u
  2. 求所需 CDF 的倒数,例如 Fₓ⁻ (X)
  3. 计算 Fₓ⁻(美国)

现在我将逐一介绍这些步骤,并介绍我们如何使用 python decorators。

随机数发生器

Python 随机模块提供了一种生成随机数的好方法。

随机. random()

返回[0.0,1.0]范围内的下一个随机浮点数。

我们定义一个函数 random_sample ,它返回一个给定长度大小的随机数列表。那很容易!

逆累积分布函数

在这个练习中,让我们以伯努利分布为例。它是一个离散的概率分布,其中随机变量 x 以概率 p 取值 1,以概率 1 - p 取值 0。

x = 0 时,P(X = X)= 1-P .F(X)在这种情况下也是 1-P。F 的倒数可以理解为,当来自均匀分布的随机样本小于等于 1- p 时,则 x 为 0。由此我们还可以得出,当随机样本大于 1- p 时,则 x 为 1。

计算逆 CDF

如前所述,如果随机生成的数字小于等于 1- p ,则该方法返回 0,否则返回 1。很高兴看到概率为 0.5(甚至概率为 0 或 1)的伯努利样本有一半是 0,另一半是 1。类似地,对于 0.8 的概率,10 个样本中有 8 个是 1。需要注意的是,在不同的机器和不同的运行中,结果可能会有所不同。

Python 装饰者

我们可以用 bernoulli_sample 来修饰函数 random_sample这将使所有的 random_sample 都来自伯努利分布。让我们看看如何做到这一点。

这样的结局和以前一样。我看到 10 个样本中有 8 个样本的概率为 0.8。同样,需要注意的是,在您的机器上和不同的运行中,结果可能会有所不同。

问题

  1. 输入参数:如果你仔细看 random_sample 函数的定义,它已经变了。现在不是以大小作为输入,而是以概率和大小两个输入。
  2. 函数名:另一个问题是函数名 random_sample 暗示了它的随机样本,而不是来自伯努利分布的样本列表。

让我们解决以上两个问题。

一般化

kwargs 是 python 中传递关键字参数的一种方式。我将用它来概括实现。此外,我将交换伯努利随机样本函数的顺序。所以与其说是伯努利装饰 random_sample ,不如说是反过来。这将为我们提供描述分布名称的函数名。

以下是我们所做的更改列表:

  1. 装饰者:现在 random_sample 方法是装饰者,装饰任何方法分配
  2. 关键字参数 s:用随机的样本更新参数字典,因此任何分配方法都可以通过,而不管它的参数。
  3. 包装:使用包装允许将 docstring 更新为包装的分发函数。help(bernoulli)显示了更具描述性的内容。

模块 main 中关于伯努利函数的帮助:

伯努利(**kwargs)
样本来自给定概率 p 和大小的伯努利分布。
:param p:事件发生的概率
:param size:随机样本数
:return:给定大小的样本列表

指数分布

让我们把我们在伯努利方程中学到的知识应用到指数分布中。指数分布的累积分布函数如下:

资料来源:https://en.wikipedia.org/wiki/Exponential_distribution

指数分布的 CDF 的倒数为:

来源:https://en.wikipedia.org/wiki/Inverse_transform_sampling

上面是使用random _ sampledecorator 从指数分布中获取样本的代码。下面是获得的样品的直方图。

指数分布:概率分布函数

结论

在这篇文章中,我想探索如何将 Python 和数据科学这两个概念结合起来。希望你对如何用 random_sample 来装饰逆变换实现可以产生目标分布的样本感兴趣。

在 LinkedIn 上与我联系或在 Medium 上关注我。如果你喜欢这个故事,你可能会喜欢我关于 python decorators 的其他故事:

[## 装饰模式和 Python 装饰器

为什么它们不一样?

medium.com](https://medium.com/better-programming/decorator-pattern-and-python-decorators-b0b573f4c1ce) [## Python 装饰器:从简单装饰器到嵌套多重

如何用多个参数化的 decorators 修改一个函数?

towardsdatascience.com](/python-decorators-from-simple-decorators-to-nesting-multiple-33bbab8c5a45)

Python:用图形和机器学习检测 Twitter 机器人

原文:https://towardsdatascience.com/python-detecting-twitter-bots-with-graphs-and-machine-learning-41269205ab07?source=collection_archive---------12-----------------------

具有 Graph2Vec、XGBoost 等特性!

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

在最近的封锁期间,Twitter 用户活动的上升,这似乎是一个开始寻找隔离项目以提高我的机器学习能力的好地方。具体来说,随着错误信息和令人困惑的阴谋控制了美国的网民,试图找出识别坏人的新方法似乎越来越成为一项相关的任务。

在这篇文章中,我将借助一些有用的 Python 网络图形和机器学习包,展示如何构建一个模型来预测 Twitter 用户是人类还是机器人,只使用每个用户的最小可行图形表示。

概述

1。初步研究

2。数据收集

3。数据转换

4。训练分类模型

5。收尾思路/改进空间

技术札记

所有编程、数据收集等。是在一个笔记本上完成的。
使用的库:

tweepy
pandas
igraph
networkx
numpy
json
csv
ast
itemgetter (from operator)
re
Graph2Vec (from karateclub)
xgboost

最后,四个资源是这项任务的关键,我将在本文后面讨论:

让我们开始吧!

初步研究

虽然将 bot 检测作为一个目标并不是什么新鲜事,但是如果没有前面提到的重要工作,像这样的项目是不可能完成的,我认为问题空间中有几个主题可以进一步探讨。

首先是规模和缩减。我不会在“业余爱好者”以上的任何级别描述我的数据科学专业知识,因此,处理能力和 Twitter API 访问都是我必须记住的因素。我知道我无法通过更大、更成熟的群体来复制模型的准确性,因此我开始研究的事情之一是,在这些限制下,如何实现分类模型的可伸缩性和准确性。

第二是分类中使用的用户数据类型。我发现了几个模型,它们借鉴了用户档案的各种不同元素,从推文的文本内容到用户名的长度或使用的档案图片。然而,我发现只有少数 尝试基于用户社交网络的图表做同样的事情。碰巧的是,这种基于图表的方法也是我收集每个用户的足够数据用于以后分类的最佳方式,而不会违反 Twitter 的 API 限制。

数据收集

首先,当使用 Twitter 时,您需要开发人员 API 访问。如果你还没有,你可以在这里申请,Tweepy(我将在这篇文章中使用的 Twitter API 包装器)的文档中有更多关于认证过程的信息。

完成后,您需要用您的凭证创建一个 API 实例,如下所示。

输入您的凭证

为了训练一个模型,我需要一个 Twitter 用户名和现有标签的数据库,以及一种快速收集每个用户相关数据的方法。

我最终选定的数据库是 IUNI 优秀的机器人知识库,其中包含数千个 TSV 和 JSON 格式的已标记人类和机器人账户。第二部分有点难。起初,我试图生成每个用户的整个时间表的图形表示,但由于 API 的限制,对于一些更多产的用户来说,这可能需要一天多的时间。小型图表的最佳格式是 Jacob Moore 的教程,使用特征向量中心性识别 Twitter 影响者。

我不会重复他的脚本如何工作的完整解释,或者什么是特征中心性,因为这两个东西在他的教程中比我能说的更好,但是从一个高层次的角度来看,他的脚本将一个 Twitter 用户(或者一个关键字,但我最终没有使用该功能)作为输入,并输出一个 CSV,其中包含一个用户边缘列表,该列表根据他们对给定用户在 Twitter 上的交互的“影响”进行加权。它还输出一个 iGraph 对象,我们将把它写入一个 GML 文件,我们将用它作为每个用户的唯一表示。

您将需要他的教程中的 TweetGrabber、RetweetParser 和 TweetGraph 类的功能。下一步是用您的 API 键创建一个 TweetGrabber 实例,并对您选择的 Twitter 用户执行搜索。

创建用户与其网络关系的 GML 文件

上述代码的第 27 行和第 28 行为每个顶点创建了一个“size”属性,该属性保存了其特征中心值,这意味着当我们将创建的 iGraph 对象写入 GML 文件时,正如我们在第 31 行中所做的那样,该文件将包含我们需要的关于用户的所有信息,并且可以丢弃之前创建的 CSV。此外,如果您愿意,您可以取消对第 33–38 行的注释来绘制和查看图形,它可能看起来像这样:

我跟踪的抽动流光的图形输出。

为了构建我将在其上训练分类模型的数据库,我将从 Bot 存储库中收集的每个用户名和标签添加到 pandas 数据帧中,并遍历该数据帧,以每个用户名作为输入运行该脚本。这个过程的这一部分是最耗时的,需要几个小时,但在从框架中删除空的或被删除的帐户后,结果是超过 20,000 个带有“基础事实”标签的用户图表用于分类。下一步:格式化这些数据来训练模型。

数据变换

但是首先,简单回顾一下什么是模型(如果你熟悉,你可以跳到‘在过程的这个点……’)。

机器学习模型的目标是查看关于某物的一系列信息(特征),然后使用这些信息尝试并预测关于该物的特定陈述(或标签)。

例如,这可能是一个模型,它获取一个人的日常饮食,并试图预测他们牙齿上的菌斑数量,或者这可能是一个模型,它获取一个人经常购物的商店类型,并试图预测他们的头发颜色。像第一种模型,个人信息与被预测的特征更紧密相关(饮食对牙齿健康的影响可能比购物习惯对头发颜色的影响更大),通常会更成功。

创建这样一个模型并“教会”它更准确地做出这些预测的方法是,将它暴露给大量的事物,这些事物已经有了它们的特征和标签。通过“研究”这些提供的例子,模型理想地“学习”什么特征与一个标签或另一个标签最相关。
例如,如果你的模型正在“研究”的数据库包含一群具有“早餐吃棉花糖”特征的人的信息,而这些人中的大多数碰巧都有较高的牙菌斑量,那么你的模型很可能能够预测,如果一个没有标签的人也在早餐吃棉花糖,他们的牙齿就不会看起来这么热。

为了更好更全面的解释,我推荐这个视频

在这个过程中的这一点上,我们有一个关于 somethings (Twitter 用户)的数据库,每个用户都有信息(他们的图表)和一个是/否声明(他们是否是机器人)。然而,这将我们带到下一步,这是创建模型的关键步骤-如何将这些图表转换为输入要素。为模型提供太多不相关的信息会使它花更长的时间从输入中“学习”,或者更糟,使它的预测不太准确。

在不丢失任何重要信息的情况下,在我们的模型中表示每个用户图表的最有效方式是什么?

这就是空手道俱乐部的由来。具体来说, Graph2Vec ,这是一个完整的图形“嵌入”库,它采用任意大小的图形,比如上图中的图形,并将其嵌入为一个低维向量。关于图形嵌入的更多信息(特别包括 Graph2Vec),我推荐这篇文章,以及这篇白皮书
长话短说,Graph2Vec 将图形转换成更密集的表示,保留结构和信息等属性,这正是我们想要的输入特征。

为此,我们需要将图形转换成与 Graph2Vec 兼容的格式。对我来说,这个过程是这样的:

创建用户图形的矢量嵌入

最终结果将如下所示:

[[-0.04542452  0.228086    0.13908194 -0.05709897  0.05758724  0.4356743
   0.16271514  0.09336048  0.05702725 -0.2599525  -0.44161066  0.34562927
   0.3947958   0.30249864 -0.23051494  0.31273103 -0.26534733 -0.10631609
  -0.44468483 -0.17555945  0.07549448  0.38697574  0.2060106   0.08094891
  -0.30476692  0.08177203  0.35429433  0.2300599  -0.26465878  0.07840226
   0.14166194  0.0674125   0.0869598   0.16948421  0.1830279  -0.17096592
  -0.17521448  0.18930815  0.35843915 -0.19418521  0.10822983 -0.25496888
  -0.1363765  -0.2970226   0.33938506  0.09292185  0.02078495  0.27141875
  -0.43539774  0.23756032 -0.11258412  0.01081391  0.44175783 -0.19365656
  -0.04390689  0.09775431  0.03468767  0.06897729  0.2971188  -0.35383108
   0.2914173   0.45880902  0.22477058  0.12225034]]

对人类的眼睛来说并不漂亮,但是结合我们的标签,正是我们创建分类模型所需要的。我对每个被标记的用户重复这个过程,并将结果存储在另一个 pandas 数据帧中,因此现在我有一个大约 20,000 行和 65 列的数据帧,其中 64 列是描述用户图形的向量,第 65 列是用户是机器人还是人类的“基本事实”标签。现在,到了最后一步。

训练分类模型

因为我们的目标是分类(预测每个“东西”是否应该被放在两个类别中的一个,在本例中是机器人或人),所以我选择使用 XGBoost 的 XGBClassifier 模型。XGBoost 使用梯度推进来优化回归和分类问题的预测,以我的经验来看,这比其他大多数选项的预测更准确。

从这里开始,有两种不同的选择:

如果您的目标是训练您自己的模型来进行预测和修改,并且您有一个用户图形向量和标签的数据库来完成此任务,则您需要使分类模型适合您的数据库。这是我的过程:

训练你自己的分类模型

如果你的目标只是试图预测你已经绘制和矢量化的单个用户的人性或机器人性,那也没问题。我已经包含了一个 JSON 文件,您可以从我的 GitHub 中加载我的模型,它链接到我的个人资料中。这个过程大概是这样的:

加载我的分类模型

就是这样!您应该会看到您开始使用的帐户的预测标签。

关闭思路/改进空间

我的模型有很多可以改进的地方,我希望有一天能再去看看。

首先也是最重要的是准确性。虽然 IUNI 根据他们的 Bot 存储库构建的 Botometer 分类模型在测试数据集上显示了近 100%的分类准确性,但我的模型显示了 79%的准确性。这是有意义的,因为我使用较少的特征来预测每个用户的标签,但我相信在我的极简方法和 IUNI 的方法之间有一个中间地带,我会有兴趣尝试结合基于图形、基于文本和基于简档的分类方法。

另一个与准确性相关的因素是图表本身的结构。Igraph 能够计算图中每个节点的特征向量中心性,但也包括许多其他基于节点的测量,如接近度、介数或多个测量的优化组合。

最后,有两件事使得测试和改进这个模型的准确性变得困难。首先,由于我对向量嵌入的理解有限,我很难识别哪些特征会导致准确或不准确的标记。第二个问题是,测试数据集的结果对 Twitter 今天的生态系统有多准确。随着机器人被检测到,这个领域也在发展,检测方法也必须发展。为此,我在整个隔离期间从 Twitter 上浏览了一些趋势话题,供用户应用这个模型,但我认为这必须等到以后的帖子。

感谢您的阅读!如果你有任何问题或反馈,请在评论中告诉我。

用于可视化和建模 covid 19-数据的 Python 开发工具包

原文:https://towardsdatascience.com/python-development-kit-for-visualizing-and-modelling-of-covid19-data-b33e7a13aace?source=collection_archive---------67-----------------------

数据可视化—开发套件—覆盆子— Python

用您自己的方法创建您的新冠肺炎数据分析

介绍

新冠肺炎冠状病毒疫情正在影响 213 个国家,并造成严重破坏。人们因被感染而死亡;世界经济缩减了;失业以每周数百万的速度增长,许多人正在制造混乱,开始反抗。因此,对 Covid19 数据的分析和模拟对于对抗新型冠状病毒病毒是重要的。这不仅对病毒学家、医生很重要,对其他学科的其他专家也很重要,对我们所有人也很重要。

人们可以使用计算软件,如微软 Excel (桌面)、 LibreOffice (桌面,免费)、谷歌工作表(在线)来处理数据,但最好使用编程来进行复杂方法的计算。因此我开发了一个开源包TAV uong/covid 19-datakit,它是 MIT 授权的,用 Python 编写。您可以使用该套件根据套件库中已实现的模型来可视化、分析或模拟数据。您也可以将自己的模型实现到工具包中。

那么就让我们来看看怎么用吧!

covid 19-数据套件

数据下载和处理

Covid19-Datakit 将处理冠状病毒疫情的数据,这些 csv 文件可以从冠状病毒源数据openZH/covid_19 或从互联网下载,例如 JainXu- list

Covid19-datakit 可以处理具有以下结构和格式的 csv 文件数据:

  • 第一名。列是数据-时间,该列中的数据将绘制在 x 轴上。第一列中的日期时间必须采用 yyyy-mm-dd 格式,例如 2020–01–01。
  • 2nd- nte 列是时间序列数据,绘制在 y 轴上。

如果您的 csv 文件不符合这些要求,您应该使用计算软件,如 MicroSoft Excel、LibreOffice Calc 或 Google sheet,来更改格式或结构。

套件—描述

麻省理工学院许可的开源软件 tavuong/covid19-datakit 包含以下部分:

  • covid19-datakit.py 是一个仪表板,有一个用户界面,通过对话框获取数据 csv 文件的位置和模型参数值。它管理工作流程:读取数据,使用模型模块计算数据,并在计算机屏幕上显示结果或将结果打印为图像(png 文件)。仪表盘有一个“我”模式,用户可以将仪表盘切换到与自己的车型一起工作。还有内置的命令行,因此您可以编写 shell 脚本来可视化许多功能的数据,例如许多国家的新案例。
  • 默认套件库TAV uong _ visual . py中的可视化模块,开发模型处理TAV uong _ model . py中的 covid19- data。您可以使用这些模块来立即可视化您的数据,例如,每日新增病例的总和或根据恢复率估计的每日感染人数的总和(我的开发模型)。
  • 用户库:是您开发自己的模型和自己的所有者演示文稿的模块。您可以使用user _ model . pyuser _ visual . py中的模板来开发集成在仪表板中的“me-mode”,这样您就可以获得数据和参数,而不必编写新的对话框和管理工作流。测试一下,你会喜欢的。

哪个计算机系统可以使用该工具包?

要运行这个工具包,你需要一个 Python 解释器,你可以从 Python.org 下载 Python 用于 WindowsLinux/UNIXMac OS X其他。该套件由 Windows 10 (PC)、由“Raspbian Buster with desktop and recommended software”(Raspberry Pi)和由 Termux(UNIX fortable t)进行测试

安装

在命令提示符(Windows X)或 LX 终端(Raspberry PI)中给出以下命令

$ github 克隆https://github.com/tavuong/covid19-datakit.git

$ pip 安装费用

$ pip 安装 Matplotlib

*$ cd ~\covid19-datakit*

$ python。\ covid 19-data kit . py[通过 PC]

$ python3。\ covid 19-data kit . py[by Raspberry PI]

它将要求:数据 csv 文件的数据读取位置,你想可视化其数据的国家,可视化或模拟的模型和我的模型' gc '或' gs '的恢复率,模拟感染与估计恢复率的情况。

将对话框用于套件的示例

*对于这个例子,我们在。\ covid 19-数据工具包\数据*

*$ CD ~ \ covid 19-数据套件*

$ python。\ covid 19-data kit . py[通过 PC]

试剂盒>病例数据文件?。\data\new_cases.csv
(请求 csv 文件的位置)

csv 文件中的国家列表将被读取并显示:

套件>国家?世界
(您想要处理的国家数据请求)

将显示可视化模式列表:

ac :实际案例:每日新增案例曲线

sr :每日病例总数

gc :实际案例,包括预计回收率:这是模拟

gs :每日案例总数,包含预计回收率:这是模拟

:我的型号:切换到自己的型号

t2 : 测试图

KIT >您的计算模型是什么?sr
(要求您选择模式)

然后它将绘制:

命令行

命令行刚刚实现。它有以下选项:

$ python。\covid19-datakit.py -h

covid19-datakit
-i <输入文件> -o <输出文件>
-c 国家
-m 模式
-g 恢复

示例呼叫 gs 模式

$ python。\ covid 19-data kit . py-I。\ data \ new _ cases . CSV-c Italy-o test.png-m GS-g 0.8

切换到用户模式:我的模式

您可以使用模板模块开发自己的所有者模型,该模型通过仪表板集成为“我”模式(covid19-datakit.py)。

通过从仪表板请求(covid19-datakit.py)中选择“我”,套件将调用我模式的可视模块:

my_collection_1(x,y,y1,y2,namecountry,gesund)。

****名称国家:国家参数

gesund :回收率

x [ ] :从 csv 文件输入时间数据**

y [ ] :输入,CSV 文件中所选国家的 covid 数据,范围同 x [ ]**

Y1 [ ] : 读取生成的缓冲字段,范围与 x [ ] 相同

y2 [ ] : 读取生成的缓冲区,范围与 x [ ] 相同

现在,您已经完成了用于可视化和/或建模的数据

根据 my_collection_1(…)中的 y[ ],您可以通过调用模块来计算另一个 y2 [ ]:

my_model_1(y2,y,factor,Tau,gesund)

Tau:孵化时间,尚未实现从仪表板读取

因子:R 因子,尚未实现从仪表板读取

gesund:来自控制板请求的回收率

y [ ]:输入 csv 文件中所选国家的 covid 数据

y2 [ ]:输出,与 y [ ]范围相同

Me 模式示例

要研究 user-visual.py 和 user_model.py 中两个模板模块的代码,先从这个例子开始理解它是如何工作的。

$ python。\ covid 19-data kit . py-I。\ data \ new _ cases . CSV-c Italy-o test.png-m me-g 0.8

摘要

软件包 covid19-datakit 专注于处理 covid19 数据。它很容易使用对话框或命令行。您可以将自己的模型集成到仪表板中。

covid19 数据的可视化和建模一直在不断发展,将来还会更新。如果您已经开发了一个新的有趣的模型-模块或演示-模块,请不要犹豫与我联系进行咨询开发,并可能将您的模块贡献给开源和麻省理工学院许可的项目TAV uong/covid 19-data kitovergithub

玩得开心!

鸣谢:简范博士教授

Python 词典

原文:https://towardsdatascience.com/python-dictionaries-651acb069f94?source=collection_archive---------9-----------------------

像专家一样使用 Python 字典

自由股票Unsplash 上的照片

Python 编程语言在数据科学项目中被开发者广泛使用。要完成这样的项目,理解数据结构起着重要的作用。Python 有几个内置的数据结构,如列表集合、元组字典,以支持开发者使用现成的数据结构。

在这篇文章中,我将尝试解释为什么以及何时使用 Python 字典,同时给你一些关于正确使用字典方法的提示。

让我们通过一步一步的解释和例子来详细理解 Python 字典。

什么是 Python 字典?

简而言之,一个字典可以被定义为存储在键/值对中的数据集合。必须是不可变的数据类型(如字符串、整数或元组),而字典中的可以是任何 Python 数据类型。

不允许出现重复的。如果同一个在同一个字典中使用了两次,那么最后一次出现的将覆盖第一次出现的。

存储在字典中的数据可以被修改,所以它们被称为可变对象。它们是无序的,这意味着我们没有保持指定项目的顺序。(从 3.7 版本开始订购)

因为它们是动态的,它们可以在需要的时候收缩。

什么时候使用 Python 字典?

既然您现在已经知道了什么是 Python 字典,那么是时候探索何时在您的代码中使用它们了。

这里有一个帮助你理解何时使用 Python 字典的列表。

  • 当数据具有可以与值相关联的唯一引用时。
  • 当快速访问数据项很重要时。字典被设计成让我们立即找到一个值,而不需要搜索整个集合。
  • 当数据顺序不重要时。
  • 因为字典是可变的,所以使用字典来存储不应该被修改的数据并不是一个好主意。
  • 当内存考虑不是应用程序的重要因素时。与列表和元组相比,字典占用更多的内存空间。

如何创建 Python 字典?

有许多创建和初始化字典的方法。如下面的代码片段所示,创建字典最简单的方法是直接使用花括号dict() 方法;

如果你有两个可迭代的对象(例如列表对象),你可以使用 zip() 函数来创建一个字典。参见下面的例子;

fromkeys() 方法是另一种创建字典的方法。它接受一个 iterable 对象并创建一个具有指定值的字典,如下面的代码片段所示;

什么是 Python 词典释义?

Python 字典理解提供了一种创建字典的优雅方式。它们使你的代码更容易阅读,更有 Pythonic 风格。它们缩短了字典初始化所需的代码,并可用于用代替循环。

字典理解的一般语法是:

dictionary = {key:value for (key, value) in iterable}

将条件句添加到词典理解中

你可以用条件语句扩展字典理解的使用。你可以在下面看到多个‘if’条件句、‘else-if’条件句在字典理解中的用法;

字典操作的时间复杂度

获取设置删除字典中的一个条目具有 O(1) 的时间复杂度,这意味着无论你的字典有多大,访问一个条目所花费的时间都是恒定的。

在一个字典上迭代具有 O(n) 的时间复杂度意味着执行这个任务所花费的时间与字典中包含的条目数量成线性比例。

如何访问字典中的值

如果你试图用一个字典中不存在的访问一个元素,你会得到一个 KeyError 。了解访问字典中元素的正确方法对于在运行时不出现 KeyErrors 非常重要。

为了避免 KeyError,get() 方法访问字典的元素。或者,您可以使用'关键字中的' T45 '来检查该键是否存在。

如何将一个条目插入词典?

没有add()insert()append()方法可以用来将条目添加到字典中。相反,您必须创建一个新的键来存储字典中的值。如果字典中已经存在该键,则该值将被覆盖。

下面的代码片段展示了许多向字典中添加条目的例子;

字典方法有哪些?

Python 字典中包含许多方法,帮助您在字典对象上执行不同的任务。我在下面列出了它们的简短定义;

  • popitem() :从字典中删除最后一项
  • pop( key,defaultvalue ) :从字典中移除并返回给定键的元素
  • keys(): 返回键
  • values(): 返回数值
  • items(): 返回字典的键值对
  • get( key[,value] ): 如果指定键在字典中,则返回该键的值
  • fromkeys( keys,value ): 返回具有指定键和指定值的字典
  • setdefault( key,value ) :返回具有指定键的项目的值。如果键不存在,则插入具有指定值的键
  • update(iterable):如果关键字不在字典中,则将指定的项目插入字典,否则更新值
  • copy(): 返回字典的浅层副本
  • clear(): 从字典中删除所有项目

如何从字典中删除一个条目?

要从 dictionary 对象中删除一个条目,可以使用 'del' 关键字或 pop() 方法。此外,您可以使用字典理解删除字典中的条目。请查看下面的代码片段,了解这些方法的实现示例;

如何抄字典?

您可以使用 copy() 方法获得一个现有字典的浅层副本浅拷贝意味着一个新的字典将用对现有字典中对象的引用来填充。

要创建深层副本,应使用 'copy.deepcopy(dict)' 方法。它用原始字典的所有元素创建一个完全独立的副本。

参见下文,了解如何在字典对象上实现浅拷贝深拷贝方法;

如何合并字典?

您可以使用包含 dict.copy()dict.update() 方法的自定义函数来合并字典。

在 Python 3.5 及更高版本中,您可以使用' **' 操作符通过解包来合并字典。

合并字典最简单、最容易的方法是使用 Python 3.9+中可用的合并操作符 '|'

下面的代码片段通过示例展示了上述所有方法的实现;

如何对字典中的条目进行排序?

Python 字典在 3.7 版之前是无序的,所以即使对(键,值)对进行排序,也不能通过保留顺序将它们存储在字典中。为了保持排序,我们可以将排序后的字典存储在一个[OrderedDict](http://docs.python.org/library/collections.html#collections.OrderedDict)

参见下文,了解如何通过值对字典进行排序;

如何在字典中循环?

Python 字典方法; values()、keys()、items() 提供了对字典中包含的元素的访问。您可以在 for 循环中使用它们来遍历字典。

另外,字典理解也可以用于迭代,如下所示;

结论和关键要点

因为数据结构是我们程序的基础部分,所以对 Python 字典有一个坚实的理解对于创建高效的程序是非常重要的。

我解释了为什么以及什么时候使用字典,下面列出了一些要点;

  • 当数据具有可以与关联的唯一引用时,可以使用 Python 字典。
  • 由于字典可变的,使用字典来存储那些一开始就不应该被修改的数据并不是一个好主意。
  • Python 字典在 3.7 版本之前是无序的,所以即使你对(键,值)对进行了排序,你也不能通过保留顺序来将它们存储在字典中。
  • Python 字典理解提供了一种创建字典的优雅方式。它们使你的代码更容易阅读,更有 Pythonic 风格。

感谢您的阅读!

Python 目录和文件管理

原文:https://towardsdatascience.com/python-directory-and-file-management-ebfa2c29073f?source=collection_archive---------36-----------------------

了解如何用 Python 处理目录和文件操作

伊利亚·巴甫洛夫在 Unsplash 上的照片

在这篇文章中,你将学习到用 Python 处理文件和目录的各种方法,比如

  • 创建、更改、删除和重命名目录
  • 获取当前目录或列出文件,同时统计目录中的文件数量
  • 读取和提取 zip 文件
  • 复制文件并将文件从一个目录移动到另一个目录

为什么要学习目录和文件管理?

  • 在机器学习和深度学习中,您将处理作为数据集一部分存储在目录中的大量文件,或者您将在文件中存储模型的训练权重。因此,学习文件和目录管理将会很有帮助
  • 目录和文件管理还将有助于在一致的目录结构中组织训练、测试和验证数据集,用于所有类型的数据,如数字数据、图像数据或文本数据。

我们将导入所需的库 osshutil ,它们将提供处理操作系统相关功能的方法。

创建目录:mkdir(路径)

要创建一个目录,我们将使用 mkdir() ,我们需要向其传递要创建的目录的路径。

如果目录已经存在,则引发' 文件存在错误'

***import os
try:
    os.mkdir('c:\\test_1')
except FileExistsError:
    print("Directory already exists")***

如果目录 test_1 不存在,那么将创建一个新的目录 test_1。如果目录 test_1 已经存在,则出现错误,'filexistserror '

重命名文件或目录:重命名(源,目标)

要重命名文件或目录,我们需要指定源,即您要重命名的文件,以及目标,即该目录下文件的新名称。

如果源文件或目录 test_1 不存在,那么我们得到一个“FileNotFoundError”错误

如果目标 test_2 目录已经存在,那么我们得到“filexistserror”错误

***try:
    os.rename('c:\\test_1\\', 'c:\\test_2')
except :
    print(sys.exc_info())***

删除目录:rmdir(路径)

删除指定为参数的目录。

如果要删除的目录不存在,那么会得到一个'FileNotFoundError'错误。

如果该目录包含文件,并且您正试图删除该目录,那么您将得到一个“ OSError ”消息“该目录不是空的”。

***try:
    os.rmdir('c:\test_2\\abc')
except:
    print(sys.exc_info())***

更改目录:chdir(路径)

将当前工作目录更改为指定路径。

如果目录 test_1 不存在,那么你会得到一个' FileNotFoundError ' 如果指定文件名而不是目录,则会出现“OSError”消息“文件名、目录名或卷标语法不正确。'

***try:
    os.chdir('c:\\test_1')
except:
     print(sys.exc_info())***

打印当前工作目录:getcwd()

os.getcwd() 以字符串形式返回当前工作目录

**print(os.getcwd())**

列出目录中的文件:listdir(路径)

列出指定目录路径中的文件。文件列表在列表中以任意顺序返回。

如果没有指定路径,那么 listdir()返回当前工作目录下的文件列表

***os.listdir('c:\\test_2\\test')***

目录' c:\ test _ 2 \ test '中的文件列表

计算目录中文件的数量

***len(os.listdir('c:\\test_2\\test'))***

您将得到输出 4,因为我们在如上所示的目录中有四个文件

从 zip 文件中读取和提取文件

您将接收或下载压缩在 zip 文件中的数据,因此知道如何从 zip 文件中读取和提取所有文件将是一个非常有用的工具。

你需要导入 zipfile 库。

我有从 Kaggle 下载的狗和猫的数据集,放在一个 zip 文件中。读取 zip 文件,然后使用 extractall ()方法提取指定的目标文件夹中的所有数据

***import zipfile
zipfile_path='c:\\Datasets\\CV\\dogs-vs-cats.zip'******zip_f= zipfile.ZipFile(zipfile_path, 'r')
zip_f.extractall('c:\\Datasets\\CV\\dogs-vs-cats')******zip_f.close()***

复制文件:复制文件(源,目标)

使用 shutil copyfile()方法将文件从源文件复制到目标文件。目的地应该是完整的目标文件名。

下面的代码一次复制一个文件,从 base_dirdest_dir 。我们用OS . path . join()来加入目录和文件名。

***from  shutil import copyfile***
***try:
    base_dir='c:\\Datasets\\CV\\dogs-vs-cats\\test1'
    dest_dir='c:\\test_2\\'
    for file in os.listdir(base_dir):
        copyfile(os.path.join(base_dir, file), os.path.join(dest_dir, file))
except:
    print(sys.exc_info())***

移动文件:移动(源,目标)

shutil 库中的 Move()方法可用于移动文件。在源参数和目标参数中都包含文件名。

***import  shutil******base_file='c:\\Datasets\\CV\\dogs-vs-cats\\test1\\1.jpg'
dest_file='c:\\test_2\\test\\1.jpg'
shutil.move(base_file, dest_file)***

如果目标文件名被更改,文件将被重命名和移动

***import  shutil******base_file='c:\\Datasets\\CV\\dogs-vs-cats\\test1\\100.jpg'
dest_file='c:\\test_2\\test\\dog_2.jpg'
shutil.move(base_file, dest_file)***

结论:

osshutil 用于目录和文件管理,帮助在一致的目录结构中组织文件,以便使用 ML/DL 算法训练、测试和验证数据集

参考资料:

[## os —其他操作系统接口— Python 3.8.3rc1 文档

该模块提供了一种使用操作系统相关功能的可移植方式。如果你只是想阅读或…

docs.python.org](https://docs.python.org/3/library/os.html)

https://docs.python.org/3/library/shutil.html

Python 采用了 R (Markdown)方式

原文:https://towardsdatascience.com/python-done-the-r-markdown-way-d03bec4b96b?source=collection_archive---------25-----------------------

照片由维特·加布雷拍摄

介绍

开始使用一种新工具可能并不容易,尤其是当那个“工具”意味着一种新的编程语言的时候。与此同时,可能会有机会在已知的基础上再接再厉,让过渡更平稳,痛苦更少。

对我来说,是从 RPython 的过渡。不幸的是,我以前的同事 pythonians 没有分享我对 R 的真正喜爱。此外,不管 R 爱好者喜欢与否, Python 是数据分析/工程/科学等领域广泛使用的工具。因此,我得出结论,至少学习一些 Python 是一件合理的事情。

对我来说,最初的步骤可能是最困难的。在舒适的 RStudio 中,像 Pycharm 或 Atom 这样的 ide 并不熟悉。这一经历促使我们决定从众所周知的环境开始,并在使用 Python 时测试它的极限。

说实话,我最终并没有将 RStudio 作为在一般环境下使用 Python 的首选武器。希望下面的文字能传达为什么的信息。然而,我确信对于一些用例,比如以特别分析 R Markdown 的方式集成 R 和 Python, RStudio 仍然是一条可行的道路。

更重要的是,对于在 R 有初级背景的人来说,这可能是一个方便的起跑线

那么,我发现了什么?

分析

包装和环境

首先,让我们设置环境并加载所需的包。

  • 全球环境:
*# Globally round numbers at decimals*
**options**(digits=2)*# Force R to use regular numbers instead of using the e+10-like notation*
**options**(scipen = 999)
  • R 库:
*# Load the required packages.* 
*# If these are not available, install them first.*
ipak <- **function**(pkg){
  new.pkg <- pkg[!(pkg %in% **installed.packages**()[, "Package"])]
  **if** (**length**(new.pkg)) 
    **install.packages**(new.pkg, 
                     dependencies = TRUE)
  **sapply**(pkg, 
         require, 
         character.only = TRUE)
}packages <- **c**("tidyverse", *# Data wrangling*
              "gapminder", *# Data source*
              "knitr", *# R Markdown styling*
              "htmltools") *# .html files manipulation***ipak**(packages)tidyverse gapminder     knitr htmltools 
     TRUE      TRUE      TRUE      TRUE

在这个分析中,我将使用 RStudio 开发的包reticulate 。但是,可以随意寻找的替代品

此外,为了更清晰的流程,我将单独导入reticulate包。

  • Python 激活:
*# The "weapon of choice"*
**library**(reticulate)*# Specifying which version of python to use.*
**use_python**("/home/vg/anaconda3/bin/python3.7", 
           required = T) *# Locate and run Python*
  • Python 库:
import pandas as pd *# data wrangling*
import numpy as np *# arrays, matrices, math*
import statistics as st *# functions for calculating statistics*
import plotly.express as px *# plotting package*

R (Studio) 中使用 Python 的一个限制是,在某些情况下,默认情况下你不会收到 Python 回溯。这是一个问题,因为,如果我把事情过于简化,追溯可以帮助你确定问题出在哪里。意思是它能帮你解决问题。所以,把它当作一个错误信息(或者没有它)。

  • 例如,当调用一个您没有安装的库时,R Markdown 中的 Python 块给了您绿灯(所以一切看起来都在运行),但这并不意味着代码以您期望的方式运行(例如,它导入了一个库)。

为了解决这个问题,我建议确保你已经在Terminal中安装了你的库。如果没有,您可以安装它们,然后再导入。

例如,我将首先导入已经安装在我的机器上的json包。我将在 RStudio 中使用端子来完成此操作。另外,让我试着导入TensorFlow

从下图可以看出没有包TensorFlow。所以,让我切换回 bash 并安装这个包:

然后转到新安装的包TensorFlow所在的目录,切换到 Python ,再次导入包:

好吧。有关更多信息,请查看安装 Python 模块页面。

数据

现在我们已经有了 RPython 集合,让我们导入一些数据来玩玩。我将使用来自 Gapminder 的样本,这是一个关于世界人口社会人口学的有趣项目。更具体地说,我将使用 GapMinder 库中最新的可用数据。

  • R 中的数据导入:
*# Let us begin with the most recent set of data*
gapminder_latest <- gapminder %>%
          **filter**(year == **max**(year))

所以,现在我们在 R 中加载了一个数据。不幸的是,无法通过 Python 直接访问 R 对象(例如向量odtibles)。所以,我们需要先转换 R 对象。

  • Python 中的数据导入:
*# Convert R Data Frame (tibble) into the pandas Data Frame*
gapminder_latest_py = r['gapminder_latest']

当使用 Python 对象(例如数组pandas 数据帧)时,要意识到的一件重要事情是,它们是而不是 显式地存储在环境中的,就像 R 对象一样。

  • 换句话说,如果我们想知道工作区中存储了什么,我们必须调用像dir()globals()locals()这样的函数:
['R', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'contact_window_days', 'contact_window_days_style', 'fig', 'gapminder_latest_count_py', 'gapminder_latest_max_lifeExp_py', 'gapminder_latest_mean_lifeExp_py', 'gapminder_latest_median_lifeExp_py', 'gapminder_latest_min_lifeExp_py', 'gapminder_latest_py', 'gapminder_latest_shape', 'gapminder_latest_stdev_lifeExp_py', 'lifeExpHist', 'np', 'pd', 'px', 'r', 'st', 'sys', 'variable', 'variable_grouping', 'variable_name']

太好了,在现在的对象中,我们可以清楚地看到数据(gapminder_latest_py)或库(如px)。

那么,让我们来探究一下这些数据吧!

预期寿命

出于演示的目的,我将把重点放在预期寿命(T21)或一个人预期的平均寿命上。

描述统计学

让我们从使用 Python 计算一些描述性统计数据开始,如表示中位数数据中的行数:

*# Descriptive statistics for the inline code in Python**## Data Frame Overview**### Number of rows*
gapminder_latest_shape = gapminder_latest_py.shape[0] 
*### Number of distinct values within the life expectancy variable*
gapminder_latest_count_py = gapminder_latest_py['lifeExp'].nunique()*## Life Expectancy**### Median (Life Expectancy)*
gapminder_latest_median_lifeExp_py = st.median(gapminder_latest_py['lifeExp']) 
*### Mean*
gapminder_latest_mean_lifeExp_py = st.mean(gapminder_latest_py['lifeExp'])
*### Minimum*
gapminder_latest_min_lifeExp_py = min(gapminder_latest_py['lifeExp']) 
*### Maximum*
gapminder_latest_max_lifeExp_py = max(gapminder_latest_py['lifeExp'])
*### Standard deviation*
gapminder_latest_stdev_lifeExp_py = st.stdev(gapminder_latest_py['lifeExp'])

很好。不幸的是,我们无法使用 Python 对象进行内联编码,这是R Markdown 的关键特性之一。因此,如果我们想要将结果用于内联代码,我们需要将 Python 对象转换回 R :

*# Descriptive statistics for the inline code in Python - transformed to R**## Data Frame Overview**## Number of rows*
gapminder_latest_nrow_r = py$gapminder_latest_shape
*### Number of distinct values within the life expectancy variable*
gapminder_latest_count_r = py$gapminder_latest_count_py*## Life Expectancy**### Median (Life Expectancy)*
gapminder_latest_median_lifeExp_r = py$gapminder_latest_median_lifeExp_py
*### Mean*
gapminder_latest_mean_lifeExp_r = py$gapminder_latest_mean_lifeExp_py
*### Minimum*
gapminder_latest_min_lifeExp_r = py$gapminder_latest_min_lifeExp_py
*### Maximum*
gapminder_latest_max_lifeExp_r = py$gapminder_latest_max_lifeExp_py
*### Standard deviation*
gapminder_latest_stdev_lifeExp_r = py$gapminder_latest_stdev_lifeExp_py

那么,关于 2007 中的寿命,我们能说些什么呢?

首先,有 142 个国家上榜。预期寿命的最小值39.61 岁,最大值 82.6 岁。

平均预期寿命值为 67.01 岁,平均预期寿命中位数为 71.94 岁或更长。最后,标准差是 12.07 年。

图表(使用 Plotly)

好吧,我们换个话题,比如图表。

例如,我们可以使用Plotly来看看全球的预期寿命是如何分布的:

fig = px.histogram(gapminder_latest_py, *# package.function; Data Frame*
                   x="lifeExp", *# Variable on the X axis*
                   range_x=(gapminder_latest_min_lifeExp_py, 
                            gapminder_latest_max_lifeExp_py), *# Minimum and maximum values for the X axis*
                   labels={'lifeExp':'Life expectancy - in years'}, *# Naming of the interactive part*
                   color_discrete_sequence=['#005C4E']) *# Colour of fill* lifeExpHist = fig.update_layout(
  title="Figure 1\. Life Expectancy in 2007 Across the Globe - in Years", *# The name of the graph*
  xaxis_title="Years", *# X-axis title*
  yaxis_title="Count", *# Y-axis title*
  font=dict( *# "css"*
    family="Roboto",
    size=12,
    color="#252A31"
  ))lifeExpHist.write_html("lifeExpHist.html") *# Save the graph as a .html object*

遗憾的是,无法通过 PythonR Markdown 中打印交互式Plotly图形。或者,更准确地说,你将通过打印(如print(lifeExpHist))得到一个Figure object:

Figure({
    'data': [{'alignmentgroup': 'True',
              'bingroup': 'x',
              'hovertemplate': 'Life expectancy - in years=%{x}<br>count=%{y}<extra></extra>',
              'legendgroup': '',
              'marker': {'color': '#005C4E'},
              'name': '',
              'offsetgroup': '',
              'orientation': 'v',
              'showlegend': False,
              'type': 'histogram',
              'x': array([43, 76, 72, 42, 75, 81, 79, 75, 64, 79, 56, 65, 74, 50, 72, 73, 52, 49,
                          59, 50, 80, 44, 50, 78, 72, 72, 65, 46, 55, 78, 48, 75, 78, 76, 78, 54,
                          72, 74, 71, 71, 51, 58, 52, 79, 80, 56, 59, 79, 60, 79, 70, 56, 46, 60,
                          70, 82, 73, 81, 64, 70, 70, 59, 78, 80, 80, 72, 82, 72, 54, 67, 78, 77,
                          71, 42, 45, 73, 59, 48, 74, 54, 64, 72, 76, 66, 74, 71, 42, 62, 52, 63,
                          79, 80, 72, 56, 46, 80, 75, 65, 75, 71, 71, 71, 75, 78, 78, 76, 72, 46,
                          65, 72, 63, 74, 42, 79, 74, 77, 48, 49, 80, 72, 58, 39, 80, 81, 74, 78,
                          52, 70, 58, 69, 73, 71, 51, 79, 78, 76, 73, 74, 73, 62, 42, 43]),
              'xaxis': 'x',
              'yaxis': 'y'}],
    'layout': {'barmode': 'relative',
               'font': {'color': '#252A31', 'family': 'Roboto', 'size': 12},
               'legend': {'tracegroupgap': 0},
               'margin': {'t': 60},
               'template': '...',
               'title': {'text': 'Figure 1\. Life Expectancy in 2007 Across the Globe - in Years'},
               'xaxis': {'anchor': 'y', 'domain': [0.0, 1.0], 'range': [39.613, 82.603], 'title': {'text': 'Years'}},
               'yaxis': {'anchor': 'x', 'domain': [0.0, 1.0], 'title': {'text': 'Count'}}}
})

所以,我们导入先前创建的。html 文件(例如使用htmltools包中的includeHTML功能):

htmltools::**includeHTML**("lifeExpHist.html") *# Render the graph*

所以,这里有一个基本的,然而是用 Python 版本的Plotly制作的交互式直方图

然而,在 RStudio 中生成这个图表需要一种变通方法。同时,以这种方式产生的图形的大小可以很容易地达到几十兆字节。

  • 因此,包含这些图表的. html 报告需要大量数据来下载给读者,并且需要更多时间来呈现页面

汇总表(使用熊猫)

pandas的一个常见用例是提供数据描述。各自的代码运行良好。但是,由于您在pandas中使用了样式,因此无法对输出进行样式化。

  • 说到pandas,我们可以很容易地为常用的统计数据创建一个汇总表,如个大洲预期寿命的平均值或标准差:
*# Create a pandas Data Frame object containing the relevant variable,*
*# conduct formatting.*

  gapminder_latest_py['continent'] = gapminder_latest_py['continent'].astype(str)
  variable = 'continent'
  variable_name = 'Continents'

  gapminder_latest_py['lifeExp'] = gapminder_latest_py['lifeExp'].astype(int)
  variable_grouping = 'lifeExp'

  contact_window_days = gapminder_latest_py.groupby([
                          pd.Grouper(key=variable)])\
                          [variable_grouping]\
                          .agg(['count',
                                'min',
                                'mean',
                                'median',
                                'std',
                                'max'])\
                          .reset_index()

  contact_window_days_style = contact_window_days\
                          .rename({'count': 'Count',
                                   'median': 'Median',
                                   'std': 'Standard Deviation',
                                   'min': 'Minimum', 
                                   'max': 'Maximum',
                                   'mean': 'Mean',}, axis='columns')

输出:

continent  Count  Minimum       Mean  Median  Standard Deviation  Maximum
  0    Africa     52       39  54.326923    52.0            9.644100       76
  1  Americas     25       60  73.040000    72.0            4.495183       80
  2      Asia     33       43  70.151515    72.0            7.984834       82
  3    Europe     30       71  77.100000    78.0            2.916658       81
  4   Oceania      2       80  80.500000    80.5            0.707107       81

另外,请注意 Python 环境设置覆盖了 R 中的设置。例如,看看均值或标准差的位数。有六个数字,而不是开头的两个数字。

结束语

好了,现在够了。如果你渴望更高级的东西,比如使用 R 中的scikit-learn 进行无监督学习,看看

然而,在结束这篇文章之前,让我说一下,如果你考虑切换到 Python 并经常使用它,考虑一下 IDE 替代 RStudio

许多分析师相信 Jupyter 笔记本 的交互性,集成markdown或选择运行各种语言的代码,如RJuliaJavaScriptJupyterHub 是基于 Jupyter 笔记本的平台,增加了版本控制。通常,用户在集装箱环境中运行分析)。另一个关于交互性和协作的例子可能是 Colab ,基本上就是运行在谷歌云上的 Jupyter 笔记本。

最后,有一个伟大的软件叫做 Visual Studio 代码 。它不仅允许你用多种语言创建和运行代码,或者在纯 Python 代码和交互式 Jupyter 笔记本之间无缝流动。也许更重要的是,它为您提供了非常有效的版本控制管理(比如 Git 集成和扩展)。如果选择这个 IDE,可以像 RStudio 一样设置 VS 代码进行 Python 开发。

但是不管你选择什么样的 Python 之路,不要忘记它是一个适合某些情况的工具,而对其他人可能就不那么适合了。就像 r 一样,在了解不同工具的优点的同时,尽量利用它的优点。

Python 环境 101

原文:https://towardsdatascience.com/python-environment-101-1d68bda3094d?source=collection_archive---------0-----------------------

pyenv 和 pipenv 有何不同,何时应该使用它们

作者图片

**Table of Contents**
🐍 [Introduction](#9ea4)
🐍 [TL;DR](#39b6)
🐍 [pyenv](#f3ad)
🐍 [pipenv](#c002)
🐍 [Conclusion](#e4c6)

[更新:2021 年 8 月 15 日 pyenv 安装]

简介:pyenv vs pipenv vs virtualenv

我当时用的是 Python 3.7.7 + virtualenv,有一天安装了 3.8.2。这给 Jupyter 笔记本带来了麻烦。它不工作,我得到了各种错误信息。

我想我应该整理一下 Python 环境。我需要知道 pyenv、pipenv 和 virtualenv 是做什么的。所以这是我所学到的文章。

Python 在 2019 年发布了 13 个版本,在 2018 年发布了 12 个版本。大多数编程语言都有一些版本管理。

Node 有nvmRuby 有 RVM 等。 pyenv 是 Python 版本管理。

它安装/卸载不同的 Python 版本,设置全局和本地(目录)Python 版本。

pyenv-virtualenv 是一个 pyenv 插件,用于管理类 UNIX 系统上的 Python 虚拟环境。

依赖项管理是管理项目中所有相关库和包的过程,以确保项目成功运行。

pipenv 是 Python 应用的打包工具,管理包依赖关系及其子依赖关系。

pipenv通过在开发环境中使用 Pipfile,在生产环境中使用 aPipfile.lock,简化了开发过程。pipenv 还管理虚拟环境。

virtualenv 是一个创建隔离 Python 环境的工具。如果您在 python 3.8 下安装 virtualenv,virtualenv 将默认创建也是 3.8 版本的虚拟环境。

这意味着如果您升级您的系统 python,您的虚拟环境可能会中断。我升级到 Python3.7.7 的时候也遇到过。

您可以在您的 Python 项目中使用 pyenv 和 pipenv,在本文中,您将了解到从它们的安装到使用的所有内容。正如我之前提到的,pyenv 有自己的 virtualenv,pyenv-virtualenv。

当您单独使用 virtualenv 时,它使用系统 Python 版本。virtualenvwrapper 为 virtualenv 提供了一套有用的脚本。

在本文中,我将重点关注 pyenv 和 pipenv,因为当您更新系统 Python 版本时, virtualenv 会出现问题。

pyenv 是 Python 版本管理+虚拟环境工具,pipenv 是 Python 包管理和虚拟环境工具。

TL;速度三角形定位法(dead reckoning)

pyenv、pipenv 和 virtualenv 图。作者图片

pipenv 创建独立的 pip 环境,而 pyenv+virtualenv 创建多个项目可以使用的 virtualenv。

pyenv

如果您正在处理您的个人项目或者使用一个以上的系统,比如团队或服务器和本地,那么您应该使用 pyenv。

安装 pyenv

可以将 pyenv 安装到 macOS 和其他 Linux OS 。(如果您有任何安装问题,请参见 Github pyenv 安装页面。)

# for macOS
$ brew install pyenv

将以下内容添加到 bash_profile/zshrc 将定义环境变量PYENV_ROOT

对于 zsh,在您的终端中运行以下命令。

$ echo 'eval "$(pyenv init --path)"' >> ~/.zprofile

(这部分可能已经不相关了,我留下来做参考。)

pyenv 的工作原理是在你的路径前面插入一个由垫片组成的目录。一个 shim 是一个小的库,它拦截并改变对另一个库的调用。添加以下内容可以启用填充和自动完成。

$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.zshrc

安装 python 版本

列出可用的 Python 版本

$ pyenv install -l
Available versions:
  2.1.3
  2.2.3
  ...

安装新的 Python 版本

$ pyenv install 3.7.7
$ pyenv install 3.8.2

显示系统中的所有 Python 版本

$ pyenv versions
3.7.7
3.8.2

设置全局 Python 版本

$ pyenv global 3.7.7

验证活动 Python 版本

$ pyenv version
3.7.7 (set by /Users/shinokada/.pyenv/version)

pyenv 快速参考。作者图片

pyenv 本地

pyenv local在目录中创建或修改.python-verion。例如,pyenv local 3.7.7Python 3.7.7. pyenv local 3.8.2创建.python-verion并将.python-verion修改为Python 3.8.2

。python 版本文件

如何创建虚拟环境

如果您正在处理您的个人项目,并且没有安装 pipenv,我建议您安装 pyenv-virtualenv

如果您在一个团队中工作,或者使用不止一个系统,我建议您安装 pipenv,我将在下面介绍它。

pyenv-virtualenv是一个 pyenv 插件,它提供了在类 UNIX 系统上管理 Python 的 virtualenvs 和 Conda 环境的特性。

下面是如何安装 pyenv-virtualenv 的说明。

# For Homebrew users
$ brew install pyenv-virtualenv

然后,您需要将以下内容添加到您的。bash_profile 或. zshrc。

# pyenv-virtualenv
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

您可以通过用 virtualenv 目录的名称指定 Python 版本来创建 virtualenv。

# Create a virtualenv called py377 using Python 3.7.7
$ pyenv virtualenv 3.7.7 py377
# Create a virtualenv called py382 using Python 3.8.2
$ pyenv virtualenv 3.8.2 py382
# Create a virtualenv called jupy based on the global Python version
$ pyenv virtualenv jupy

我经常使用这个命令来创建一个 virtualenv。
$ pyenv virtualenv 3.8.6 py386

本地虚拟

一旦创建了不同的 virtualenv,就可以为一个目录设置一个本地 virtual env。这里我用的是 Oh-My-Zsh 内置命令 [take](/the-ultimate-guide-to-your-terminal-makeover-e11f9b87ac99)

$ take py377
# Set a local(direcotry) python environment to 377
$ pyenv local py377
(py377)$ cat .python-version
py377

设置本地虚拟环境

设置本地虚拟环境

每个 virtualenv 都有不同的 pip 存储

下图中,我在 virtualenv py377 下升级了 pip。在将本地改为 3.7.7 并检查 pip 列表后,它显示了不同的 python 包。

每个 pyenv virtualenv 都有不同的 pip

如何删除本地虚拟机:

通过移除.python-version你可以移除一个本地虚拟。

# remvoing .python-version will set the directory to the global Python version
$ rm .python-version

删除虚拟设备

$ pyenv uninstall my-virtual-env
# or
$ pyenv virtualenv-delete my-virtual-env

pyenv activate 是做什么的?

您可以激活虚拟设备:

# Activate py382
$ ~/pythonproject: pyenv activate py382
# cd to py377 which has local virtualenv py377\. 
# Activated version py382 overrides the local
(py382) $ ~/pythonproject:  cd py377
# confirming the local virtualenv is py377
(py382) $ ~/pythonproject/py377:  cat .python-version
py377
# Deactivate py382
(py382) $ ~/pythonproject/py377: pyenv deactivate
# Now the local virtualenv py377 is used
(py377) $ ~/pythonproject/py377:

当你activate a virtulaenv时,virtualenv 会覆盖本地 virtualenv。

pipenv

如果您的项目依赖于 Python 包版本及其依赖项,那么 pipenv 适合您。

pipenv 创建了一个 Pipfile.lock,您可以在移动到不同的系统时使用它。

Pipfile.lock 包含所有的依赖项及其版本。

当您使用 Pipfile.lock 安装 Python 包时,它将创建与您的原始系统完全相同的环境。

当一个 repo 有一个 Pipfile.lock 时,可以用pipenv install安装所有的包和依赖项。

让我们用自制软件安装 pipenv。你可以在这里找到其他操作系统的安装。

# macOS
brew install pipenv

使用 Python 3.7 创建新项目:

$ pipenv --python 3.7 install

pipenv-python 3 . 7 . 7 安装创建 Pipfile 和 Pipfile.lock

在上图中,我用pipenv --python 3.7.7创建了一个新的虚拟人。它显示虚拟位置:

Virtualenv location: /Users/shinokada/.local/share/virtualenvs/pi37-AdrjAtjU

它创建了 Pipfile 和 Pipfile.lock。pipenv 使用这些 Pipfile 和 Pipfile . lock 来控制 Python 版本和包版本。

pip 文件内容:

cat Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true[dev-packages][packages][requires]
python_version = "3.7"

[source]告诉您的包来源。[包裹]是您的包裹信息。[dev-packages]适合您的开发需求。[requires]是所需的 Python 版本。

Pipfile.lock 内容:

cat Pipfile.lock
{
    "_meta": {
        "hash": {
            "sha256": "7e7ef69da7248742e869378f84218111f8f0017fddf94d086813baa518a65489"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.7"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {},
    "develop": {}
}

一旦你安装了一个包,你可以在 Pipfile.lock 中的default下找到这个包和散列。

作者快速参考

pipenv 与 pyenv 一起工作

如果您的系统没有特定的 Python 版本,它会询问您是否要安装 Python 版本。

$ pipenv --python 3.6
Warning: Python 3.6 was not found on your system…
Would you like us to install CPython 3.6.10 with pyenv? [Y/n]: Y
Installing CPython 3.6.10 with pyenv (this may take a few minutes)…
⠼ Installing python...
$ ls 
Pipfile

pipenv 与 pyenv 一起工作

这将在目录中创建一个 Pipfile。

cat Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true[dev-packages][packages][requires]
python_version = "3.6"

安装软件包

我们用pipenv代替pip来安装包。

$ pipenv install numpy
$ cat Pipfile
...
[packages]
numpy = "*"
...

这就创建了 Pipfile.lock 并将numpy ="*"添加到 Pipfile 中。您可以使用 Pipfile.lock 在不同的系统中创建相同的环境。

安装项目的所有依赖项(包括开发):

$ pipenv install --dev

创建包含预发行版的锁定文件:

$ pipenv lock --pre

显示已安装依赖项的图表:

$ pipenv graph
numpy==1.18.4

检查您安装的依赖项是否存在安全漏洞:

$ pipenv check
Checking PEP 508 requirements…
Passed!
Checking installed package safety…
An error occurred:
Your API Key '1ab8d58f-5122e025-83674263-bc1e79e0' is invalid. See [https://goo.gl/O7Y1rS](https://goo.gl/O7Y1rS)

它返回一个错误,我希望未来的版本可以修复它。

将本地 setup.py 安装到您的虚拟环境/Pipfile 中:

$ pipenv install -e .

使用低级 pip 命令:

$ pipenv run pip freeze

管道外壳和出口

您可以通过运行pipenv shell激活项目的 virtualenv,通过运行exit停用它。

升级软件包的 pipenv shell

如上图所示,可以使用pipenv shell并使用list-U等 pip 命令来升级包。

作者的一些 pip 命令

拆卸管道虚拟管道

$ pipenv --rm
Removing virtualenv (/Users/shinokada/.local/share/virtualenvs/pi37-AdrjAtjU)…

所以你所有的 pipenvs 都存储在~/.local/share/virutlaenvs目录下。

ls ~/.local/share/virtualenvs
pi36-JaecZ40h pi37-AdrjAtjU

如果您愿意,可以从该目录中删除 pipenv。

pipenv 和 pyenv 虚拟冲突

如果你试图在 pyenv 下使用 pipenv,就会发生这种情况。它将显示一个礼貌通知。

$ mkdir demo
$ cd demo
# Python version
$ python --version
Python 3.7.7
# create a virtualenv
$ pyenv virtualenv 3.8.2 demo382
Looking in links: /var/folders/17/2xhf1tw15xzd8sz_0hw3gp2h0000gn/T/tmpcn78j8xb
...
# Set the local virtualenv
$ pyenv local demo382
(demo382) $ python --version
Python 3.8.2# Create pipenv 
$ pipenv --python 3.8
Courtesy Notice: Pipenv found itself running within a virtual environment, so it will automatically use that environment, instead of creating its own for any project. You can set PIPENV_IGNORE_VIRTUALENVS=1 to force pipenv to ignore that environment and create its own instead. You can set PIPENV_VERBOSITY=-1 to suppress this warning.

Pipfile.lock

当您准备将其投入生产时,您需要锁定您的环境,以便您可以确保在生产中使用相同的环境。

$ pipenv lock

这将创建或更新您的Pipfile.lock

一旦您在生产环境中获得了代码和Pipfile.lock,您就可以安装所有的包:

$ pipenv install --ignore-pipfile

这将忽略Pipfile进行安装,并使用Pipfile.lock安装所有软件包。Pipenv 将创建与您的开发环境完全相同的环境,包括子依赖项。

结论

pyenv,pipenv 图。作者图片

上图左侧,pyenv + pyenv-virtualenv 可以容纳不同的项目。

这意味着 pyenv-virtualenv 可以与不同的项目共享包。而在 pyenv+pipenv 上,每个项目都拥有自己的 pip/包,没有共享。

如果你在一个团队中工作,那么你应该一起使用 pyenv+pipenv。

如果您的项目涉及多个系统,比如本地和远程服务器,那么您也应该使用它们。

因此,简而言之,如果您的项目涉及多个系统,您应该使用 pyenv+pipenv。

pyenv 和 pipenv 创建 virtualenvs 的方式不同,但您可以同时使用这两种方式。

还有其他可用的工具,它们有不同的范围和用途,如下图所示。

https://github.com/David-OConnor/pyflow

通过 成为 会员,可以完全访问媒体上的每一个故事。

请订阅。

[## 7 个强大的 Rust 驱动的命令行工具

适合每个开发人员的现代 Linux 命令

towardsdatascience.com](/awesome-rust-powered-command-line-utilities-b5359c38692) [## 终端改造的终极指南

今天你将度过的最好的 11 分钟:程序员的终端提示

towardsdatascience.com](/the-ultimate-guide-to-your-terminal-makeover-e11f9b87ac99) [## 为您的数据科学项目安排任务的分步指南

macOS/Linux 中 cron 和 launchd 的完整指南

towardsdatascience.com](/a-step-by-step-guide-to-scheduling-tasks-for-your-data-science-project-d7df4531fc41)

参考

Python ETL 工具:最佳 8 个选项

原文:https://towardsdatascience.com/python-etl-tools-best-8-options-5ef731e70b49?source=collection_archive---------0-----------------------

想用 Python 做 ETL?这里有 8 个很棒的图书馆

ETL 是从一个或多个系统获取数据,并在进行一些中间转换后将其加载到目标数据仓库的过程。市场上有各种 ETL 工具可以执行这个过程。

一些工具提供完整的端到端 ETL 实现,一些工具帮助您从头开始创建自定义 ETL 过程,还有一些选项介于两者之间。在本帖中,我们将看到一些常用的 Python ETL 工具,并了解在哪些情况下它们可能非常适合您的项目。

在浏览 Python ETL 工具列表之前,让我们首先了解任何 ETL 工具都应该具备的一些基本特性。

ETL 工具的特性

ETL 代表提取、转换和加载,因此任何 ETL 工具至少应该具有以下特性:

提取

这是从各种来源提取数据的过程。一个好的 ETL 工具支持各种类型的数据源。这应该包括大多数数据库(基于 NoSQL 和 SQL 的)和文件格式,如 csv、xls、xml 和 json。

改变

提取的数据通常保存在暂存区,原始数据在这里被清理并转换成有意义的形式,以便存储在数据仓库中。标准的 ETL 工具支持所有基本的数据转换特性,如行操作、连接、排序、聚合等。

负荷

在加载过程中,转换后的数据被加载到目标仓库数据库中。标准 ETL 工具支持各种数据库的连接器,如 Snowflake、MS SQL 和 Oracle。

其他附加功能

除了基本的 ETL 功能之外,一些工具还支持额外的特性,比如用于可视化和跟踪各种 ETL 管道的仪表板。事实上,除了 ETL 之外,一些工具还提供了执行并行或分布式处理的能力,在某些情况下甚至是基本的分析,根据您的项目需求,这些都是很好的附加组件。

Python ETL 工具

Python 是一种相对容易学习和使用的编程语言。Python 在 GitHub 上有一个非常活跃的开源社区,定期推出新的 Python 库和增强功能。由于这个活跃的社区和 Python 的低难度/功能比,Python 现在在许多不同的领域都引人注目,如游戏开发、web 开发、应用程序开发、NLP 和计算机视觉等等。

近年来,Python 已经成为数据处理、数据分析和数据科学(尤其是强大的 Pandas 数据科学库)的流行编程语言选择。因此,有大量的 Python ETL 工具可供选择就不足为奇了。我们来看看最常见的。

Petl

Petl(代表 Python etl)是一个基本工具,它提供了从不同来源(如 csv、XML、json、text、xls)向数据库导入数据的标准 ETL 功能。就功能而言,它微不足道,并且不像列表中的其他工具那样提供数据分析功能。但是,它支持所有标准的转换,如行操作、排序、连接和聚合。

对于一个简单的工具来说,Petl 还不错,但是它可能会遇到性能问题;尤其是与其他一些选择相比。因此,如果您只需要构建一个简单的 ETL 管道,并且性能不是主要因素,那么这个轻量级工具应该可以完成这项工作。但是对于任何更复杂的东西,或者如果你期望项目的范围扩大,你可能想要继续寻找。

熊猫

熊猫标志,一个对 ETL 有用的 Python 库

Pandas 是当今最流行的 Python 库之一,也是我个人的最爱。我用它来处理水文数据、天体物理数据和无人机数据。它越来越受欢迎很大程度上是因为它在数据科学中的使用,这本身就是一个快速发展的领域,也是我第一次遇到它的原因。

Pandas 使用数据帧作为数据结构来保存内存中的数据(类似于 R 编程语言中处理数据的方式)。除了常规的 ETL 功能,Pandas 还支持大量的数据分析和可视化特性。

Pandas 相对容易使用,并且具有许多丰富的功能,这就是为什么它是数据科学家进行简单 ETL 和探索性数据分析的常用工具。如果您已经在使用 Pandas,它可能是部署概念验证 ETL 管道的一个好的解决方案。

玛拉

Mara 是一个轻量级的 Python ETL 工具,但是仍然提供了创建 ETL 管道的标准特性。它还提供了其他内置功能,如基于 web 的 UI 和命令行集成。Web UI 有助于可视化 ETL 管道执行,这也可以集成到基于 Flask 的应用程序中。它使用 PostgreSQL 作为数据处理引擎。

如果你正在寻找一个简单的 ETL 工具,但仍然有一些复杂的功能,那么 Mara 可能是一个不错的选择。

气流

阿帕奇气流的标志

Apache Airflow 由 Airbnb 创建,是一款开源的工作流管理工具。它可以用来创建数据 ETL 管道。严格地说,它本身不是一个 ETL 工具,相反,它更像是一个编排工具,可以用来创建、调度和监控工作流。这意味着您可以使用 Airflow 通过整合您的 ETL 过程的各种独立编写的模块来创建管道。

气流工作流遵循 DAG(有向无环图)的概念。与列表中的其他工具一样,Airflow 也有一个基于浏览器的仪表板,用于可视化工作流和跟踪多个工作流的执行。如果您想通过将独立的和现有的模块链接在一起来创建一个复杂的 ETL 工作流,Airflow 是一个不错的选择

Pyspark

PySpark 标志

Pyspark 是运行在 Python 上的 spark 版本,因此得名。根据他们的网站,“Spark 是用于大规模数据处理的统一分析引擎。”

Spark 内核不仅为创建 ETL 管道提供了强大的功能,还支持数据流(Spark Streaming)、SQL (Spark SQL)、机器学习(MLib)和图形处理(Graph X)。

使用 Pyspark 的主要优点是可以快速处理大量数据。因此,如果您希望创建一个 ETL 管道来快速处理大数据或处理数据流,那么您绝对应该考虑 Pyspark。也就是说,它不是现成的 ETL 解决方案,而是 ETL 管道部署的一部分。

倭黑猩猩

Bonobo Python ETL 工具的徽标

Bonobo 是一个使用 Python 构建的轻量级 ETL 工具。它很简单,也相对容易学习。它使用图形概念来创建管道,并且还支持管道中多个元素的并行处理。它还有一个可视化界面,用户可以在其中跟踪 ETL 管道的进度。

总而言之,它只是另一个易于使用的 ETL Python 工具,对于简单的用例来说,这可能是一个很好的选择,但没有太多突出的功能来将其与包分开。
(是的,我们的名单中既有熊猫也有倭黑猩猩)

路易吉

Luigi Python ETL 工具的徽标

Luigi 是一个基于 Python 的 ETL 工具,由 Spotify 创建,但现在作为开源工具提供。它是一个比这个列表中的许多工具更复杂的工具,并且具有创建复杂 ETL 管道的强大功能。根据他们的 Github 页面,“它处理依赖关系解析、工作流管理、可视化、处理故障、命令行集成等等”

它还带有一个 web 仪表板来跟踪所有的 ETL 作业。如果你正在寻找建立一个企业解决方案,那么 Luigi 可能是一个不错的选择。

奥多

Odo 是一个 Python 工具,可以将数据从一种格式转换成另一种格式。但是它主要值得注意的特性是在将巨大的 csv 数据集加载到各种数据库时的性能。

正如他们在自己的网站上描述的:“Odo 使用它所支持的数据库的本地 CSV 加载能力。这些装载机速度极快。在加载大型数据集时,Odo 将击败任何其他纯 Python 方法。”

我没有做过性能测试来验证这些说法,但如果有人做过,请在评论中分享。但是不管怎样,它的用例似乎很清楚:如果您正在寻求创建一个简单的管道,重点是将巨大的 csv 数据集加载到您的数据仓库中,那么您应该尝试 Odo。

惊喜选项:通过数据虚拟化跳过 ETL

听起来可能很奇怪,一些公司已经完全放弃使用 ETL,转而支持通过 数据虚拟化 进行直接集成。

数据虚拟化是一个逻辑数据层,它跨不同的孤岛集成数据。数据虚拟化管理统一数据,并通过集中的安全性和治理将数据交付给用户。

Denodo 提供数据虚拟化作为数据管理/工程选项。

结论

正如您所看到的,有很多 Python ETL 工具可供选择,每种工具都有自己的特点和缺点。无论您只是在寻找标准的 ETL 功能,还是在寻找更多的附加功能和复杂性,Python 都可能是一个不错的选择。

Python ETL 与 ETL 工具

原文:https://towardsdatascience.com/python-etl-vs-etl-tools-9709171c9e58?source=collection_archive---------8-----------------------

你应该自己编码还是授权一个 ETL 工具?

选择你的方向:自己编码你的 ETL 管道或者使用现有的 ETL 工具

如果你正在研究 ETL 解决方案,你将不得不决定是使用现有的 ETL 工具,还是使用其中一个 Python ETL 库构建自己的 ETL 工具。在这篇文章中,我们来看看在做决定时需要考虑的一些因素。

ETL(提取转换负载)是为数据仓库创建数据管道的最重要的方面。市场提供了各种现成的 ETL 工具,可以很容易地在数据仓库中实现。然而,最近 Python 也成为创建定制 ETL 管道的一个很好的选择。在本文中,我们将快速比较 Python ETL 和 ETL 工具,以帮助您在项目中选择两者。

ETL 工具

市场上有许多现成的 ETL 工具可以用来构建容易复杂的数据管道。大多数提供友好的图形用户界面,具有丰富的管道构建功能,支持各种数据库和数据格式,有时甚至包括一些有限的商业智能功能。最棒的是,所有这些都是现成的。

这些工具可以是许可的,也可以是开源的。他们中的大多数都采用订阅模式,从每月几百美元到每月几千美元不等。另一方面,开源工具是免费的,它们也提供了一些许可工具所提供的特性,但是通常需要更多的开发才能达到类似的结果。

市场上一些可用的 ETL 工具如下。

信息动力中心

Informatica 的 ETL 解决方案是目前最常用的数据集成工具,用于连接和检索来自不同数据源的数据。Informatica 在这个行业已经有很长时间了,并且是这个领域的一个成熟的参与者。他们有针对 ETL、数据屏蔽、数据质量、数据复制、数据管理等的数据集成产品。

阿洛玛

Alooma 是一款授权的 ETL 工具,专注于将数据迁移到云中的数据仓库。Alooma 似乎是许多企业的一个很好的解决方案,它的自动化数据管道以及与 Amazon Redshift、Microsoft Azure 和 Google BigQuery 的简单集成。然而,在 2019 年被谷歌收购后,Alooma 在很大程度上放弃了对非谷歌数据仓库解决方案的支持。这可能会给依赖多个云平台的公司带来问题。

Xplenty

Xplenty 是一个基于云的 ETL 和 ELT(提取、加载、转换)工具。它使用可视化界面来构建数据管道,并连接到 100 多个常见数据源。

AWS 胶水

AWS Glue 是亚马逊基于 AWS 平台的无服务器 ETL 解决方案。如果你已经在 AWS 生态系统中根深蒂固,AWS Glue 可能是一个不错的选择。

Python ETL

Python 无需介绍。每年 Python 在越来越多的领域变得无处不在,从天体物理学到搜索引擎优化。所以 Python 有 ETL 的解决方案也就不足为奇了。

对于 ETL,Python 提供了一些健壮的开源库。得益于不断增长的 Python 开源社区,这些 ETL 库提供了大量特性来开发健壮的端到端数据管道。

如果您对 Python 了如指掌,您可以创建复杂的 ETL 管道,类似于使用 ETL 工具所能完成的事情。但是要准备好消耗一些开发时间。这些库功能丰富,但不像上面列出的一些 ETL 平台那样现成可用。

一些流行的 python ETL 库有:

  • 熊猫
  • 路易吉
  • Petl
  • 倭黑猩猩
  • 气泡

这些库已经在关于 Python ETL 选项的其他帖子中进行了比较,所以我们在这里不再重复讨论。相反,我们将关注是使用这些还是使用已建立的 ETL 平台。

Python ETL 与 ETL 工具

在设计数据仓库策略时,必须仔细选择 ETL 的策略。一旦你选择了一个 ETL 过程,你就被套牢了,因为将它移植到另一个平台需要花费大量的开发时间。对于具有许多模式和复杂体系结构的企业数据仓库来说尤其如此。

因此,让我们比较一下定制 Python ETL 和 ETL 工具的有用性,以帮助做出选择。

费用

ETL 工具(尤其是大型企业数据仓库)的许可成本可能很高——但这一费用可能会被您的工程师在其他事情上节省的时间所抵消。较小的公司或创业公司可能不总是能够负担得起 ETL 平台的许可费用。在这种情况下,创建一个定制的 Python ETL 可能是一个不错的选择。但是,同样重要的是,要考虑这样节省的成本是否值得推迟产品上市。初创公司的另一个考虑因素是,像 Avik Cloud 这样定价更灵活的平台可以保持成本与使用成比例——这将使 ETL 需求有限的早期初创公司更加负担得起。

数据仓库的规模和复杂性

如果它是一个具有复杂模式的大型数据仓库,从头开始编写一个定制的 Python ETL 过程可能会很有挑战性,尤其是当模式更改更加频繁时。在这种情况下,您应该从各种 ETL 工具中探索适合您的需求和预算的选项。

简单和灵活

如果数据仓库很小,您可能不需要企业 ETL 工具的所有特性。编写一个定制的轻量级 Python ETL 过程可能是一个好主意,因为它既简单又能让您更灵活地根据自己的需要进行定制。

可量测性

数据库的初始大小可能不大。但是如果您预计在不久的将来会有增长,那么您应该判断您的定制 Python ETL 管道是否也能够随着数据吞吐量的增加而扩展。如果有疑问,您可能希望更仔细地研究一些 ETL 工具,因为它们更容易扩展。

用户友好性

正如您可能猜到的那样,要将 Python 用于您的 ETL 过程,需要 Python 方面的专业知识。但是 ETL 工具通常有用户友好的图形用户界面,即使对于非技术人员来说也很容易操作。因此,这是一个根据项目需求做出的选择。

增值和支持

ETL 工具,尤其是付费工具,在多种特性和兼容性方面提供了更多的附加值。他们还提供客户支持——这似乎是一个不重要的考虑,直到你需要它。然而,开源工具确实有很好的文档和大量也能提供支持的在线社区。

如果您使用定制的 Python ETL,您将会错过这些东西。将如此多的市场 ETL 工具的特性整合到具有相同健壮性的定制 Python ETL 过程中是一项具有挑战性的工作。

令人惊讶的第三个选项:数据虚拟化

另一个越来越受欢迎的选择是完全放弃 ETL,转而支持 数据虚拟化 。数据虚拟化是一个逻辑数据层,它跨不同的孤岛集成数据。数据虚拟化管理统一数据,并通过集中的安全性和治理将数据交付给用户。

Denodo 提供数据虚拟化作为数据管理/工程选项。

结论

谈到 Python ETL 和 ETL 工具,没有明显的赢家,它们都有各自的优点和缺点。最后,这一切都归结为基于我们上面讨论的各种参数做出选择。但是,如果您强烈考虑使用 Python 进行 ETL,至少要看看现有的平台选项。如果你觉得特别大胆,可以考虑深入兔子洞,学习一些关于数据虚拟化的知识。同样,如果您正在考虑将 ETL 工具用于简单的 ETL 用例,那么仔细研究一下 Python 可能是值得的。

Python 日常

原文:https://towardsdatascience.com/python-everyday-fa8946524532?source=collection_archive---------31-----------------------

招数、代码优化、面试问题等

Unsplash 上由 Hitesh Choudhary 拍摄的照片

Python 是初学者觉得非常容易上手的语言之一。它是一种解释的、面向对象的高级编程语言。

在本帖中,我们将讨论面试问题、执行操作的 python 技巧、如何优化代码等等。

那么,事不宜迟,让我们开始吧:

1)优化和分析:

我在采访中经常遇到这个问题——如何优化 python 代码。嗯,我通常更喜欢依靠标准的最佳实践尽早构建数据处理管道(我将在本文后面讨论)。然后,开始识别可能以下列形式存在的低效率:

  • 一条语句— timeit (在结尾的多个示例中演示了这一点)
  • 代码的某一部分——cProfile

让我们先学习代码剖析。

什么是个人资料?根据 python 文档:

概要文件是一组统计数据,描述了程序的各个部分执行的频率和时间。

我们将看到如何使用标准库 cProfile 对给定的 python 函数评估概要文件。

让我们以斐波那契数列为例来说明轮廓是怎样的:

斐波那契数列剖析

轮廓输出

输出中的第一行告诉我们总共监控了多少个调用,其中有多少是原始的。这表明代码中存在递归(因为 180 个调用中只有 4 个是原语调用)。

PyCallGraph 是剖析代码的另一种方式,并且更容易解释,因为输出是 png 图形图像的形式。我们不会在这里讨论太多,因为这超出了这篇文章的范围,更多的可以在这里阅读

2) 用装饰器缓存结果:

继续上面关于优化的讨论,它需要分析代码的运行时间和内存配置文件。如果代码有较长的运行时间和大量的内存使用,它被称为是昂贵的。

然后对应用程序进行分析,以识别具有优化空间的昂贵代码。提高代码速度的典型方法是缓存罪魁祸首(是的!!!,对我们来说是)。

缓存的目的是存储计算量很大的结果。因此,它们只需计算一次,通过称为 Decorators 的包装器进行缓存和检索。

装饰器是一个函数,它的输入和输出也是一个函数。

装饰斐波那契示例

3) Join()组合字符串:

字符串是不可变的。这意味着每当 2 个字符串被连接时;由于不能就地修改,因此会创建一个新的表示。还要注意,字符串连接的时间度量是连接操作次数和字符串平均长度的函数。

使用“Join”连接字符串,因为它比“+”运算符更快

串并置

4)计数器

如果您想通过添加公共关键字的值来合并两个字典,则“+”运算符不起作用。

例如,A+B 在下面的代码中抛出错误,但可以使用计数器实现:

合并两个字典的计数器

同样,我们也可以找到 A 和 B 的交集和并集。

使用“Counter”的另一个非常基本的应用是当我们传递一个字符串作为输入来计算字符串中每个字母的出现次数时,例如“python”:

字符串计数

可以使用 OrderedDict 来计算每个字母表在字典中出现的顺序:

有序直接

计数器也可以通过展平来计算字典中每个元素的出现次数:

对字典值进行扁平化后的元素进行计数

5)变量交换

避免创建临时变量来交换变量。为了通过一个例子来理解它,让我们看看表达式的交换是如何发生的

x,y = y,x

步骤 1:首先计算右边的 y,x,这在内存中创建了一个 2 元素元组。这两个元素是被标识为 y 和 x 的对象,供 Python 内部处理。

步骤 2:在左侧表达式的求值过程中,元组被分配到左侧,并首先被解包到 x 中,然后是 y 中

变量交换

6) 列表 vs 德格:

Deque 是双端队列,支持内存高效追加和从两边弹出。

列表:在列表的末尾插入是有效的,但是,当一个新元素被插入到列表的前面时,所有后面的元素索引都移动 1

这里 deque 派上了用场,它是一个双链表,速度更快。

列表与队列

7) ' in '关键字

“in”关键字是检查元素是否存在的最快、最干净的方法。

在'与'得到'中

8)映射、减少和过滤关键字

过滤器输出包含满足给定条件的元素的新列表。

Map 对象用于将给定的函数,在我们下面的例子中,一个指数函数,投射到指定的 iterable 的每一项。

Reduce 通过将函数应用于 iterable 返回单个值。它被标记为 reduce,因为它将 iterable 中的元素减少到一个累积值

映射、减少和过滤

9) 发电机的使用:

为了理解生成器,让我们首先理解可迭代的。例如,逐个读取列表的元素被称为迭代,其中列表是可迭代的。但是 iterable 的问题是,它将所有可能并不总是需要的值存储在内存中,因此产生了生成器的角色。

生成器是迭代器的一个子类,它可以动态生成值。这可以节省内存并提高性能。

例如,在视频流以记录盗窃的情况下,人们不是对每个图像都感兴趣,而是只对可能发生盗窃的图像感兴趣。因此,它就像一个正在进行的过程,其中只有某个事件相关的信息需要分析,而不是整个输入需要预先存储。

也可能是这样的情况,我们最初生成一个数字列表,但是基于算法,只使用了一些元素。这导致了在生成这些数字时 CPU 周期的浪费。不仅如此,大量内存被用来同时存储对象中的这些数字。

更多关于提高代码效率的提示不言自明:

  • Python 检索局部变量比检索全局变量更快。每次需要全局对象时,访问全局对象都要进行一次完整的查找,从而降低了速度。
  • 列表理解更快,因为它不需要加载 append 并作为函数调用。查找、加载和函数调用是一个耗时的过程,它会增加迭代次数。
  • 在‘if else’之上尝试 except
  • 交集 vs ' &'运算符:

“交叉点”上的“&”

  • 开箱操作员:

使用*作为解包运算符

而且,还有很多。正如他们所说,学习是永无止境的。我将继续写更多关于 Python 及其海量的文章。

在那之前,继续你的旅程,成为一个狂热的“Pythonista”。

PS: 我添加了 python 代码片段来说明概念,而不是创建多个 gists。如果能知道创建多个更小的 gists 来解释每个概念是唯一的演示方式还是有更快的解决方法,那就太好了。

全部代码放在 jupyter 笔记本这里

感谢阅读。

参考资料:

Python 初学者-基础知识

原文:https://towardsdatascience.com/python-for-beginners-basics-7ac6247bb4f4?source=collection_archive---------33-----------------------

了解变量、集合、循环等等

通过 Unsplash 的原始图像

  1. 介绍
  2. 入门指南
  3. 变量
  4. 基本操作
  5. 收集
  6. 经营者
  7. 条件语句
  8. 有用的东西

介绍

Python 是一种面向对象的、解释性的高级语言,具有简单的语法和强大的功能。使用 Python,我们可以用更少的努力和更多的可读性来构建复杂的应用程序。

既然我们知道了什么是 Python?我们来探讨一下为什么要用?

  • 高级 大部分 Python 组件都取自自然语言——我们用来交流的语言。与其他语言相比,这使得 Python 更容易学习。
  • 解释 Python 逐行编译代码——这使得识别错误变得容易,同时,与其他代码相比,速度有点慢。
  • 简单的语法
    如果你是一名经验丰富的开发人员,现在正试图学习 Python,这将比你已经在学习的语言更加直接和简单。但是如果你是编程新手,我认为你从 Python 开始是幸运的。你找不到比 Python 更简单又强大的语言了。
  • 动态语义
    如果你是一个典型的传统编码者,你知道我们应该在使用之前初始化任何东西。在 Python 中,这一切都是动态发生的。

入门指南

我建议您使用 PyCharm IDE,因为您正在学习 Python,您可以从这里的下载它。安装和配置 IDE 很简单,但是当涉及到解释器时,不要浪费你的时间试图自己做所有的事情,相反,看这个视频。它提供了如何正确设置 Python 环境的分步说明。

现在我们已经完成了 IDE 安装,让我们从底层开始编程。

变量

变量不过是一个带有值的词。就这么简单;与 java 不同,我们不需要提及变量的数据类型,如intStringFloat

假设你想在一个变量中存储一个值 10——请看:

声明变量

Python 的动态语义自动将变量视为Int。现在我们知道了如何声明一个变量并给它赋值,下一步是探索不同的变量类型。

IntFloatStringBoolean 是 python 支持的基本数据类型。看看如何声明它们并给它们赋值:

Python 中的基本数据类型

多亏了 Python 的简单语法——我们可以用不同的数据类型在单个变量中声明多个变量。看一看:

基本操作

既然我们已经学习了如何创建变量,是时候探索基本的功能了——找出字符串的长度,将字符串转换成大写或小写,等等。

  • 字符串长度: Python 包含一个名为len()的函数,返回给定容器中的物品数量。在我们的例子中,容器是字符串,返回值是它的长度。看一看:

寻找字符串的长度

  • 索引:我们可以使用索引找到字符串中特定位置的值或字符。我们需要记住的主要事情是索引是从零开始的。看一看:

索引演示

  • 连接:我们可以使用加号(+)在 python 中连接两个字符串。它类似于 Java 和 Kotlin 语法。看一看:

串并置

  • 切片:切片是 Python 中的一个优秀特性,通过它我们可以使用它们的索引得到字符串的各个部分,如下所示:

分割字符串

  • Strip: 使用strip我们可以删除字符串中的前导和尾随空格。如果你只想删除前导空白,我们可以使用lstrip()或者删除尾随空白;我们可以用rstrip()

条形函数的用法

  • 查找&替换:这些是任何编程语言中的标准功能— find用于验证期望值是否在实际值中,而replace用于删除特定值,然后在该位置添加期望值。看一看:

查找和替换用法

  • 转换:我们可以分别使用upper()lower()title()函数将字符串转换成大写、小写或标题大小写。

转换函数的使用

收集

到目前为止,我们已经看到了可以保存单个值的变量的不同用法。但是,如果我们想要存储一个值列表,那该怎么办呢——这就是集合的用途。

Python 中有四种集合类型:

1)列表

该列表是可以随时更新的值的集合。在 Python 中,列表用方括号表示。看一看:

列出具有相同数据类型的集合

列表可以包含任何数据类型,如下所示:

具有不同数据类型的列表集合

我们可以在列表上执行一些有用的操作,比如添加或删除数据、对列表进行排序以及在特定索引处插入数据。看一看:

对列表的操作

2)元组

tuple 类似于 list,但是一旦初始化就不能添加数据,它由圆括号表示,如下所示:

元组演示

我们可能不会添加/删除元组中的数据,但是我们可以做一些有用的事情,比如查找最大/最小值、元组中某个项目的计数以及某个项目的索引。看一看:

元组上的操作

3)设置

集合是一个没有索引和无序的集合。In 集合不允许重复值。Set 由大括号表示,如下所示:

简单集合用法

与其他集合类型类似,我们可以添加、删除和更新集合中的数据。看一看:

布景上的操作

4) 字典

与其他类型相比,字典是一种不同的集合类型。集合包含键值对形式的数据。如果你是一个 java 或 Kotlin 程序员,重复的条目是不允许的——就像hashmap

基本词典用法

我们可以分别用两个独特的函数keys()values()来获取字典中的所有键或值。看一看:

字典上的操作

经营者

逻辑运算符

逻辑运算符是任何语言中的基本运算符之一。Python 有三个逻辑运算符,比如andornot

  • and: 如果所有状态都为真,则返回真。

和操作员行为

  • 或:如果任一语句为真,则返回 true。

或者操作员行为

  • not: 反转结果,假设为真,则返回 false。

标识运算符

python 中有两个标识操作符— isis not

  • is:如果两个变量相同,则返回 true。
  • is not:如果两个变量不相同,则返回 true。

标识运算符

这里我们将探索 Python 中的whilefor 循环。两者功能相似,但语法不同。

while 循环

while 循环重复执行一系列语句,直到满足给定条件。看一下语法:

while condition:
    statement(s)

while 循环用法

这里的i ≤ 5是条件。最初,I 值为 1,并且在每次迭代中,I 增加 1。在第 5 次迭代时,I 值为 6,条件失败,因此循环终止。

for 循环

for 循环用于顺序迭代。它主要用于迭代集合。

for iterator_var in sequence:
    statements(s)

这里的序列是一个集合,对于每次迭代,集合中该索引处的值将被赋给iterator_var,我们可以在内部语句中访问它。迭代在列表的最后一个索引处终止。

让我们来做一个简单的 for 循环示例——我们有一个编号为 1、2、3、4 的列表,这里的目标是使用 for 循环获得列表中各项的总和。看一看:

对于循环使用

条件语句

一些基本的 Python 条件语句有ifelifcontinuebreak。让我们看看如何使用它们:

如果

一个if语句是用if关键字写的,后跟条件,以冒号结尾。如果条件满足,那么里面的语句就会执行。与条件相反,我们可以使用else关键字执行另一组语句,如下所示。

if-else 用法

否则如果

当我们需要满足两个以上的条件时,关键字就派上了用场。让我们以上面的例子为例,如果i是零,它显示为偶数,但 0 既不是偶数也不是奇数——这可以使用如下所示的elif来解决:

elif 用法

继续

continue是循环中派上用场的关键字。有了这个关键字,我们可以跳过当前的迭代。看一看:

继续使用

破裂

break 类似于continue,但是当你调用break而不是跳过当前的迭代时,它将终止整个循环。

中断使用

有用的东西

打印

我们已经看到了使用 print 在控制台中显示数据的两种方法——一种是将值直接传递给打印函数,另一种是传递逗号分隔的参数。看看吧,如果你不记得了:

基本打印用法

我们需要在静态字符串中间打印动态值。这可以通过两种方式实现,比如字符串格式和百分比符号的使用。看一看:

print 语句中的字符串格式

如果您观察清楚,在第一种方法中有额外的尾随零,这是因为 Python 将值显示为浮点数。我们可以限制小数点,如下所示:

评论

在使用任何语言时,开发人员都会在代码中加入注释,以便其他开发人员能够理解。Python 提供了两种类型的注释——单行和多行。

  • 单行:这类评论以#开头,如下图:

单行注释

  • 多行:这种类型的注释对于编写关于函数的冗长解释或者注释一段代码非常有用。三重引号表示消息开头和结尾的多行注释。看一看:

多行注释

范围

range()是 Python 中的内置函数。简单来说,range()允许用户在给定范围内生成一系列数字。一般来说,它是用来循环的,看看:

范围使用

希望你学到有用的东西,感谢阅读。

你可以在TwitterQuoraLinkedIn 上找到我。

Python 初学者——控制语句

原文:https://towardsdatascience.com/python-for-beginners-control-statements-6feadf4ac4c?source=collection_archive---------41-----------------------

了解从基础到高级的条件执行

照片由 Unsplash 上的 Yancy Min 拍摄

介绍

对于编写顺序执行的程序来说,这个世界通常是一个复杂的地方。不管你在做什么项目,都需要跳过一些语句,然后递归地执行一系列语句。

这是任何语言中条件语句出现的地方;通常,大多数语言都有一个 if 语句作为开始的基本步骤,Python 也是如此。不再拖延,让我们探索用 Python 编写条件语句的不同方法。

If声明

简单来说,if 语句是两个部分的组合:表达式和语句。

表达式:需要计算并返回布尔值(真/假)的条件。

语句:语句是一个通用的 python 代码,当表达式返回 true 时执行。

if 语句的语法如下所示:

if <**expression**>:
    <**statement**>

请始终记住,表达式后面的冒号(:)是强制的,要将它放到操作中,我们可以做如下所示的事情:

python 中简单的 if 语句

如果表达式返回 true,我们还可以执行多个语句,请看:

if 块用多个语句执行

为了有趣,我们可以在一行中编写各种语句,用分号分隔,请看:

在单行中包含多个语句的 if 块

我们还可以使用 if 语句,通过使用in操作符来检查一个值是否在字典中。看一看:

“else”和“elif”

使用 if 语句,我们可以执行一组选定的语句,但是如果我们希望在条件失败时执行另一组语句,该怎么办呢?这时候else进来了。看一下语法:

if <**expression**>:
    <**statement1**>
else:
    <**statement1**>

类似于 if 语句我们需要在 else 后面使用冒号(:)并保持缩进,看一个简单的例子:

简单的 if / else 执行

让事情变得复杂一点,如果我们需要检查不止一个条件呢?那就是elif曝光的时候。elif充当 if /else 块的组合。

如果前面的条件不满足,并且满足当前表达式,则执行elif块下的语句块。看一下语法:

if <expression>:
    <statement1>
**elif** <expression>:
    <statement2>
**elif** <expression>:
    <statement3>
    ...
else:
    <statement4>

让我们写一段简单的代码来更好地理解它。

简单 elif 分组码

使用“get”进行条件执行

到目前为止,我们已经看到了通用的解决方案;为了让事情变得更复杂一点,我们可以在字典上使用get函数。这个过程包括将必要的条件和输出作为键值对包含在字典中。

为了更好地理解它,让我们写一个简单的例子,看一看:

在这里,字典表情符号充当指示表达式和语句执行的键值对。当我们以 input 作为第一个参数调用字典上的 get 函数时,它将检查具有该值的键。如果找到了,它打印键值,否则打印第二个参数。这里,第二个参数充当 else case。

三元运算符

Python 引入了一个三元运算符来保持最小化。换句话说,我们可以说它是 if / else 块的最简单的书写形式。

当我们深入研究控制语句时,我们需要考虑三件主要的事情:条件表达式、肯定结果和否定结果。整个条件执行都围绕着他们。让我们看看 Python 中三元运算符的语法:

<**positive_result**> if <**conditional_****expression**> else <**negative_result**>

这个操作符旨在减少样板代码,创建一个更简洁、可读性更强的程序。让我们用三元运算符写一个简单的例子:

奖金

要了解更多关于 Python 从基础到高级的知识,请阅读以下文章

就这些了,希望你能学到一些有用的东西,感谢阅读。

你可以在 MediumTwitterQuoraLinkedIn 上找到我。

面向初学者的 Python 函数

原文:https://towardsdatascience.com/python-for-beginners-functions-2e4534f0ae9d?source=collection_archive---------25-----------------------

python 中的函数式编程

  1. 什么是函数式编程?
  2. Python 中的第一个函数
  3. 函数和变量
  4. 带参数的函数
  5. 有返回值的函数
  6. 用作参数和返回值
  7. 内部函数
  8. λ函数
  9. 地图和过滤功能
  10. 装饰者

#1 什么是函数式编程?

函数式编程是一种编码范式,其中我们定义做什么,而不是执行动作。这个想法最初来自数学——我们定义函数的输入和我们期望的输出。

函数式编程很少依赖于状态管理——这意味着当我们传递相同的参数时,无论输出多少次都是相同的。它可以被解释为数据正在经历一些转换,最终导致所需的输出。

#2 你在 Python 中的第一个函数

虽然 Python 主要不是函数式语言,但它支持相对简单的函数式编程,因为 Python 中的一切都是对象。这意味着函数可以被赋给变量并传递。

为了简单起见,让我们从打印 Hello world 的简单函数开始。看一看:

简单的 python 函数

函数的语法以一个def关键字开始,后跟函数名,然后是循环括号。定义函数以冒号(:)结尾。然后在有四个空格缩进的下一行,函数体开始。缩进是我们在使用函数时需要记住的最重要的事情。

#3 函数和变量

全局变量和函数变量

当我们在一个函数中有一个同名的变量时,在全局范围内,当我们试图访问这个变量时,就会产生歧义——无论我们访问的是全局变量还是函数范围内的变量。

所以 Python 提供了一个名为globals()的函数,通过它我们可以访问函数内部同名的全局变量。看一看:

在函数内部访问全局变量

将函数赋给变量

在 Python 中,我们可以将一个函数赋给一个变量,然后调用它。看一看:

将函数赋给变量并调用

#4 带参数的函数

现在我们知道了如何定义一个函数,是时候进入下一阶段了,我们将输入传递给函数——参数。为了快速理解它,我们将从一个计算两个数之和的数学函数开始。看一看:

带参数的函数

这是一个简单的函数,就像第一个一样,但是有两个输入— ab

调用函数

可以通过两种方式调用带参数的函数,只需调用函数并按照函数中提到的顺序传递参数,或者使用命名参数。看一看:

调用函数

具有默认值的参数

在上面的示例中,ab是两个强制参数——这意味着开发人员必须传递两个参数来调用函数。在 Python 中,我们可以用默认值指定参数。所以这些参数是可选参数。调用函数时,如果没有传递任何可选参数,Python 会考虑该参数的默认值。看一看:

具有默认值的参数

我们可以通过三种方式调用上述函数,如下所示:

使用默认值参数调用函数

#5 个具有返回值的函数

我们已经看到了如何将输入传递给函数;是时候实现函数的输出了。这类似于 Java、Kotlin 等大多数语言——我们需要使用 return 关键字并提及值。看一看:

带输出的函数

Python 有一种独特的能力,可以返回多个值作为输出,这是大多数语言都做不到的。看一看:

具有多个输出值的函数

xyz变量将分别被赋予加号、减号和乘号的值。

#6 函数作为参数和返回值

Python 函数式编程能够将函数作为输出返回,或者作为参数传递。

作为一个参数

到目前为止,我们已经看到了如何将变量作为参数传递给函数。现在我们将学习如何将函数作为参数传递给其他函数——类似于 Kotlin 中的高阶函数。看一看:

使用函数作为参数

用作返回值(输出)

类似于将函数作为参数传递,我们也可以将其作为输出返回——这是 Python 中的一个独特功能。看一看:

使用函数作为返回值

#7 内部函数

我们可以在另一个函数内部编写一个函数,这是我直到现在才在其他编程语言中看到的。内部函数的作用域是外部函数,只能从外部函数访问内部函数。看一看:

✅访问内部函数的正确方法

内部函数

✖️不能从包装函数的外部访问内部函数:

非法访问内部函数

# 8λ函数

Lambda 是具有单行表达式的函数的最简单形式,它没有名称。在 Python 中,我们必须使用lambda关键字而不是def来创建 lambda 函数。看一看:

λ函数

这里变量f是一个简单的 lambda 函数,而abf的参数。语法类似于普通函数。唯一的变化是关键字和单行表达式。

下面是一个简单的例子,展示了我们如何使用普通函数和 lambda。看一看:

普通函数和 lambda 函数的功能相同

#9 映射和过滤功能

到目前为止,我们已经看到了如何创建函数和其他策略。Python 自带的默认功能包括 map 和 filter,这在一些用例中非常方便。

地图

map是一个函数,它需要另一个函数对象和任意数量的iterables,如列表和字典。map用提供给它的函数对象迭代列表中的每一项,并返回一个列表。看一看:

地图功能

我们可以向 map 传递多个列表,如下所示:

带有多个列表的地图

过滤器

filter函数需要两个参数——一个函数对象和一个 iterable。Filter通过返回一个boolean值的函数对象迭代每一项。最后,filter返回一个列表,其中包含从函数对象返回 true 的项目。

滤波函数

#10 室内装潢师

装饰器是一种设计模式——它接受一个对象并向其添加新的功能,而无需从调用点进行任何更改。正如我前面说过的,Python 中的一切都是对象——所以我们可以将函数用作装饰器,并且可以应用于其他函数。看一看:

装饰者用法

希望你学到有用的东西,感谢阅读。

你可以在 MediumTwitterQuoraLinkedIn 上找到我。

面向数据记者的 Python:从网络上获取数据

原文:https://towardsdatascience.com/python-for-data-journalists-get-your-data-from-the-web-c0cee664d17?source=collection_archive---------65-----------------------

使用 Python 和 Pandas 在网络上发现、读取和分析 CSV、Excel 电子表格中的数据

摄于 Unsplash 上的粘土堤岸。所有其他图像由阿兰·琼斯。

作为一名记者,你的工作是讲述一个故事,让你的读者觉得有吸引力、有娱乐性和知识性。作为一名数据记者,你可以从网上的数据中找到这个故事。你找到数据,研究它,并得出结论,告知你的叙述。也许你还会制作一些有趣的图表或插图。

如果你知道去哪里找,并且有检索、处理和分析数据的技能,那么就会有大量的数据存在。

我们将探索如何找到、读取、分析和可视化这些数据。

更准确地说,我们将:

  • 使用 Python 和 Pandas 从网上读取电子表格文件
  • 提取我们感兴趣的数据
  • 为我们的特定目的操纵数据
  • 探索数据中的关系
  • 画一些说明图

开放数据,什么和哪里?

许多政府和组织开放了他们的数据,任何人都可以访问。例如,美国和英国政府拥有涵盖政府、经济和社会各个方面的公开数据。欧盟也有类似的资源。

大型非政府组织以及私营组织也免费或收费提供数据。其中包括世界银行、世界经济论坛、世界卫生组织和联合国。数据也有学术来源。位于英国牛津大学的“我们的数据世界”就是一个很好的例子,美国约翰·霍普金斯大学的新冠肺炎仪表板提供了疫情的最新数据(尽管这些数据不能直接下载)。

但是,如果你不确定从哪里开始,一个好的地方是谷歌的公共数据浏览器,你可以在那里搜索特定提供商或特定主题的数据。

数据格式

你会发现数据有多种格式。最常见的可能是可下载的电子表格。这些通常是 Excel 格式或 CSV 文件。

API(应用程序编程接口)也是有用的数据源,这些数据通常以 CSV 或 JSON 的形式出现。API 有时会限制您可以检索的数据,并且通常要求您注册。API 使用“免费增值”模式并不罕见,在这种模式下,有限的访问是免费提供的,但如果你想访问大量数据,则需要付费。

使用 Python 和熊猫

我们将看看如何处理不同类型的数据,以及如何使用 Python 和 Pandas 来整理、分析和可视化这些数据。

为了提供一个焦点,我们来看看英国的人口数据。我们将追踪过去几十年人口的增长情况,以及移民对人口的影响(如果有的话)。我们将使用两个不同的数据源,并将它们连接起来,看看这些数字之间是否有任何关系。

使用网络上的数据只需要很少的编程知识,但是你确实需要对 Python 和 Pandas 的基础有一点熟悉,或者至少愿意学习它们。

在下面的代码中,我将使用 Jupyter 笔记本(您可以使用标准的 Python 编辑器或 IDE,但我发现 Jupyter 更容易构建这些简单例程的原型)。

如果您的计算机上还没有 Python 工具,我建议您安装 Anaconda。有了 Anaconda,你可以在一个包中获得 Python 以及大量有用的库,如 Pandas、Jupyter 笔记本和代码编辑器。有关如何获取它的说明,请参见下面的文章:

[## 为数据可视化设置 Jupyter 笔记本

Jupyter 笔记本是一个伟大的和相当简单的方式来探索数据和创造可视化的互动…

towardsdatascience.com](/setting-up-jupyter-notebooks-for-data-visualisation-e287e2688af6)

入门指南

假设你已经准备好了工具,我们就开始吧。

我将把每一点代码都呈现为一个 Jupyter 笔记本代码单元,我建议你也这样做。

因此,我们需要做的第一件事是输入我们将要使用的 Python 库。

import pandas as pd
import matplotlib.pyplot as plt

这几乎是我们操作数据和产生可视化所需的一组标准库。

如果由于某种原因你还没有安装这些,你将需要从命令行安装 condapip ,例如

conda install pandas

或者

pip install pandas

注意,如果您没有使用 Anaconda,您可能需要使用命令 pip3 而不是 pip 进行安装。

让我们从电子表格数据、CSV 和 Excel 文件开始探索。

CSV 和 Excel

每当您找到一个为您提供 Excel 文件下载的数据源时,您通常会发现他们也提供了一个 CSV 替代文件。对于简单的电子表格,我们使用哪个并不重要。

尽管如此,CSV 文件更容易被人阅读——它们是纯文本表格,表格中的每个值或标题用逗号(或其他字符)分隔。当然,您可以用电子表格打开它们,但是如果需要,您也可以用简单的文本编辑器编辑它们。

另一方面,Excel 文件是一种专有格式,需要用兼容 Excel 的电子表格程序来查看或编辑。

电子表格文件有时可以直接从 url 中读取,其他的则必须从浏览器中手动下载。

为了使我们这里的目的更容易,我已经将我们将要使用的文件复制到一个存储库中,您可以从您的程序中直接访问它。

首先,我们要看看英国人口在过去 50 年左右的时间里是如何增长的。我们将使用英国国家统计局的数据。

您可以在此下载该文件:

https://www.ons.gov.uk/generator?format=csv&uri =/peoplepulationandcommunity/populationandmigration/populationestimates/time series/uk pop/pop

将其保存在与笔记本或程序相同的目录中。

下面的程序片段将该数据加载到 Pandas 数据帧中。真正的工作由 pd.read_csv 完成,它从您的目录中读取文件,第二行显示表格的前 10 行。

当我下载这个文件时,它被命名为 series-100520.csv

然而,当下载文件时,你可能会得到一个反映你下载日期的文件名。所以检查文件名并适当调整代码。

代码如下:

data = pd.read_csv(‘series-100520.csv’)
data.head(10)

好了,现在我们有了从 CSV 文件加载的数据帧,我们已经执行了命令 data.head(10) ,它显示了数据表的前 10 行。它基本上由两列组成:年份和那一年的人口,但是包含了一些关于文件的注释。

这就是问题。这些额外的行可能对人类读者有用,但对我们的分析并不十分有用。此外,我们希望这两列的标题有意义。也许我们可以称它们为“年”和“流行”。

这很容易解决。我们只是跳过头几行,标题和编号为 0 到 6 的行,自己定义标题是什么。

下面是再次读取该文件的代码,但是添加了一些额外的参数,这将完全符合我们的要求。

data=pd.read_csv(‘series-100520.csv’,skiprows=8,names=[‘Year’,’Pop’], index_col=0)data.head(10)

那更好。一个简单的表,有两列和合理的列标题。我们告诉 Pandas,我们将使用第一列作为数据帧的索引(否则 Pandas 将添加一个额外的编号索引)。

现在我们可以用它做一些有用的事情。例如,我们可以画一个这样的图。

data.plot(title=’UK Population in millions, 1970 to 2018', grid=True);

这是一个简单的线形图,显示了从 1971 年到 2018 年的人口增长。代码相当简单明了,我们只需调用 plot 函数,它会自动使用索引(年份)作为 X 轴,并将“Pop”列绘制为 Y 值。

我们可以看到,在这一时期有一个逐渐上升的增长。

另一件我们很容易做的事情是查看实际的增长是多少。该表有 48 行,标记为 1971 年至 2018 年,因此我们可以像这样访问人口的第一个值:数据['Pop'][1971] 和最后一个像这样的数据['Pop'][2018] 。所以人口的变化是一个减去另一个。

data[‘Pop’][2018]- data[‘Pop’][1971]

我们得到的结果是

10507600

这比 48 年前增加了 1000 多万。或者以百分比表示:

percentageIncrease = round((data[‘Pop’][2018]- data[‘Pop’][1971])/data[‘Pop’][1971]*100,2)print(‘The UK population has increased by’, percentageIncrease,’% from 1971 to 2018')

从中我们可以得到

从 1971 年到 2018 年,英国人口增长了 18.79%

所以现在我们知道有多少人生活在英国,以及在过去的几十年里人口是如何增长的。

移居

现在我们将使用来自下议院图书馆的不同数据源。根据开放议会许可,这些数据可以免费下载,您可以在这里找到:

https://www . parliament . uk/site-information/copyright/open-parliament-licence/

这次数据是以 Excel 电子表格的形式出现的。这类似于读取 CSV 文件,但是我们可以指定的参数有一些不同。例如,这个电子表格中有许多不同的工作表,为了将它读入熊猫数据帧,我们需要指定哪一个。

我们感兴趣的工作表叫做“摘要”。

所以从这个网址下载文件

http://research briefings . files . parliament . uk/documents/sn 06077/CBP 06077-data . xlsx

和以前一样,保存在您的工作目录中。

同样,该文件包含几行没有用的内容,所以我们将标题指定为第 2 行,将索引作为第一列(和前面一样),并跳过表的最后 10 行(使用 skipfooter )。

immData=pd.read_excel(‘CBP06077-data.xlsx’,sheet_name=’Summary’,index_col=1,header=2, skipfooter=10)immData.head(10)

生成的数据帧如下图所示。还可以,但是有一些我们不需要的列。不过,这没有太大关系,因为我们要做的是将我们感兴趣的数据复制到保存人口数据的原始数据帧中。

本质上,我们将复制用于净迁移的列的一部分,并将其粘贴到 dataframe 数据中的新列中。

为此,我们使用一个名为 iloc 的函数。这允许我们使用行和列的位置来选择数据帧的矩形部分。例如,iloc[x,y] 会从列 y 中选择行 x

但是 xy 可以是范围,所以 iloc[x1:x2,y1:y2 会为列 y1y2 选择行 x1x2

更具体地说,代码 immData.iloc[0:10,2:4] 将选择 immData 的一部分,从第 0 行到第 10 行,从第 2 列到第 4 列。或者 iloc[0:10,5] 将选择第 1 行到第 10 行,但只选择第 5 列。

我们想要的是第 5 列的净迁移,但是因为我们想要将其粘贴到数据数据帧中,所以它需要与数据的大小相同,所以我们只想要 1971 年到 2018 年的数字。1971 是第 8 行,2018 是从表格底部向上一行,我们可以将此选择表示为 [8:-1,5] ,其中-1 表示“从最后一行向后一行”。

我们将在数据 calle Imm 中创建一个新列,并将 iloc ed 副本粘贴到其中,如下所示:

data[‘Imm’]=immData.iloc[8:-1,5]*1000data.head(10)

结果是添加了新列的原始表。我们将移民数据乘以 1000,得到与人口数据相同的形式。

让我们用图表来描绘移民的增长。这与我们之前看到的非常相似,但是我们将 Y 值指定为“Imm”。

data.plot(y=’Imm’)

你可以看到,尽管有起有落,但在此期间,英国的净移民一直在增加。

我们可能做的另一件有趣的事情是将移民数字表示为总人口的百分比。在这里,我们创建另一个新列,并用百分比填充它。

data[‘Imm as % of Pop’] = data[‘Imm’]/data[‘Pop’]*100data

你可以看到,作为总人口的一个百分比,移民增加的百分比相当小。但这一比例也在上升。

data.plot(y=’Imm as % of Pop’)

所以看起来每年的移民数量和总人口数量之间可能有关系。让我们通过绘制总人口和移民水平的散点图来对此进行研究。

data.plot.scatter(x=’Pop’,y=’Imm’)

嗯,是的,似乎有一个线性的关系。随着人口的增加,移民也在增加。

由于移民导致的总人口增长看起来很小,所以一定还有其他原因。也许移民越多,移民就越多,因为现在的移民往往会带着他们的家人一起生活。我们没有考虑过这种关系,也不会考虑!

我们的目标

我认为我们已经达到了这篇文章的目标。我们已经了解了如何下载和读取 CSV 文件或 Excel 电子表格形式的数据。我们对这些数据进行了处理,以提供一些可能值得研究的信息,我们还研究了不同数据之间的关系。我们还绘制了一些说明性的图表。

我希望这是有用的,你会发现这里使用的技术与你未来的工作相关。感谢阅读。

你可以在这里找到更多关于绘制熊猫图的信息:

[## 用熊猫绘图:数据可视化导论

如果您是一名初露头角的数据科学家或数据记者,能够可视化您的数据会让您有能力…

towardsdatascience.com](/plotting-with-pandas-an-introduction-to-data-visualization-8bd7c0831650)

面向数据科学的 Python 第一部分

原文:https://towardsdatascience.com/python-for-data-science-66efe1bcc45d?source=collection_archive---------43-----------------------

数据科学/ Python 编程语言

近距离接触 Python

戴维·克洛德在 Unsplash 上的照片

数据科学

D 数据科学是当今谷歌上搜索次数最多的术语之一。谷歌趋势显示,自 2013 年 9 月以来,人们对“数据科学”一词的兴趣呈上升趋势。数据科学项目在所有主要大学的出现证明了这一学科新的受欢迎程度。对于门外汉来说,熟悉数据科学和数据科学家等术语是非常必要的。“数据科学”是指对数据的创建、验证和转换进行科学研究,以创造意义(定义由数据科学协会给出,这是一个由数据科学家组成的非营利性专业协会)。“数据科学家”是指使用科学方法从原始数据中解放和创造意义的专业人员。

数据科学也可以被认为是统计学与计算机科学和技术的融合。随着我们的社会变得越来越受数据驱动,计算机的处理能力逐年显著增长(以便理解大量数据),数据成为新的石油,从而引发了数据科学的前所未有的激增。然而,通过数据科学获得有意义的结果,数据的质量与数据的数量同样重要。

图片提供:iambipin

Python 和数据科学

Python 和数据科学共享一种共生关系(某种程度上)。多年来,Python 已经成为数据科学事实上的编程语言。学习 Python 的简单和容易以及 Python 中大量人工智能(AI)包的可用性是成为数据科学的全部和最终全部的主要因素。Python 在业界的广泛使用使它成为一个显而易见的选择。

一段历史

Python 编程语言是由 Guido Van Rossum 于 20 世纪 80 年代末在荷兰的Centrum wisk unde&Informatica(CWI)创建的,此前创建一种新的编程语言( ABC 语言)将淘汰 BASIC 编程语言失败。在 2018 年 7 月 12 日选择下台之前,他还是 Python 的终身仁慈独裁者(这是一个授予拥有最终决定权的软件开发领导者的头衔)。

Van Rossum 认为他需要一个简短、独特且略带神秘的名字,所以他决定将这种语言称为 Python。

你可能会对“Python”这个名字感兴趣。编程语言为什么这么命名?当 Python 的实现开始时,吉多·范·罗苏姆也在阅读来自 20 世纪 70 年代 BBC 喜剧系列“巨蟒剧团的飞行马戏团”的出版剧本。Van Rossum 认为他需要一个简短、独特且略带神秘的名字,所以他决定将这种语言称为 Python。在他的国王日演讲中,他明确指出他的意图是向巨蟒剧团的飞行马戏团的不敬的喜剧天才致敬。他还提到,谷歌的第一个版本是用 Python 写的,因为拉里·佩奇和谢尔盖·布林认为 Python 是表达他们关于如何索引网络和组织搜索结果的原始想法的正确语言。

Python 是由一群充满激情和主人翁感的志愿者在互联网上开发的。

Python 安装

Python 可以通过从这里或者从官方网站Python.org下载 Anaconda 个人版(推荐方式)来安装。

图片提供:iambipin

双击下载的。exe 文件,并按照说明进行操作。

图片提供:iambipin

Pythonic 式的方法

Python 方式(Python 社区对遵循特定方式的代码使用的形容词)是一种非常简约的方法。

漂亮总比难看好。
显性比隐性好。
简单比复杂好。
复杂总比复杂好。

先从打印“Hello World!”并且当我们考虑在其他流行的通用语言如 C++和 Java 中做同样的事情时会理解它。

用 C++打印“Hello World ”:

#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
    cout<<"Hello World!";
    return 0;
}

要用 Java 打印“Hello World ”:

class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!"); 
    }
}

两个字的印刷“你好,世界!”可以通过一行代码在 Python 中完成。它充分说明了 Python 的简单性和极简性。

print("Hello World!")

Python 简单、强大、优雅。Python 中的编码模仿了我们说英语的方式。假设你要为学校数据库创建一个程序。考虑涉及删除学生数据的模块。记录的删除只能由具有管理权限的人员执行。如果没有它,就会出现认证错误。还必须检查班级中是否存在具有该特定 id 的学生。为了在 Python 中执行此操作,您只需编写几行代码,如下所示:

def student_delete:
    """
    To delete a student from student database
    """
    if not user.is_admin():
        raise AuthError("You do not have sufficient privileges")
    if not class.has_student(student_id):
        raise ValueError("Invalid Student ID")
    class.get_student(student_id).delete()

上面几行代码几乎不言自明。代码片段展示了 Python 的简单性。对于初学者来说,def 是 Python 中定义函数的关键词。在 Python 系列的后续文章中,我们肯定会详细探讨 Python 编程的本质。

在结束对 Python 编程的介绍之前,有必要熟悉一下 Tim Peters(创建了 Timsort 混合排序算法并对 Python 编程语言做出了重大贡献的软件开发人员)的“Python 之禅”。“Python 之禅”简洁地陈述了用 Python 编写计算机程序时要遵循的 19 条指导原则。您可以通过运行以下命令来查看它:

import this

然后你会看到“Python 的禅”:

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

在本系列的后续文章中,我们将深入探讨 Python 编程语言的各个方面。希望您学到了一些关于 Python 编程语言的新知识。编码快乐!!!

参考资料:

用于数据科学的 Python 分类机器学习指南

原文:https://towardsdatascience.com/python-for-data-science-a-guide-to-classification-machine-learning-9ff51d237842?source=collection_archive---------16-----------------------

如何正确执行分类机器学习并对其进行评估

分类机器学习

亲爱的读者们,新年快乐。终于到了 2020 年。
随着数据的上升,
你掌握了 21 世纪最性感的技巧了吗?
它叫做——机器学习。

那是什么?你没有时间学习它,但你非常想掌握它?你找不到一篇关于机器学习的好文章,教你如何正确地执行评估你的模型?

别担心,我会解决你所有的问题——如果我有足够的数据的话。

今天,我们将谈论所有关于机器学习的话题。 是啊,大家最爱的话题,是不是很刺激?

根据 薪级表 ,一名机器学习工程师的平均年薪为110,000 美元,不包括绩效奖金。我们都知道机器学习正在兴起,我们也知道你现在就需要学习它。

谷歌机器学习趋势

那么,机器学习到底是什么?
机器学习是人工智能(AI)的一个子集,它在机器中引入了“学习”的能力。把它想象成机器能够在它们的人工大脑中开发出一个模式,给定你提供给它的数据

图片来自维基媒体

传统上,我们通过给机器规则来给它们编程做一些事情,比如一个 if-else 语句。现在,我们让机器通过向它们提供数据来发现这些规则。这里有一个形象化的例子可以帮助你更好地理解它。

机器能够通过训练过程发现这些规则,在训练过程中,机器尝试不同的规则,并评估每个规则与我们的数据的拟合程度。发现规则后,我们现在可以说机器根据我们的数据造出了一个模型

该过程的一个例子是:

  • 将猫的图像传入机器,并贴上“猫”的标签
  • 传入女孩的数据和她们的习惯,同时给她们贴上“女孩”的标签
  • 传入每个员工的工资以及他们的职位资格

在这个过程之后,机器将能够预测:

  • 如果图像是猫或其他动物
  • 如果是女孩或男孩,根据这个人的习惯
  • 具有某个职位资格的员工的工资

机器学习有多种形式。经常提到的有监督、无监督和强化学习。定义您将处理哪种形式的机器学习的主要因素将是您的数据集,或数据。

如果你有一组输入输出,大多数时候它会被归类为监督机器学习。为了简单起见,我们将在本文中只讨论监督学习来帮助您入门。

分类和回归

监督机器学习处理两个主要问题,
分类回归

如果你注意了,我上面展示的例子是关于—

  • 女孩还是男孩——分类
  • 员工工资-回归

相当直接。
分类通常有离散输出,而
回归有连续输出。

先决条件

首先,我们需要知道您将如何收集您的数据。

今天,大多数现实世界的企业都使用机器学习来优化他们的产品/服务。

  • 当您停止使用某项服务一段时间后,您可能会收到一封电子邮件,向您提供折扣/奖励以继续使用该服务。
  • 当你浏览 Youtube/网飞时,你会得到与你的兴趣相符的推荐,这会让你在这个平台上呆得更久。
  • 当你的照片被发布到脸书上时,你会自动被平台识别并被标记。

如果你在这些组织中的一个工作,他们已经建立了适当的数据仓库,包含了大部分的数据。然后,您可以在大多数情况下通过使用 SQL 来提取这些数据。因此,您首先需要的是 SQL

列表上的下一个可能是 Python ,带有特定的库。
Pandas 将是 Python 中用来操作数据的主库,所以那应该是你掌握的第一个库。

[## 用于数据科学的 Python 熊猫指南

10 分钟内完成数据探索指南

towardsdatascience.com](/python-for-data-science-basics-of-pandas-5f8d9680617e)

之后,我们将通过本文中的可视化我们的大量数据和发现。没有它,没有人能真正理解我们在做什么。
我已经写了多篇关于
的文章,一定要看看它们来刷新你的记忆。****

**** [## 面向数据科学的 python——Plotly 数据可视化指南

现在是 2020 年,是时候停止使用 Matplotlib 和 Seaborn 了

towardsdatascience.com](/python-for-data-science-a-guide-to-data-visualization-with-plotly-969a59997d0c) [## 用于数据科学的 Python 使用 Plotly 进行数据可视化的高级指南

如何在 Plotly 中添加和自定义滑块、下拉菜单和按钮

towardsdatascience.com](/python-for-data-science-advance-guide-to-data-visualization-with-plotly-8dbeaedb9724)

继续,知道如何正确地探索你的数据也是很好的。
拿到数据集后,很多数据从业者往往不知道该怎么处理。这种情况经常导致我们都想避免的优化较差的机器学习模型。

因此,请阅读我的文章

** [## 用于数据科学的 Python 在执行机器学习之前要做什么?

不要沉迷于机器学习模型,先了解你的数据。

towardsdatascience.com](/python-for-data-science-what-to-do-before-performing-machine-learning-a30f62465632)

从 Plotly 到熊猫再到机器学习。我掩护你。既然已经出来了,是时候开始了。

丹尼尔·里卡洛斯Unsplash 上拍摄的照片**

进口

像往常一样,我们将与 Jupyter 笔记本 一起工作。

#all plotly
from plotly.offline import init_notebook_mode,iplot
import plotly.graph_objects as go
import cufflinks as cf
init_notebook_mode(connected=True)#others
import pandas as pd
import numpy as np

导入数据集

在本文中,我们将使用一个 电信客户流失数据集

df = pd.read_csv(filepath)

机器学习的数据预处理

在这个阶段,我们将把数据预处理成机器可读的格式。请记住,机器实际上并不理解文本,因为它们只是将文本作为输入。例如,机器不理解文本“男性”和“女性”之间的差异。因此,在我们通过训练过程之前,我们需要正确地处理我们的分类和数字数据。

分类数据

将分类数据转换成可理解输入的最常用方法是为每个类别创建虚拟变量。例如,我们的合同栏中有 3 种类型的合同,即“逐月”、“一年”和“两年”。然后,合同列被转换为 3 列,每种类型的合同对应一个真或假指示器。这里有一幅图可以帮忙。

分类数据预处理

我们可以通过熊猫的 get_dummies 函数很容易地做到这一点。

#Creating Dummy Variables for Categorical Columns
df = pd.get_dummies(data = df,columns = cat_cols )

我们可以看到分类列已经被处理过了。然而,也有布尔列只包含两个类别,通常是或否。我们可以使用以下公式将这些值编码为 1 和 0:

from sklearn.preprocessing import LabelEncoder
#Encoding bool_cols
le = LabelEncoder()
for i in bool_cols :
    df[i] = le.fit_transform(df[i])

现在所有的分类和布尔列都完成了。
我们只剩下—

数字列

数字列的预处理包括缩放,使得一个量的变化等于另一个量的变化。机器需要理解,仅仅因为一些列(如“总费用”)有很大的值,并不意味着它在预测结果方面起很大作用。为了实现这一点,我们将所有的数字列放在同一个标度中,这样它们就不会被另一个支配。

from sklearn.preprocessing import StandardScaler
#Scaling Numerical columns
std = StandardScaler()
scaled = std.fit_transform(df[num_cols])
scaled = pd.DataFrame(scaled,columns=num_cols)df.drop(columns = num_cols,axis = 1, inplace= True)
df = df.merge(scaled,left_index=True,right_index=True,how = "left")

分割训练和测试

完美。现在我们的数据已经被完美地缩放和分类了。我们可以将它们分成我们的训练集和测试集。

训练集是我们传递到训练过程中的数据,而测试数据用于评估我们的模型。

#splitting train and test data 
train,test = train_test_split(df,test_size = .25 ,random_state = 111)#defining our features and metric
cols    = [i for i in df.columns if i not in Id_col + metric_col]
train_X = train[cols]
train_Y = train[metric_col]
test_X  = test[cols]
test_Y  = test[metric_col]

取样操作

如今,来自现实生活情况的数据经常导致对每个潜在输出的不平衡数量的观察。
通过数据探索,我们做的第一件事是找出流失客户和非流失客户的数量。结果是—

如您所见,非流失客户的数量明显高于流失客户的数量。不需要太多的细节,这将给我们的模型带来一个问题,因为机器正在获得更多关于非流失客户的信息,并且可能将流失客户误认为非流失客户。因此,这将降低预测客户流失的准确性。

换句话说,我们的模型将擅长预测客户是否会留在,但在预测客户是否会流失时表现不佳。根据业务需求,这显然与我们试图实现的目标相矛盾。我们希望尽可能准确地预测客户流失情况,以便抓住所有客户,并采取额外的商业行动来说服他们留下来。例如,如果我们知道客户即将流失,就发送折扣代码。

过采样

也就是说,我们可以通过
过采样来最小化这个问题的影响。过采样是人为增加数据集中某一类的观察次数的方法。通常,我们更喜欢平衡每个类的观察数量,这意味着我们应该有 50%的流失观察和 50%的非流失观察。

重击

我们将使用的方法是 SMOTE,代表综合少数过采样技术。在不涉及太多细节的情况下,SMOTE 人为地创造了新的观察结果,而不仅仅是现有少数民族案例的副本。相反,该算法通过涉及向量、随机数和每个样本的最近邻居来创建新的观察值。对我们来说,最主要的收获是,现在公平地创造了更多对流失客户的观察。

这里是为了便于理解,对 SMOTE 算法的补充阅读。

from imblearn.over_sampling import SMOTEcols    = [i for i in df.columns if i not in Id_col+metric_col]
smote_X = df[cols]
smote_Y = df[metric_col]#Split train and test data
smote_train_X,smote_test_X,smote_train_Y,smote_test_Y = train_test_split(smote_X,smote_Y,                                                           test_size = .25 ,                                                                         random_state = 111)#oversampling minority class using smote
os = SMOTE(random_state = 0)
os_smote_X,os_smote_Y = os.fit_sample(smote_train_X.to_numpy(),smote_train_Y.to_numpy())
os_smote_X = pd.DataFrame(data = os_smote_X,columns=cols)
os_smote_Y = pd.DataFrame(data = os_smote_Y,columns=metric_col)

现在,我们有 2 列车组和 2 测试组。
其中一个是原始数据,另一个应用了 SMOTE。
我们稍后会比较他们的表现。

特征选择

现在我们有了一组平衡的数据。
我们如何知道
包括不包括的特征?

我们不应该假设所有的特征在预测结果时都起着重要的作用。其中有些可能无关紧要,也可能无关紧要。我们可以在相关图中清楚地观察到这一点。

#correlation
correlation = df.corr()
#tick labels
matrix_cols = correlation.columns.tolist()
#convert to array
corr_array  = np.array(correlation)#Plotting
trace = go.Heatmap(z = corr_array,
                   x = matrix_cols,
                   y = matrix_cols,
                   colorscale = "Magma",
                   colorbar   = dict(title = "Pearson Correlation coefficient",
                                     titleside = "right"
                                    ) ,
                  )layout = go.Layout(dict(title = "Correlation Matrix for variables",
                        autosize = False,
                        height  = 720,
                        width   = 800,
                        margin  = dict(r = 0 ,l = 210,
                                       t = 25,b = 210,
                                      ),
                        yaxis   = dict(tickfont = dict(size = 9)),
                        xaxis   = dict(tickfont = dict(size = 9))
                       )
                  )data = [trace]
fig = go.Figure(data=data,layout=layout)
iplot(fig)

相关图表

我们可以从关联热图中观察到,不同的特征对客户流失有不同的影响。过多特征的结果是噪声,这会降低我们模型的性能。因此,我们如何确定哪些特征是重要的?— 功能选择

特征选择是机器学习中的核心技术之一,它将提高性能,缩短训练时间,并提高模型的简单性。有多种特征选择算法,我们今天将使用的一种被称为—
递归特征消除

递归特征消除(RFE)拟合模型并消除最弱的特征,直到达到指定的特征数量。下面是对它的详细解释:

如前所述,递归特征消除(RFE,Guyon 等人( 2002 ))基本上是预测器的向后选择。该技术首先在整个预测因子集上建立一个模型,并计算每个预测因子的重要性分数。然后移除最不重要的预测值,重新构建模型,并再次计算重要性分数。在实践中,分析师指定要评估的预测值子集的数量以及每个子集的大小。因此,子集大小是 RFE 的一个调整参数。优化性能标准的子集大小用于基于重要性排名选择预测器。然后,最佳子集用于训练最终模型。[4]

from sklearn.linear_model import LogisticRegressionfrom sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegressionlog = LogisticRegression()rfe = RFE(log,10)
rfe = rfe.fit(os_smote_X,os_smote_Y.values.ravel())#identified columns Recursive Feature Elimination
idc_rfe = pd.DataFrame({"rfe_support" :rfe.support_,
                       "columns" : [i for i in df.columns if i not in Id_col + metric_col],
                       "ranking" : rfe.ranking_,
                      })
cols = idc_rfe[idc_rfe["rfe_support"] == True]["columns"].tolist()

在这段代码中,我们选择了 10 个最好的特性来包含在我们的逻辑回归模型中。然后我们可以画出 RFE 的排名。

import plotly.figure_factory as ff
tab_rk = ff.create_table(idc_rfe)
iplot(tab_rk)

这张表显示了 RFE 选择的特性,以及它们各自的排名,这样你就可以衡量某个特性的重要性。
我们现在可以分离数据集了。

#separating train and test data SMOTE
train_rf_X_smote = os_smote_X[cols]
train_rf_Y_smote = os_smote_Y
test_rf_X_smote  = test[cols]
test_rf_Y_smote  = test[metric_col]#separating train and test data Original
train_rf_X = train_X[cols]
train_rf_Y = train_Y
test_rf_X = test_X[cols]
test_rf_Y = test_Y

在这个阶段,我们有 2 训练集和 2 测试集,其中所有特征都被递归消除。其中一个是原始数据,另一个应用了 SMOTE。

培训模式

现在到了我们训练模型的实际阶段。
有多种算法用于训练分类问题。
我们无法判断哪种算法最适合我们的数据,因此我们通常使用多种算法进行训练,并根据精心选择的标准比较它们的性能。今天,我们将只关注
逻辑回归以及它与我们数据的吻合程度。

维基媒体的 Sigmoid 函数

****逻辑回归是最常用的机器学习算法之一,用来预测二进制类,在这种情况下流失不流失。它的工作原理是将基于 Sigmoid 函数的 0 和 1 之间的输出概率附加到每个输入。基于默认为 0.5 的阈值,高于该阈值的将被归类为 1 (流失),低于该阈值的将被归类为 0 (非流失)。

ML-Cheatsheet 决定边界

决策阈值

例如,如果我们的阈值是 0.5,而我们对一组特征的预测概率是 0.7,那么在我们的例子中,我们会将这个观察结果归类为变动

理解了这一点,让我们训练我们的数据。

#training for dataset without smote
logit_ori_rfe = LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
          penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
          verbose=0, warm_start=False)
logit_ori_rfe.fit(train_rf_X,train_rf_Y)#training for dataset with smote
logit_smote_rfe = LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
          penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
          verbose=0, warm_start=False)
logit_smote_rfe.fit(train_rf_X_smote,train_rf_Y_smote)

差不多就是这样,我们的模型已经训练好了。如你所见,训练一个模特并没有你想象的那么复杂。
大多数时候,将数据转换成“好的”格式进行训练,以及评估您的模型,这是非常耗时的部分。

评估您的模型

我们有两种型号。一个用 SMOTE 数据集训练,一个用原始数据集训练。我们可以开始使用这些模型进行预测,但我们想首先评估这些模型的准确程度。
为了评估模型,我们需要考虑一些标准。

对于分类,我们用来评估模型的几个常用指标是

  • 准确(性)
  • 精确
  • 召回
  • f1-分数
  • ROC 曲线

让我解释一下每一个的意思。

精确度和召回由维基媒体

在讨论召回率和精确度之前,我们需要了解什么是误报、漏报以及它们的对应情况。

这可以通过左边的图表更好地解释,想象完整的图表是我们的数据集,圆圈是我们模型的预测。图的左边是实际的正值(1),图的右边是实际的负值(0)。

看左边的圆圈,圆圈内的所有点都被我们的模型预测为正,而圆圈外的所有点都被我们的模型预测为负。我们还知道,在图的左边,圆圈外的所有点都是正的。因此,它被错误地预测,指示一个假阴性。图表左侧圆圈中的所有点都被正确预测,表明真阳性

反之亦然适用于图的右侧。

精确度和召回率

维基百科的精确度和召回率

精确度和召回率使我们对模型有了更深入的理解。
精度定义为相关结果的百分比,
召回定义为正确分类的相关结果的百分比。

在不涉及太多细节的情况下,我们模型中的精度指的是被正确分类的预测流失客户的百分比。

召回措施为正确分类的实际流失客户的百分比。

F1 分数

在许多情况下,我们可以根据您试图解决的问题来优先考虑精度或回忆。在我们的案例中,我们肯定希望优先考虑** 尽可能准确地预测实际客户流失,这样我们就可以说服他们留下来。**

在一般情况下,有一个指标可以协调精确度和召回率,这就是 F1 分数。总体目标是最大化 F1 分数,使你的模型更好。

F1 分数公式

ROC 曲线和 AUC

在调整多个变量以最大化我们的精确度、召回率和 F1 分数之后,我们还可以调整模型的阈值。

例如,阈值默认为 0.5,高于该值的任何输出概率都将被归类为 1。我们可以将阈值更改为更低/更高的值,以进一步增加我们的首选指标。

为了形象化这种变化,我们可以画出每个阈值对假阳性率和真阳性率的影响。曲线看起来会像这样。

受试者工作特征曲线

再说一次,不要涉及太多的细节,你的模型越好,曲线(蓝色)就越靠近图的左上角。相反,一个在分类方面做得很差的模型会向直线(红色)收敛,这不比随机猜测好。

使用 ROC 曲线,我们可以正确地确定一个模型是否优于另一个模型。我们也可以根据我们是否应该最大化真阳性率,或者最小化假阳性率来选择我们的分类阈值。在我们的情况下,我们应该以最大化真实阳性率为目标。因此,这也将增加我们的召回指标。

准确(性)

准确性是衡量模型性能的最基本的标准。它基本上是根据测试集正确预测的输出的百分比。

因此,我们确实应该考虑将召回准确性F1 得分作为这个特定模型的重要指标。

让我们开始吧。

#perfoming evaluation for original dataset
predictions   = logit_ori_rfe.predict(test_rf_X)
probabilities = logit_ori_rfe.predict_proba(test_rf_X)print(classification_report(test_rf_Y,predictions))#confusion matrix
conf_matrix = confusion_matrix(test_rf_Y,predictions)
conf_matrix#roc_auc_score
model_roc_auc = roc_auc_score(test_rf_Y,predictions) 
print ("Area under curve : ",model_roc_auc,"\n")
fpr,tpr,thresholds = roc_curve(test_rf_Y,probabilities[:,1])

评估指标

从我们在原始数据集上训练的模型来看,总体准确率相当高,为 81% 。然而,我们可以看到代表流失客户类别 1** 的所有指标都相当低。**

  • 精度为 69%
  • 召回率为 56%
  • F1 为 62%

由于观察值数量的不平衡,我们得到了一个相当高的加权平均值,因为与类别 1 相比,类别 0 的观察值要多得多。这是一个危险信号的迹象,因为我们的首要任务是能够准确预测 1 级。

#plot roc curve
trace2 = go.Scatter(x = fpr,y = tpr,
                    name = "Roc : " + str(model_roc_auc),
                    line = dict(color = ('rgb(22, 96, 167)'),width = 2))
trace3 = go.Scatter(x = [0,1],y=[0,1],
                    line = dict(color = ('rgb(205, 12, 24)'),width = 2,
                    dash = 'dot'))data = [trace2,trace3]layout = go.Layout(dict(title = "Receiver operating characteristic",
                        autosize = False,
                        height = 700,width = 800,
                        plot_bgcolor = 'rgba(240,240,240, 0.95)',
                        paper_bgcolor = 'rgba(240,240,240, 0.95)',
                        margin = dict(b = 195),
                        xaxis = dict(title = "false positive rate"),
                        yaxis = dict(title = "true positive rate"),
                       )
                  )#defining figure and plotting
fig = go.Figure(data,layout=layout)
iplot(fig)

受试者工作特征曲线

从 ROC 曲线上我们看到 AUC 是 73%,后面可以对比其他模型。

visualizer = DiscriminationThreshold(logit_ori_rfe)
visualizer.fit(train_X,train_Y)
visualizer.poof()

阈值图

阈值图对于我们确定阈值也很有用。正如我们所知,我们正试图最大化** 召回,同时不牺牲太多其他指标。阈值图帮助我们准确地做到这一点。
看起来接近 0.3 的阈值将允许我们最大限度地提高召回率,同时保持其他指标不变。**

这就是我们迄今为止对第一个模型的理解,让我们评估一下由 SMOTE 数据集训练的模型。

#perfoming evaluation for original dataset
predictions   = logit_smote_rfe.predict(train_rf_X_smote)
probabilities = logit_smote_rfe.predict_proba(train_rf_X_smote)print(classification_report(train_rf_Y_smote,predictions))#confusion matrix
conf_matrix = confusion_matrix(train_rf_Y_smote,predictions)
conf_matrix#roc_auc_score
model_roc_auc = roc_auc_score(train_rf_Y_smote,predictions) 
print ("Area under curve : ",model_roc_auc,"\n")
fpr,tpr,thresholds = roc_curve(train_rf_Y_smote,probabilities[:,1])

评估指标

很快,您可以观察到第 1 类(流失客户)的所有指标都显著增加。不利的一面是,整体精度会略有下降。

  • 精度为 75%
  • 召回率为 83%(几乎增加了 30%)
  • F1 为 78%

作为一名专业的数据科学家,您应该在一天中的任何时候推荐这个模型而不是第一个模型。因为当务之急是准确预测的客户流失,所以你必须明白这个模型比之前的模型做得好得多,即使整体准确性略有下降。这就是真正的数据科学家与平庸的数据科学家的区别。

****#plot roc curve
trace2 = go.Scatter(x = fpr,y = tpr,
                    name = "Roc : " + str(model_roc_auc),
                    line = dict(color = ('rgb(22, 96, 167)'),width = 2))
trace3 = go.Scatter(x = [0,1],y=[0,1],
                    line = dict(color = ('rgb(205, 12, 24)'),width = 2,
                    dash = 'dot'))data = [trace2,trace3]layout = go.Layout(dict(title = "Receiver operating characteristic",
                        autosize = False,
                        height = 700,width = 800,
                        plot_bgcolor = 'rgba(240,240,240, 0.95)',
                        paper_bgcolor = 'rgba(240,240,240, 0.95)',
                        margin = dict(b = 195),
                        xaxis = dict(title = "false positive rate"),
                        yaxis = dict(title = "true positive rate"),
                       )
                  )#defining figure and plotting
fig = go.Figure(data,layout=layout)
iplot(fig)****

受试者工作特征曲线

从 ROC 曲线中,我们观察到 AUC 约为 78%,比我们之前的模型高出约 5%。这表明我们的 SMOTE 模型优于以前的模型。

****visualizer = DiscriminationThreshold(logit_smote_rfe)
visualizer.fit(train_rf_X_smote,train_rf_Y_smote)
visualizer.poof()****

阈值图

阈值图也表明了我们当前模型的性能优势。请注意,我们如何在这里将阈值调得更高,以获得相对较高的召回率、精确度和准确度。

当前模型,阈值=0.4:

  • 约 90%的召回率
  • F1 分数约为 80%
  • 大约 70%的精度

以前的模型,阈值= 0.3:

  • 约 80%的召回率
  • F1 分数约为 60%
  • 大约 50%的精度

请注意,我们希望避免设置太低的阈值,否则我们会以过多的误报而告终。看起来我们有一个明显的赢家。****

总的来说,我们用两个不同的数据集使用逻辑回归训练了两个模型,一个使用 SMOTE 采样,一个不使用。基于几个标准,SMOTE 模型在预测流失客户方面表现明显更好。现在,您可以使用该模型来预测未来的客户流失。

结论

照片由阿齐兹·阿查基Unsplash 上拍摄

做得好,我知道这是一个漫长的,但它是值得的。
机器学习是一个复杂的过程,有许多因素决定你的模型的性能,从而决定你的技能组合。

在本文中,您已经了解到:

  • 什么是机器学习
  • 数据预处理(数值和分类)
  • 取样操作
  • 特征选择
  • 培训模型
  • 评估模型

这些技术只是机器学习的开始,
我们还有更多的内容要介绍。

在你走之前

我们的数据之旅还没有结束。随着数据行业人才的缺乏,用机器学习的适当知识来教育自己将使你在获得数据角色方面具有优势。请继续关注,我将在下一篇文章中讨论如何为您的数据集选择正确的模型,以及更多关于数据行业的故事、指南和经验。与此同时,请随意查看我的其他文章,以暂时满足您对数据的渴望。

一如既往,我引用一句话作为结束。

在机器学习和人工智能领域,我们需要迎头赶上。——克劳斯·弗罗利希

订阅我的时事通讯,保持联系。

也可以通过 我的链接 注册中等会员来支持我。你将能够从我和其他不可思议的作家那里读到无限量的故事!

我正在撰写更多关于数据行业的故事、文章和指南。你绝对可以期待更多这样的帖子。与此同时,可以随时查看我的其他 文章 来暂时填补你对数据的饥渴。

感谢 的阅读!如果你想与我取得联系,请随时联系我在 nickmydata@gmail.com 或我的 LinkedIn 个人资料 。也可以在我的Github中查看之前写的代码。******

面向数据科学的 python——Plotly Dash 交互式可视化指南

原文:https://towardsdatascience.com/python-for-data-science-a-guide-to-plotly-dash-interactive-visualizations-66a5a6ecd93e?source=collection_archive---------9-----------------------

构建您的第一个 web 应用程序!

卢克·切瑟在 Unsplash 上的照片

问候读者,
如果你像我一样,你喜欢数据。当数据被恰当地呈现时,它可以讲述很多故事。

我们生活在一个人们依赖数据进行商业决策的时代,这就是为什么专业地展示数据会让你领先于他人。

想象给了你一些你不知道的问题的答案。
—本·施奈德曼

我们可以通过使用惊人的可视化技术来实现这一点。我们已经讨论过如何利用我们目前在 Python 中拥有的强大库。

[## 面向数据科学的 python——Plotly 数据可视化指南

现在是 2020 年,是时候停止使用 Matplotlib 和 Seaborn 了

towardsdatascience.com](/python-for-data-science-a-guide-to-data-visualization-with-plotly-969a59997d0c) [## 用于数据科学的 Python 使用 Plotly 进行数据可视化的高级指南

如何在 Plotly 中添加和自定义滑块、下拉菜单和按钮

towardsdatascience.com](/python-for-data-science-advance-guide-to-data-visualization-with-plotly-8dbeaedb9724)

在这篇文章中,我们将会更进一步。我们将讨论如何使用 Python 中的 Plotly Dash 构建一个交互式仪表盘。仪表板甚至可以作为 web 应用程序托管。

破折号

纽约石油和天然气由 Dash 应用程序库

达什是这个街区新的性感男孩。

这是一个 Python 框架,允许你使用 Flask、Plotly.js 和 React.js 创建惊人的 web 应用。Dash 在构建具有高度定制用户界面的数据可视化应用程序方面效率极高,无需了解任何 HTML、CSS 或 Javascript。

基本上,如果你已经掌握了 Python,它会很快,很漂亮,也很容易学。

Dash 消除了所有需要了解 web 开发的担忧,包括部署应用程序的头痛问题。它易于维护,跨平台,并且可以随时移动。

现在你可以只用纯 python 来构建你的移动响应网络应用。

但是说够了

我开始听起来像 Dash 的推销员了。

spiro 的 gif 图片

同样令人欣慰的是,近年来对 Plotly Dash 的需求正在增加。以下是 Plotly Dash 在过去 5 年的谷歌趋势中的结果。

谷歌趋势

现在那已经不碍事了。让我们开始吧。

先决条件

Dash 可视化基于 Plotly。
因此,请确保你在继续阅读这个提前指南之前,已经对的基础知识有了扎实的理解。你可以在这里参考我写的关于 Plotly 的 基础的文章

为了和 Plotly 一起工作,你也应该掌握熊猫。
真巧。我碰巧也写了一本熊猫指南。
如需刷新记忆,请过一遍。

[## 用于数据科学的 Python 熊猫指南

10 分钟内完成数据探索指南

towardsdatascience.com](/python-for-data-science-basics-of-pandas-5f8d9680617e)

进口

装置

pip install dash

使用 Jupyter 笔记本电脑…

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
import numpy as np
from dash.dependencies import Input, Output

链接到本指南中使用的数据集

df = pd.read_csv('mpg.csv')

作者图片

第一部分。布局

作者图片

Dash 框架分为两部分。第一部分是应用程序的布局,它定义了应用程序的外观和感觉。这涉及到你应用程序上所有东西的风格、定位和大小。

Dash 使用组件来定义布局。

  • dash_core_components —用于交互用户界面的组件。这些组件由 Dash 团队开发和维护,包括像搜索栏范围滑块和任何你能想到的用于交互式图形体验的东西
  • dash_html_components —表示 HTMLCSSJavascript 代码的组件。你可以使用这个组件来声明标签,比如 divimg
    ,就像你开发一个网站一样。

让我们建立一个简单的“Hello World”布局来热身。

#initiating the app
app = dash.Dash()#defining the layout
app.layout = html.Div(children=[
    html.H1(children='Hello World!')
])#running the app
if __name__ == '__main__':
    app.run_server()

在这个应用程序中,我们简单地定义了一个 H1 HTML 标签为“Hello World”。
不管你在哪里运行代码,你都应该像这样。

作者图片

点击链接访问您的应用程序。

作者图片

这就是你的第一个“Hello World”应用程序。这很酷,但让我们在应用程序中展示一个真实的图表。

#initiating the app
app = dash.Dash()#defining the layout
app.layout = html.Div(children=[
    html.H1(children='Hello World!')
    html.Div(children='Dash: A web application framework for Python.'),dcc.Graph(
        id='graphid',
        figure={
            'data': [
                {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'Cats'},
                {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': 'Dogs'},
            ],
            'layout': {
                'title': 'Cats vs Dogs'
            }
        }
    )
])#running the app
if __name__ == '__main__':
    app.run_server()

作者图片

在这段代码中,我们引入了 Div 标签(最常用的标签之一)和 dcc。图形组件

dcc。图形组件

图形组件用于显示一个图形图形。图形参数用来表示 go。图,你可以在这里刷新一下关于它的记忆

fig = go.Figure(data = data,layout = layout)#**data can be any type of plotly graphs (pie chart,scatter, etc)**

基本上,您可以通过 dcc 传递任何类型的 Plotly 图。要在您的应用程序上显示的图形组件。然后,您可以进一步定制Plotly 和 Dash 中该图形的样式。

现在让我们为从 Github 导入的数据做一个布局。

app = dash.Dash()
df['year'] = random.randint(-4,5,len(df))*0.10 + df['model_year']app.layout = html.Div([
                html.Div([
                    dcc.Graph(id='mpg-scatter',
                              figure={
                                  'data':[go.Scatter(
                                      x=df['year']+1900,
                                      y=df['mpg'],
                                      text=df['name'],
                                      mode='markers'
                                  )],
                                  'layout':go.Layout(
                                      title='MPG vs Model Year',
                                      xaxis={'title':'Model Year'},
                                      yaxis={'title':'MPG'},
                                      hovermode='closest'
                                   )}
                    )
                ],style={'width':'50%','display':'inline-block'}),
])if __name__ == '__main__':
    app.run_server()

作者图片

在这个应用程序中,我们只是将数据集中的车型年的每加仑英里数可视化。另外,随着车型年的增加,我们可以清楚地看到 MPG 略有增加。

使用 style 参数,我们可以声明我们希望图表在仪表板中的外观。通过检查web 应用程序的元素,您可以进一步深入到样式中。

作者图片

我们可以看到这个内部 div 的宽度是其父 div 的一半。这是因为我们在代码中声明了以下内容。

style={'width':'50%'}

我认为到目前为止,在 Dash we 中制作一个简单的仪表板是非常简单的。

  • 像你在绘图时那样绘制图表
  • 将图表作为 dcc 插入。图仪表板中的部件
  • 根据我们的需要调整风格
  • 运行应用程序

第二部分。互动回访

这就是有趣的地方。

在声明了我们的基本布局之后,Dash 允许我们在应用程序中添加复杂的交互。这个组件也将允许我们实时更新我们的数据。

  • 当用户悬停在您的图表上时,进行某些更改
  • 当用户在搜索栏中键入内容时更新可视化效果
  • 在用户刷新时或在实时更新数据

是的,你没听错。
如果需要,仪表板将能够在中实时更新自身,但稍后会详细介绍。让我们来讨论如何使用回调来更新特定用户操作的数据。

回调函数

我们通过在布局之后定义回调函数来实现这一点。回调函数,像其他函数一样,有—

  • 一个输入
  • 一个输出
  • 如何处理输入
[@app](http://twitter.com/app).callback(Output('<component-id>','<what to update>'),
             [Input('<component-id>','<what to take in as Input>')])
def callback_graph(<random name for inputs>):
    x = do something with x
    return x

使用我们在 Dash 中声明的组件 id,我们能够精确定位我们想要什么作为我们函数的输入,以及更新什么。

Hoverdata

例如,我们将使用包含在 dcc 中的一个属性。图形组件默认为,悬停数据。它会返回一个 JSON 字符串,其中包含您所悬停的数据的相关信息。让我展示给你看。

html.Div([
   dcc.Markdown(id='hoverdata-text')
])[@app](http://twitter.com/app).callback(Output('hoverdata-text','children'),
             [Input('mpg-scatter','hoverData')])
def callback_stats(hoverData):
    return str(hoverData)#children is the default property that a component will display

作者图片

在这一节中,我们在图表下面添加了一个 Div 来显示我们所悬停的内容。如您所见,当我们将鼠标悬停在图中的不同点上时,Div 的内容会立即更新。我们通过以下方式实现这一目标—

  • 将 HoverData 作为输入
  • 将 Div 声明为输出
  • 将 HoverData 显示为纯文本

*额外注意:HoverData 中的 pointIndex 代表当前引用数据的 DataFrame 的索引。这在以后会很有用。

也就是说,我们可以利用接收到的输入做各种事情。天空才是极限。

回去工作

让我们展示一些关于我们导入的数据集的有趣内容。
对于我们的第一款网络应用,我们希望展示每个数据点—

  • 汽车型号名称
  • 加速
  • 达到 0 到 60 英里/小时所需的时间

作者图片

通过利用 HoverData 中的数据,我们可以参考我们的 pandas dataframe,mpg.csv 中的实际数据。然后,我们可以基于它进行计算,并显示我们想要显示的各种指标。

我希望您现在意识到了,Dash 框架有多强大。

结论

布鲁克·卡吉尔Unsplash 上的照片

恭喜你,

您已经掌握了 Plotly Dash 的基本概念。

在这篇文章中,你学到了—

1。仪表板—布局

2。破折号—回调

这两者对于构建你的第一个 web 应用程序都是必不可少的。

现在去吧,数据从业者,

去造一个你感兴趣的东西,展示给全世界。

如果你遇到困难,请随时联系我。你可以在下面找到我的信息。

在你走之前

我们的数据之旅还没有结束。我正在撰写更多关于数据行业的故事、文章和指南。你绝对可以期待更多这样的帖子。与此同时,请随意查看我的其他文章来暂时填补您对数据的渴望。

像往常一样,我引用一句话作为结束。

学习如何做数据科学就像学习滑雪一样。你必须做这件事。 克劳迪娅·珀里奇 ,首席科学家,d stilley

订阅我的简讯,保持联系。

也可以通过 我的链接 注册一个中等会员来支持我。你将能够从我和其他不可思议的作家那里读到无限量的故事!

我正在撰写更多关于数据行业的故事、文章和指南。你绝对可以期待更多这样的帖子。与此同时,可以随时查看我的其他 文章 来暂时填补你对数据的饥渴。

感谢 的阅读!如果你想和我取得联系,请随时通过 nickmydata@gmail.com 联系我或者我的 LinkedIn 个人资料 。也可以在我的Github中查看之前写的代码。

用于数据科学的 python-Plotly Dash 交互式可视化高级指南

原文:https://towardsdatascience.com/python-for-data-science-advanced-guide-to-plotly-dash-interactive-visualizations-8586b0895032?source=collection_archive---------14-----------------------

构建您的第一个实时仪表板!不,真的!

斯蒂芬·道森在 Unsplash 上拍摄的照片

问候数据从业者,
我想你已经意识到对懂得如何交流数据的人的需求在增加。这正是我们应该在数据科学行业中不断寻求改进、学习更多知识和提高技能的原因。

即使围绕机器学习大肆宣传,数据可视化也没有失去其重要性。在规划任何机器学习之前,通常需要进行探索性数据分析。

大型科技公司经常需要交流他们拥有的数据。
我们是执行的人。

一个很好的例子就是谷歌和他们已知的谷歌趋势

作者截图

因此,构建干净的和漂亮的T21 可视化是一项有价值的技能,它绝对会让你脱颖而出。****

破折号

Dash 应用程序库的临床分析仪表板

你听说过神出鬼没吗?

达什是这个街区的新成员。我在这里写了一下。

[## 面向数据科学的 python——Plotly Dash 交互式可视化指南

构建您的第一个 web 应用程序!

towardsdatascience.com](/python-for-data-science-a-guide-to-plotly-dash-interactive-visualizations-66a5a6ecd93e)

基本上, Dash 是新的 Python 库,它允许你在不需要了解任何 HTML、CSS 或 Javascript 的情况下,构建具有高度定制化用户界面的惊人的数据可视化应用。

它消除了部署应用程序的麻烦,使其移动响应和易于维护。

但是你已经知道我在想什么了。

gif 由 thelonelyisland

你不是为这个来的,你想知道更多。

在本文中,我们将讨论如何将更多的定制添加到 Dash web 应用程序中。我们还将深入探讨如何在没有任何交互的情况下实时更新仪表盘,

先决条件

Dash 可视化基于 Plotly。理解构建简单的 Plotly 图的基本原理很重要。我在这里 写了构建基本的 Plotly 图 ,涵盖了构建任何类型的图时需要理解的概念。

[## 面向数据科学的 python——Plotly 数据可视化指南

现在是 2020 年,是时候停止使用 Matplotlib 和 Seaborn 了

towardsdatascience.com](/python-for-data-science-a-guide-to-data-visualization-with-plotly-969a59997d0c)

为了使用 Plotly,您需要使用 Pandas 对您的数据执行一些软转换

我掩护你。我碰巧也写了一本熊猫指南。
如果你需要刷新关于熊猫的记忆,请去翻阅一下。

[## 用于数据科学的 Python 熊猫指南

10 分钟内完成数据探索指南

towardsdatascience.com](/python-for-data-science-basics-of-pandas-5f8d9680617e)

进口

装置

pip install dash

使用 Jupyter 笔记本电脑…

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
from dash.dependencies import Input, Output

实时更新

作者图片

在这一部分,我们将讨论如何让您的仪表板实时运行

是的,你没听错。

Dash 允许其用户通过更新其数据源来实时自动化仪表板,而无需任何交互。这是通过实现间隔组件来实现的。

仪表板核心部件—间隔

dash 核心组件中的 interval 组件是一个触发器,它将定期触发回调。要在应用程序上实现这一点,只需将间隔连接到您需要更新的标签或图表,然后让奇迹发生。

我们将通过一个简单的例子来探讨这个问题。

app = dash.Dash()app.layout = html.Div([
    html.H1(id='live-counter'),
    dcc.Interval(
        id='1-second-interval',
        interval=1000, 
        n_intervals=0
    )
])[@app](http://twitter.com/app).callback(Output('live-counter', 'children'),
              [Input('1-second-interval', 'n_intervals')])
def update_layout(n):
    return 'This app has updated itself for {} times, every second.'.format(n)if __name__ == '__main__':
    app.run_server()

作者图片

在本节中,我们简单地定义了一个 H1 标签和一个区间组件。然后我们定义了一个回调函数,将区间组件作为输入,将 H1 标签作为输出。

组件中的一个重要属性是 interval 属性,它定义了组件触发的频率。在这里,我们采取 1 秒钟的间隔。

这意味着回调函数会每 1 秒自动触发一次。

最后,我们可以利用 interval 组件中的 n 属性,它会根据我们定义的时间间隔自动更新。只需插入 n 作为我们显示的文本的一部分,以显示实时变化。

向上拉平

让我们把它提高一个档次,好吗?
我们如何为实际的实现这一点?

很简单,我们更新图表本身。

作者代码

作者图片

在这个代码块中,我们简单地定义了一个图形组件和一个区间组件。然后我们定义了一个回调函数,将 interval 组件作为输入,图形的数字作为输出。

在我开始解释之前,一个好的流程图总是有帮助的。

作者图片

每秒钟,带有随机数的新数据被追加到我们的数据源中。然后基于那个更新的数据源绘制一个新的图表。应用程序上的图形随后会被更新后的图形替换为

这里,我们只是将随机数作为数据插入到数据源中。但是,如果您正在跟踪,您将知道您可以基于您的管道轻松地追加/覆盖您的数据源

你在实时搜集数据吗?

您是否在为您的网站可视化交易数据?

您可以轻松地将它声明为您的数据源,并每一秒/每一分/每一天都将其可视化。

我希望你现在意识到 Dash 有多强大。如何利用它取决于你的想象力。

注意:注意更新图表的时间间隔太小。拥有实时数据而没有真正的用例是不明智的,因为在更新数据源时可能会有极其繁重的计算,更不用说绘制极其繁重的图形了。

高级定制

所以现在你已经能够建立图表并自动化它们了。下一步是什么?

你需要设计定制你的网络应用,让它对用户来说看起来很漂亮。从颜色到定位,Dash 让你只用一行代码就能轻松做到。

半铸钢ˌ钢性铸铁(Cast Semi-Steel)

CSS 代表层叠样式表,它是设计 HTML 标签样式的主要语言。如果你希望美化你的网络应用,学习 CSS 是必须的。

如何添加 CSS

Dash 允许您在 Python 代码本身中添加 CSS。
对于 Dash 中几乎每一个 组件,都有一个名为‘style’的属性,允许你通过 Python 字典为那个组件声明 CSS。

html.H1(children='Hello World!',
style={'width':'20%','display':'inline-block'})

那很酷。然而,如果您的 web 应用程序可伸缩,有一种更好的方法来声明您的 CSS。

专门为每个组件声明 CSS 是低效的,它还会降低应用程序的加载时间。

因此,我们可以在 Dash 中使用 Classname 解决方案,它本质上是 HTML 元素的 class 属性。

截图来自剧情

在开始 Dash 代码的同一个文件夹中,创建另一个名为 assets 的文件夹,并将所有 CSS 和 Javascript 代码放入其中。默认情况下,最新的 Dash 版本将读取所有以。css 和。js 从资产文件夹并将其应用到 web 应用程序。

app.py:

app = dash.Dash(__name__)app.layout = html.H1(children='Hello World!', 
className= 'H1-Text H1-Text-Display')if __name__ == '__main__':
    app.run_server()

app.css:

.H1-Text{
 width:20%;
}.H1-Text-Display{
 display:inline-block;
}

这样,您可以在 Dash 代码中为不同的组件重用类。
让它更干净更快捷。

注意:为了让 Dash 默认读取 assets 文件夹,请在声明 app = dash 时包含 name in。破折号(name)。

结论

照片由 YTCountUnsplash 上拍摄

祝贺你, 你在短跑方面又上了一个台阶。

在这篇文章中,你学到了—

  1. Dash —实时更新
  2. 破折号—添加 CSS

极限是天空。现在去吧,做点东西,和我分享。我等着呢。

在你走之前

我们的数据之旅还没有结束。我正在撰写更多关于数据行业的故事、文章和指南。你绝对可以期待更多这样的帖子。与此同时,请随意查看我的其他文章来暂时填补您对数据的渴望。

像往常一样,我引用一句话作为结束。

数据是新的科学。大数据掌握着答案
VMware 首席执行官帕特·基尔辛格

订阅我的简讯保持联系。

也可以通过 我的链接 注册一个中等会员来支持我。你将能够从我和其他不可思议的作家那里读到无限量的故事!

我正在撰写更多关于数据行业的故事、文章和指南。你绝对可以期待更多这样的帖子。与此同时,你可以随时查看我的其他 文章 来暂时填补你对数据的渴望。

感谢 的阅读!如果你想和我联系,请随时通过 nickmydata@gmail.com 联系我或者我的 LinkedIn 个人资料 。你也可以在我的Github中查看之前写的代码。

用于数据科学的 Python 在执行机器学习之前要做什么?

原文:https://towardsdatascience.com/python-for-data-science-what-to-do-before-performing-machine-learning-a30f62465632?source=collection_archive---------24-----------------------

不要沉迷于机器学习模型,先了解你的数据。

你好,读者,
欢迎来到另一集“数据会让你变得富有”,在这里我将分享我的经验、指南和我的数据之旅的故事。
如果你是来学习新东西的,请继续阅读,我保证你会从我的所有文章中有所收获,因为我的主要动机是为我的观众提供价值。这就是我介绍自己的方式,即使是在面试中。

本周,我们将谈论机器学习
对,大家都感兴趣的话题。每个数据科学家都在展示他们的模型,比较他们的准确度分数,而他们中的一些人甚至不知道这些数据是关于什么的。

谷歌趋势的机器学习趋势

机器学习正在兴起。我们都知道。
基于 Google Trends,它甚至与数据科学本身作为一个话题不相上下,
我们都知道数据科学有多热门。

我经常看到,当谈到数据时,初级数据从业者脑海中闪现的第一件事是机器学习……而且不仅仅是他们。

最近,我参加了公司内部的黑客马拉松
由组织的最高管理层决定的进入前 3 名的想法,都与机器学习有关。在这一点上,很难忽视机器学习,因为每个人都在学习。
然而,只有极小比例的数据从业者能做好。

忘记人工智能吧——在大数据这个勇敢的新世界里,我们应该提防的是人工白痴。—汤姆·查特菲尔德

不要误解我。我不是来攻击机器学习的。相反,我在这里指导你如何做得更好。不要在没有首先了解什么是业务需求的情况下盲目地投入机器学习。在了解你的数据集之前,不要开始考虑用什么算法。如果你没有完全掌握你的问题陈述,又是什么影响了它,你怎么知道应该包括哪些栏目?

我们很多人都被细节所困扰,但最终,这完全取决于我们能为我们工作的组织提供多少价值。为了提供这样的影响,我们必须完全理解我们的数据集,这就引出了我的下一个话题。

数据探索

照片由威利安·贾斯登·德·瓦斯康塞洛斯Unsplash 上拍摄

在决定对数据集执行何种技术之前,您必须首先完全理解它。你可以通过探索数据集来实现。

探索是以发现信息或资源——维基百科为目的的搜索行为

下面是维基百科(100%可信)在 Exploration 上提供的定义。现在把它应用到你的数据集中。

就像上面的图像一样,您现在处于数据集中的陌生区域。你可以通过问这样的问题来更好地理解它:

  • 数据集的目标是什么?
  • 我们试图衡量的指标是什么?
  • 每列是什么意思?

为了回答这些问题,我们通过使用熊猫来彻底检查数据。如果我们能够可视化某些点,那就更清楚了。

先决条件

数据探索大量使用熊猫
因此,你应该可以轻松地浏览它。你可以通读一下我写的关于熊猫基础知识的文章来刷新你的记忆。

[## 用于数据科学的 Python 熊猫指南

10 分钟内完成数据探索指南

towardsdatascience.com](/python-for-data-science-basics-of-pandas-5f8d9680617e)

除了熊猫之外,我们也将视觉化我们的发现。我对自己的可视化感到自豪,因为它让我有能力绘制出交互式图形。这在探索过程中非常有用,因为我可以流畅地浏览图表。如果你是 Plotly 的新手,请仔细阅读我关于如何使用 Plotly 的文章。

[## 面向数据科学的 python——Plotly 数据可视化指南

现在是 2020 年,是时候停止使用 Matplotlib 和 Seaborn 了

towardsdatascience.com](/python-for-data-science-a-guide-to-data-visualization-with-plotly-969a59997d0c) [## 用于数据科学的 Python 使用 Plotly 进行数据可视化的高级指南

如何在 Plotly 中添加和自定义滑块、下拉菜单和按钮

towardsdatascience.com](/python-for-data-science-advance-guide-to-data-visualization-with-plotly-8dbeaedb9724)

我几乎涵盖了你在这里需要的一切。不客气

现在你已经设置好了,剩下的就是进入代码了。让我们直入主题吧。

进口

像往常一样,我们将与 Jupyter 笔记本 一起工作。

#all plotly
from plotly.offline import init_notebook_mode,iplot
import plotly.graph_objects as go
import cufflinks as cf
init_notebook_mode(connected=True)#others
import pandas as pd
import numpy as np

导入数据集

在本文中,我们将使用一个 电信客户流失数据集

df = pd.read_csv(filepath)

数据集摘要

df.head(5)
df.info()

df.head()和 df.info()是获得数据集良好感觉的一种极其快速和简单的方法。从这里,我们可以通过查看数据集的前 5 行来大致了解数据集。

然而,我们看到有 21 列,Jupyter 不能提前显示所有内容。因此,我们还没有一个清晰的图像。

查看 df.info(),我们可以看到有 7032 行和 21 列。我们还可以看到所有列的名称、数据类型以及有多少非空值。巧合的是,所有的列都有 7032 个非空值,这意味着在我们的数据集中没有任何缺失数据。通常情况下,情况并非如此。我们可以通过以下方式检查缺失的数据:

df.isnull().sum()

这将返回所有的列以及每一列有多少 null 值。

之后,我们希望了解所有列的含义。
既然这是一个已发布的数据集,你可以在 数据集上找到 本身的链接。
再说一遍,通常不是这样。我们可以通过以下方式进一步了解我们的专栏:

df.nunique()

这将返回所有列及其唯一值的数量。

我们首先定义我们的度量。
为什么首先要创建这个数据集?
它是为了研究(和预测)某个电信公司的流失而创建的。
因此,很明显这里的列 Churn 是我们的度量列。

我们观察到 customerID 有 7032 个唯一值,这与数据集中的行数相同。这意味着 customerID 是我们的唯一行标识符。

对于月费用总费用任期列,我们可以根据它们拥有的唯一值和它们的数据类型推断出它们是数值列。

对于剩余的列,我们看到它们有 2、3 和 4 个唯一值。这可能意味着它们是分类列。

为了总结我们刚刚获得的信息并充分利用它们,我们可以为它们创建变量:

#defining all our columns
Id_col     = ['customerID']
metric_col = ["Churn"]
cat_cols   = df.nunique()[df.nunique() <= 4][df.nunique() > 2].keys().tolist()
cat_cols   = [x for x in cat_cols if x not in metric_col]
bool_cols = df.nunique()[df.nunique() == 2].keys().tolist()
bool_cols = [x for x in bool_cols if x not in metric_col]
num_cols   = [x for x in df.columns if x not in cat_cols + metric_col + Id_col + bool_cols]

探索数据集

探索数据集有不同的方式。我个人的做法是首先围绕指标栏,因为这是我们试图研究的内容。

到现在为止,你可能已经明白,这是一个包含 7032 名客户的数据集,以及他们所有的属性,如果他们已经停止使用该公司的服务。因此,我们可以研究他们拥有的属性和他们的流失率之间的关系。

一个简单的例子就是性别列。
基本问题比如—
离职的男性还是女性多?

我们肯定可以通过探索我们的数据集来回答这个问题。

让我们先来看看有多少真正的客户被搅了。

#defining data
trace = go.Pie(labels=df["Churn"].value_counts().keys().tolist(), 
                values=df["Churn"].value_counts().values.tolist(), 
                marker=dict(colors=['red']), 
                # Seting values to 
                hoverinfo="value"
              )
data = [trace]#defining layout
layout = go.Layout(title="Churn Distribution")#defining figure and plotting
fig = go.Figure(data = data,layout = layout)
iplot(fig)

看起来大约有 27%的顾客放弃了他们的服务。

由于我们的客户流失列仅包含 2 个唯一值,即“是”或“否”。
我们可以将数据集分为流失的客户和停留客户。这样我们可以更深入地研究数据。****

#Separating customers who churned and customers who stayed
churn     = df[df["Churn"] == "Yes"]
not_churn = df[df["Churn"] == "No"]

别在我面前睡着了,我们才刚刚开始。

让我们首先处理所有的分类列以及它们与我们的度量标准的关系。我们进一步将我们的分类列分为布尔型分类型,布尔型本身只有两个唯一值。

让我们来看看所有的分类列及其实际的唯一值。

#all categorical columns and thier unique values
for i in cat_cols:
    for j in df[i].unique().tolist():
        print(i + ' unique values are ' + j)

有几列像在线备份在线安全同时包含值无互联网服务。对我们来说,这本质上意味着同样的事情,那就是他们没有那个特征。因此,我们可以将所有无互联网服务转换为

columns_to_be_replaced = [ 'OnlineSecurity', 'OnlineBackup', 'DeviceProtection',
                'TechSupport','StreamingTV', 'StreamingMovies']for i in columns_to_be_replaced : 
    df[i]  = df[i].replace({'No internet service' : 'No'})

我们的数据现在更清晰了,更容易处理。

形象化

下一步是对照我们的指标来可视化我们所有的特性。重要的是以一种你的观众容易阅读的方式来形象化它。

分类列:

我绘制了多个支线剧情来展示分类特征相对于变动的分布,从而实现了这种可视化。

如果你觉得很难理解,刷新我的文章:

#defining data
data = {}
for i in cat_cols:
    for j in df[i].unique().tolist():
        data[i + '_' + j] = go.Bar(
    x=['churn','not churn'],
    y=[(churn[i][churn[i] == j].value_counts().values.tolist()[0]/churn[i].value_counts().values.sum())*100,(not_churn[i][not_churn[i] == j].value_counts().values.tolist()[0]/not_churn[i].value_counts().values.sum())*100],
    name = j,width=0.4)

对于上面的代码块,我们为的每个唯一值定义了一个条形图,该值出现在的每个列中。结果我们总共有 13 个痕迹。

#defining layout
layout = go.Layout(
    title = 'Distribution of Categorical Columns in customer attrition',
    barmode='stack',
    showlegend= False
)#defining figure and plotting
fig = tools.make_subplots(rows=2, cols=2, subplot_titles = ('MultipleLines', 'InternetService', 'Contract', 'PaymentMethod'))
fig.append_trace(data['MultipleLines_No phone service'], 1,1)
fig.append_trace(data['MultipleLines_No'], 1,1)
fig.append_trace(data['MultipleLines_Yes'], 1,1)
fig.append_trace(data['InternetService_DSL'], 1,2)
fig.append_trace(data['InternetService_Fiber optic'], 1,2)
fig.append_trace(data['InternetService_No'], 1,2)
fig.append_trace(data['Contract_Month-to-month'], 2,1)
fig.append_trace(data['Contract_One year'], 2,1)
fig.append_trace(data['Contract_Two year'], 2,1)
fig.append_trace(data['PaymentMethod_Electronic check'], 2,2)
fig.append_trace(data['PaymentMethod_Mailed check'], 2,2)
fig.append_trace(data['PaymentMethod_Bank transfer (automatic)'], 2,2)
fig.append_trace(data['PaymentMethod_Credit card (automatic)'], 2,2)
fig.layout.update(layout)
iplot(fig)

从图中,我们可以清楚地观察到流失客户与非流失客户的某些模式。首先,大部分流失客户订阅了按月合同,而留下来的客户分享了几乎相同的 T2 分布。这可能表明逐月订阅本身存在产品缺陷。我不会在这里进入所有的细节,但我们可以有效地得出某些结论,这将有助于我们以后的机器学习模型。

让我们对布尔列做同样的事情。

#defining data
data = {}
for i in bool_cols:
    for j in df[i].unique().tolist():
        data[i + '_' + j] = go.Bar(
    x=['churn','not churn'],
    y=[(churn[i][churn[i] == j].value_counts().values.tolist()[0]/churn[i].value_counts().values.sum())*100,(not_churn[i][not_churn[i] == j].value_counts().values.tolist()[0]/not_churn[i].value_counts().values.sum())*100],
    name = j,width=0.4)
trace = list(data.keys())#defining layout, fig and plotting
fig = tools.make_subplots(rows=4, cols=3, subplot_titles = ('Partner','SeniorCitizen','Partner', 'Dependents',
       'PhoneService', 'OnlineSecurity', 'OnlineBackup', 'DeviceProtection',
       'TechSupport', 'StreamTV','StreamingMovies','PaperlessBilling'))
fig.append_trace(data[trace[0]], 1,1)
fig.append_trace(data[trace[1]], 1,1)
fig.append_trace(data[trace[2]], 1,2)
fig.append_trace(data[trace[3]], 1,2)
fig.append_trace(data[trace[4]], 1,3)
fig.append_trace(data[trace[5]], 1,3)
fig.append_trace(data[trace[6]], 2,1)
fig.append_trace(data[trace[7]], 2,1)
fig.append_trace(data[trace[8]], 2,2)
fig.append_trace(data[trace[9]], 2,2)
fig.append_trace(data[trace[10]], 2,3)
fig.append_trace(data[trace[11]], 2,3)
fig.append_trace(data[trace[12]], 3,1)
fig.append_trace(data[trace[13]], 3,1)
fig.append_trace(data[trace[14]], 3,2)
fig.append_trace(data[trace[15]], 3,2)
fig.append_trace(data[trace[16]], 3,3)
fig.append_trace(data[trace[17]], 3,3)
fig.append_trace(data[trace[18]], 4,1)
fig.append_trace(data[trace[19]], 4,1)
fig.append_trace(data[trace[20]], 4,2)
fig.append_trace(data[trace[21]], 4,2)
fig.append_trace(data[trace[22]], 4,3)
fig.append_trace(data[trace[23]], 4,3)
fig.layout.update(layout)
iplot(fig)

太美了。从这里,我们可以判断某个特性在流失客户和非流失客户之间的分布是否有很大差异。首先,我们可以看到像无纸化记账合作伙伴这样的功能有很大的不同。再说一遍,我不想深入讨论,但你会意识到,你可以在这里做出某些结论。

数字列:

让我们想象一下流失客户和非流失客户的每个数字特征的分布。我们先从任期开始。

#defining data
trace1 = go.Histogram(x  = churn['tenure'],
                          histnorm= "percent",
                          name = "Churn Customers",
                          marker = dict(line = dict(width = .5,
                                                    color = "black"
                                                    )
                                        ),
                         opacity = 1
                         ) 

trace2 = go.Histogram(x  = not_churn['tenure'],
                      histnorm = "percent",
                      name = "Non churn customers",
                      marker = dict(line = dict(width = .5,
                                          color = "black"
                                         )
                             ),
                      opacity = .7
                     )
data = [trace1,trace2]#defining layout
layout = go.Layout(dict(title ='tenure' + " distribution in customer attrition ",
                        plot_bgcolor  = "rgb(243,243,243)",
                        paper_bgcolor = "rgb(243,243,243)",
                        xaxis = dict(gridcolor = 'rgb(255, 255, 255)',
                                         title = 'tenure',
                                         zerolinewidth=1,
                                         ticklen=5,
                                         gridwidth=2
                                        ),
                        yaxis = dict(gridcolor = 'rgb(255, 255, 255)',
                                         title = "percent",
                                         zerolinewidth=1,
                                         ticklen=5,
                                         gridwidth=2
                                        )
                       ),barmode = 'overlay'
                  )#defining figure and plotting
fig  = go.Figure(data=data,layout=layout)
iplot(fig)

很快我们就能看到分布的巨大差异。
具体来说,在流失的客户中,大约有一半只在电信公司呆了不到 3 个月。另一方面,留下来的客户在任期上分享了一个相当平均的分配,稍微偏向于更长的任期。

让我们对总费用月费用做同样的事情。

#defining data
trace1 = go.Histogram(x  = churn['MonthlyCharges'],
                          histnorm= "percent",
                          name = "Churn Customers",
                          marker = dict(line = dict(width = .5,
                                                    color = "black"
                                                    )
                                        ),
                         opacity = 1
                         )trace2 = go.Histogram(x  = not_churn['MonthlyCharges'],
                      histnorm = "percent",
                      name = "Non churn customers",
                      marker = dict(line = dict(width = .5,
                                          color = "black"
                                         )
                             ),
                      opacity = .7
                     )
data = [trace1,trace2]#defining layout
layout = go.Layout(dict(title ='MonthlyCharges' + " distribution in customer attrition ",
                        plot_bgcolor  = "rgb(243,243,243)",
                        paper_bgcolor = "rgb(243,243,243)",
                        xaxis = dict(gridcolor = 'rgb(255, 255, 255)',
                                         title = 'monthlycharges',
                                         zerolinewidth=1,
                                         ticklen=5,
                                         gridwidth=1
                                        ),
                        yaxis = dict(gridcolor = 'rgb(255, 255, 255)',
                                         title = "monthlycharges",
                                         zerolinewidth=1,
                                         ticklen=5,
                                         gridwidth=1
                                        )
                       ),barmode = 'overlay'
                  )#defining figure and plotting
fig  = go.Figure(data=data,layout=layout)
iplot(fig)

类似地,我们看到大多数购买了的顾客每月花费了 70 到 110 的费用。另一方面,大多数入住的顾客每月花费少于 30 美元。作为一名数据从业者,您可以与企业沟通,进一步了解这些客户将钱花在了什么产品/服务上,并进一步分析该产品/服务。

#defining data
trace1 = go.Histogram(x  = churn['TotalCharges'],
                          histnorm= "percent",
                          name = "Churn Customers",
                          marker = dict(line = dict(width = .5,
                                                    color = "black"
                                                    )
                                        ),
                         opacity = 1
                         )trace2 = go.Histogram(x  = not_churn['TotalCharges'],
                      histnorm = "percent",
                      name = "Non churn customers",
                      marker = dict(line = dict(width = .5,
                                          color = "black"
                                         )
                             ),
                      opacity = .7
                     )
data = [trace1,trace2]#defining layout
layout = go.Layout(dict(title ='TotalCharges' + " distribution in customer attrition ",
                        plot_bgcolor  = "rgb(243,243,243)",
                        paper_bgcolor = "rgb(243,243,243)",
                        xaxis = dict(gridcolor = 'rgb(255, 255, 255)',
                                         title = 'TotalCharges',
                                         zerolinewidth=1,
                                         ticklen=5,
                                         gridwidth=1
                                        ),
                        yaxis = dict(gridcolor = 'rgb(255, 255, 255)',
                                         title = "TotalCharges",
                                         zerolinewidth=1,
                                         ticklen=5,
                                         gridwidth=1
                                        )
                       ),barmode = 'overlay'
                  )#defining figure and plotting
fig  = go.Figure(data=data,layout=layout)
iplot(fig)

总费用是而不是一个很好的特征来做出结论。想想吧。
客户的任期越长,客户花费的总费用越高。因此,总费用直接受到该客户的租期和月费用的影响。我们看到,大多数流失客户的总支出少于 100,这是有道理的,因为我们知道,大多数流失客户在前 3 个月就退出了。

也就是说,让我们想象一下任期每月 费用之间的关系,同时了解这两个特征对总费用的影响。当我们这样处理多个变量时,我会想到泡沫图。

#defining data
trace1 = go.Scatter(x=churn['MonthlyCharges'],y=churn['tenure'],mode = "markers",marker = dict(line = dict(color = "blue"),
                                                                   size=churn['TotalCharges']/180,
                                                        color = 'blue',

                                                      ),
                        opacity = .9
                       ,name='churn',showlegend=True)trace2 = go.Scatter(x=not_churn['MonthlyCharges'],y=not_churn['tenure'],mode = "markers",marker = dict(line = dict(color = "red"),
                                                                   size=not_churn['TotalCharges']/180,
                                                       color = 'red',

                                                      ),
                        opacity = 0.5
                       ,name='not_churn',showlegend=True)
data = [trace1, trace2]

#defining layout
layout = go.Layout(dict(title = 'Monthly Charges vs Tenure (radius = total charges)',
                            plot_bgcolor  = "rgb(243,243,243)",
                            paper_bgcolor = "rgb(243,243,243)",
                            xaxis = dict(gridcolor = 'rgb(255, 255, 255)',
                                         title = "monthly charges",
                                         zerolinewidth=1,ticklen=5,gridwidth=2),
                            yaxis = dict(gridcolor = 'rgb(255, 255, 255)',
                                         title = "tenure",
                                         zerolinewidth=1,ticklen=5,gridwidth=2),
                            height = 600
                           )
                      )#defining figure and plotting
fig = go.Figure(data,layout=layout)
iplot(fig)

从图中,我们可以看到,代表总电荷的气泡在图的右上角变大。这实质上意味着总费用直接取决于每月费用和客户的使用期限。

至此,您已经对数据集有了相对扎实的 理解。我将在这里停止我的探索,但这只是我自己。您可以从不同角度进一步研究数据集,例如了解要素之间的关系。天空是极限。

您还可以在这里找到本文的完整代码:

[## 机器学习之前做什么

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/nickefy/what-to-do-before-machine-learning/blob/master/What To Do Before Machine Learning.ipynb)

恭喜

照片由阿里·叶海亚Unsplash 上拍摄

我赞扬你坚持到最后,因为这可能意味着你对数据充满热情。你应该担心,它正在接管。

简而言之,这里是你在这里学到的东西:

  • 数据探索
  • 拆分不同类型的数据
  • 在数据中定义行标识符、度量和功能
  • 可视化数据以帮助探索

你现在更愿意建立一个机器学习模型来预测客户的流失,这也是我下一篇文章要做的。

在你走之前

我们还没有完成这个数据集。我将对这个数据集执行分类机器学习,以预测客户下次是否会流失。我还在撰写更多关于数据行业的故事、文章和指南。你绝对可以期待更多这样的帖子。与此同时,请随意查看我的其他文章来暂时填补您对数据的渴望。

最后,我总是会引用一句话。

数据是新的科学。大数据掌握着答案。— 安吉拉·阿伦茨

订阅我的时事通讯,保持联系。

感谢 的阅读!如果你想与我取得联系,请随时通过 nickmydata@gmail.com 或我的 linkedIn 个人资料 联系我。也可以在我的Github中查看代码。

金融 Python:现代投资组合理论的实现

原文:https://towardsdatascience.com/python-for-finance-an-implementation-of-the-modern-portfolio-theory-39cdbaeefbd4?source=collection_archive---------41-----------------------

现代投资组合理论和有效边界概念在 Python 中的实现。

该脚本的输出是一个用散景创建的交互式仪表板。有 3 个主要区域:代表有效边界的图,股票价格的时间序列,以及具有最小风险、最大夏普比率和最大回报的投资组合的组成。

现代投资组合理论

现代投资组合理论(MPT)是一种用数学术语描述诸如多样化和风险管理等概念的金融理论。MPT 为投资者提供了建立多元化投资组合的工具,在给定的风险水平下,投资组合的回报最大化。风险通常用标准差来衡量。

这个理论是由经济学家哈里·马科维茨提出的,他因为这项研究获得了 1990 年的诺贝尔经济学奖。该理论的数学公式涉及方差和协方差等概念。如有兴趣了解详情,请访问 维基百科专用页面

有效边界

有效边界的概念可以正式定义为在任何给定风险下具有最高回报的投资组合集合,它与 MPT 密切相关。该边界通常呈“C”形,如下图所示,可以区分三个点:

  • 风险最小的投资组合。
  • 回报最大的投资组合。
  • 具有最大夏普比率的投资组合,这通常是投资者的首选,因为它被认为是风险水平和预期回报之间的良好折衷。

MPT 的 Python 实现

下面介绍的 Python 笔记本使用户能够通过模拟定制数量的投资组合,轻松探索投资机会的设计空间,并创建一个可用于选择所需交易策略的交互式仪表盘。

完整的代码可以在下面的链接中找到,在我的 GitHub 页面上,还有“python for finance”系列的其他脚本。

[## 里坡/现代警察理论

现场脚本执行数值模拟,并找到最佳的投资组合构成符合现代…

github.com](https://github.com/r-poli/ModernPorfolioTheory)

实现是用 Python 3 实现的,数据的下载是通过 FINNHUB 应用编程接口(API)完成的。用户需要注册(注册是免费的)来获得个人 API 密钥。

该脚本由 3 部分组成:输入部分,主体和绘图部分。用户必须指定以下输入:

  • 感兴趣的股票或交易所交易基金(ETF)的符号列表(例如,特斯拉公司的“TSLA”;“VOO”为先锋 500 指数基金 ETF 等。),包括每只股票或 ETF 的简短描述。
  • 她/他想要模拟的投资组合数量。
  • 她/他希望用来执行回溯测试的日期范围。
  • API 密匙,很容易免费获得这里
*## DEFINE INPUTS*  
**ticks** = ["EMB", "AGG", "VGT", "TSLA", "AMZN"] 
**line_name** = ["Emerging countries debt", "US debt", "S&P 500 Vanguard ETF", "Tesla", "Amazon"] 
**num_port** = 1000 
**start_date** = '01/06/2015' 
**end_date** = '27/06/2020' 
**api_key** = "YOUR API KEY"

你可以在我的 GitHub 页面的笔记本中找到关于代码的更多评论和其他细节。在那里,您还可以找到“Python for finance”系列的其他工具。

享受,快乐交易!

https://www.linkedin.com/in/riccardopoli/里卡多里坡
T6

免责声明:投资股市有风险,可能导致金钱损失。这篇文章的内容不能作为财务建议。

Python for Finance —分析应收账款

原文:https://towardsdatascience.com/python-for-finance-analysing-account-receivables-35d3d809c769?source=collection_archive---------35-----------------------

分析应收账款对于识别潜在的公司收款问题非常重要。

应收账款是客户欠公司的金额。在这个故事中,我们将使用 Python 来分析科技行业公司的应收账款。这个故事将分成两部分。首先,我们将开始分析苹果公司的应收账款。然后,我们将分析科技行业中一组可比公司的应收账款与销售比率。

照片由 卢卡斯 发自 Pexels

如何阅读应收账款

应收账款是公司的金融资产,因为它们代表公司因销售商品或服务而拥有的金额。

投资者经常用来比较公司间应收账款的比率之一是应收账款对销售比率。就销售额而言,应收账款的高比率表明一个公司有很大比例的赊销。高比率会给公司带来一定的风险,因为债务人可能无法偿还债务。

每个公司都需要估计有多少应收账款无法收回。这些被称为坏账应收账款,会减少公司的利润和应收账款总额。因此,保持较低的应收账款水平可能被视为一个好迹象,因为公司计提的坏账准备将因此减少。

另一方面,非常低的应收账款与销售比率可能表明一个公司对其客户过于积极。因此,积极的收集方法可能会影响公司与客户的关系,从而影响销售。

使用 Python 进行应收账款趋势分析

首先,我们将使用 Python 为 Apple 执行应收款趋势分析。这将向我们展示应收账款在过去几个季度的绝对值是如何变化的。

我们将使用免费的财务 APIfinancialmodelingprep来检索财务数据。如果您已经阅读了我之前的文章,那么下面的代码对您来说会很熟悉。因此,我不会详细介绍它的功能。

基本上,我们向 API 端点发出 get 请求来检索资产负债表数据。然后,我们解析响应以提取应收款数据并将其添加到 Python 字典中。

最后,我们将字典转换成熊猫数据框架。

import requests
import pandas as pd

all_Receivables = {} 
stock = 'AAPL'

balanceSheet = requests.get(f'https://financialmodelingprep.com/api/v3/financials/balance-sheet-statement/{stock}?period=quarter')

balanceSheet = balanceSheet.json()

all_Receivables[stock] = {}

for item in balanceSheet['financials']:
  receivables = item['Receivables']
  period = item['date']
  all_Receivables[stock][period] = receivables
all_Receivables

receivables_apple = pd.DataFrame.from_dict(all_Receivables, orient='index')
receivables_apple = receivables_apple.T 

一旦我们有了 Pandas 数据框架,我们就可以使用库 Plotly 来绘制条形格式的应收账款:

import plotly.express as px

fig = px.bar(receivables_apple, x=receivables_apple.index,y =receivables_apple[stock],title='Account Receivables: ' + stock)

fig.show()

使用 Python 比较公司间的应收账款

在上一节中,我们绘制了苹果公司的应收账款趋势。我们可以看到应收账款随着时间的推移在增加。这可能是由于销售额的增长转化为更高水平的应收账款。

因此,仅仅关注应收账款可能不足以帮助投资者。在本节中,我们将进一步分析这两种情况:

  • 应收账款对销售比率。这将表明销售方面的应收账款水平。这将非常有助于将一家公司与可比较的公司进行比较。
  • 同行业不同公司的应收账款对比

首先,正如你在下面的代码部分看到的,我们有一个在技术领域运营的公司列表。在我之前的一篇文章中,我向你展示了如何通过程序提取一个行业中所有公司的报价。

接下来,我们遍历列表中的每个公司,以便 提取应收账款和收入来计算应收账款与销售额的比率。 接下来,我们将这三个变量添加到一个 Python 字典中。最后,正如我们在上一节中所做的,我们将字典转换成熊猫数据帧。

technological_companies = ['MSFT','AAPL','AMZN','GOOG','IBM','CSCO','ORCL','SAP','IBM']
all_Receivables = {} 

for company in technological_companies:
  try:
#Retrieve Balance Sheet Data for each of the companies in the list
    balanceSheet = requests.get(f'https://financialmodelingprep.com/api/v3/financials/balance-sheet-statement/{company}?period=quarter')
    balanceSheet = balanceSheet.json()
    all_Receivables[company] = {}
    for item in balanceSheet['financials']:
      receivables = item['Receivables']
      all_Receivables[company]['receivables'] = receivables

    IS = requests.get(f'https://financialmodelingprep.com/api/v3/financials/income-statement/{company}?period=quarter')
    IS = IS.json()
    for item in IS['financials']:
      revenues = item['Revenue']
      all_Receivables[company]['Revenue'] = revenues

    all_Receivables[company]['receivables_to_sales'] = float(receivables)/float(revenues)
  except:
    pass

receivables_companies = pd.DataFrame.from_dict(all_Receivables, orient='index')
receivables_companies = receivables_companies.T
print(receivables_companies)

然后,我们执行一些数据操作,只保留行 receivables_to_sales ,因为这是我们想要绘制的信息。

#keep only receivables to sales
receivables_companies = receivables_companies[receivables_companies.index =='receivables_to_sales'] 
receivables_companies = receivables_companies.T.reset_index()

最后,在清理数据框架后,我们可以使用 Plotly 绘制不同公司的应收账款与销售比率:

import plotly.express as px

fig = px.bar(receivables_companies, x=receivables_companies['index'],y =receivables_companies['receivables_to_sales'])

fig.show()

应收账款比较

包扎

我们已经看到了两种简单的方法来分析单个公司以及一组可比公司的应收账款。

在我们的例子中,我们可以看到,与同行公司相比,IBM 的应收账款与销售额比率非常高。作为完成我们分析的下一步,我们需要查看公司财务报告的财务注释,以了解高比率的原因。是因为 IBM 向客户提供长期付款吗?或者可能是公司没有足够的能力来管理应收账款的回收?

另一个极端,我们有比率非常低的亚马逊。这可能是因为亚马逊业务的一部分是直接销售给即时付款的客户。

在 Twitter 上关注我,了解更多关于 Python for Finance 的信息

原载于 2020 年 4 月 16 日【https://codingandfun.com】

金融 Python:金融市场的自动化分析

原文:https://towardsdatascience.com/python-for-finance-automated-analysis-of-the-financial-markets-f649375bf8b2?source=collection_archive---------31-----------------------

一种高度自动化的方法,用于按业务部门分析金融市场的表现。

本文中介绍的 Python 脚本已经被用于分析新冠肺炎对标准普尔 500 指数的各个业务部门的影响,但是也可以很容易地适用于任何其他的金融市场分析。

代码是用 Python 编程语言开发的,可以在我的 GitHub 存储库(下面的链接)中找到,作为一个 Jupyter 笔记本。

[## 里坡/金融市场分析

这款 Jupyter 笔记本使用户能够对以下行业或子行业进行自动股票市场分析

github.com](https://github.com/r-poli/FinancialMarketAnalysis)

该脚本使用标准的 Python 包(即 pandas、bokeh、math)以及用于下载标准普尔 500 股票价格的 yfinance API(应用程序编程接口)。该 API 可以免费使用,并且是公共的,这意味着用户不需要单独的 API 密钥。

***# Import libraries***
import **yfinance** as yf
import **pandas** as pd
from **bokeh**.plotting import figure
import **bokeh**.models as bmo
from **bokeh**.palettes import Paired11
from **bokeh**.io import show
from **bokeh**.models import ColumnDataSource, HoverTool
import **math**

在脚本的第一部分,用户需要定义名为 "depth" 的变量来定义分析的详细程度。这可以设置为“扇区或“子扇区”。选择“扇区将产生如图 1 所示的图,而“子扇区将产生类似于图 2 和图 3 所示的图。在最后一种情况下,用户还必须指定“过滤器”,即感兴趣的部分。过滤器的可用值有:通信服务非必需消费品消费品能源金融医疗工业信息技术材料房地产公用事业。

***# Example of input definition***
**depth** = '*sub_sector*'
**filter** = '*Information Technology*'

所有其他输入,如标准普尔 500 股票列表,以及当前市场表现的比较日期(2020 年初)都是自动设置的。

index_name = 'SP_500'
companies = pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies', flavor='bs4')[0]

此时,数据被下载,所有的计算被执行。正如预期的那样,yfinance API 用于收集财务数据。

df_all = pd.DataFrame()
color_df = pd.DataFrame({0})**for** stock **in** companies_codes:
  stock_data = yf.Ticker(stock.replace(".",""))
  stock_name = companies[company_label].loc[companies[code_label] == stock].values[0]
  df_all[stock_name] = stock_data.history(start="2020-01-01")['Close']

最后一部分是创建所有图的地方。

if depth == 'sector':df_sector = df_summary.groupby(['Sector']).mean()
    df_sector = df_sector.sort_values(by=['YTD_performance'], ascending=False)source2 = ColumnDataSource(data=dict(cum_sum_ytd=df_sector.YTD_performance.to_list(), sector=df_sector.index.to_list()))p = figure(plot_height=700, plot_width=1200, x_range=df_sector.index.to_list(), toolbar_location='right', y_range=[-50, 50],
               title='Year-to-date performance of individual sectors (S&P 500 stocks)', tools="save")color_map = bmo.CategoricalColorMapper(factors=df_summary['Sector'].unique(), palette=Paired11)p.vbar(x='sector', top='cum_sum_ytd', width=0.9, source=source2, fill_color={'field': 'sector', 'transform': color_map},
            legend='sector', line_width=0)p.xaxis.major_label_orientation = math.pi/3
    p.yaxis.axis_label = 'Year to date average performance (%)'p.title.text_font_size = '12pt'
    p.yaxis.axis_label_text_font_size = '12pt'show(p)

您可以在 GitHub 页面上的笔记本中找到对代码的进一步评论和其他细节。

新冠肺炎对金融市场的影响

在本节中,图 1、图 2 和图 3 总结了上述代码的输出。

新冠肺炎对我们的生活、习惯、实体经济和金融市场产生了前所未有的影响。疫情造成的金融冲击并不一致,各商业部门对危机的反应也不同。

从图 1 中可以看出,总的来说,所有部门都受到了疫情的负面影响,能源部门的损失最大。事实上,由于世界人口的很大一部分被封锁,对石油和天然气的需求大幅下降。工业部门也经历了重大损失,特别是在“航空航天和国防”以及“航空”分部门。主要原因是对这些服务的需求减少,这是由于现有的限制和对新冠肺炎病毒传播的恐惧。

医疗保健

医疗保健是受影响最小的行业,生物技术子行业的一些公司股价平均上涨了 16%,见图 2。这是因为许多公司正在新冠肺炎疫苗上投入资源。赢得这场竞赛的公司可能会有丰厚的利润。

图二。新冠肺炎对标准普尔 500“医疗保健”股的影响

通信服务

在这个前所未有的时代,智能工作以及人们对讲话和看望亲人的渴望增加了对视频会议应用程序和软件的需求。由于人们在许多国家被隔离,他们倾向于在流媒体服务上花费更多时间。因此,家庭娱乐和电信服务在疫情期间表现良好(分别增长 12%和 23%),图 3。

图 3。新冠肺炎对标准普尔 500“通讯服务”股票的影响

如果你想阅读更多关于该主题的内容,请参考我在几周前(2020 年 5 月)写的这篇文章,解释新冠肺炎对每个业务部门和子部门的影响。

注意安全,交易愉快!

https://www.linkedin.com/in/riccardopoli/ 里坡

免责声明:投资股票市场有风险,可能导致金钱损失。这篇文章的内容不能作为财务建议。

面向金融的 Python 完全初学者指南

原文:https://towardsdatascience.com/python-for-finance-the-complete-beginners-guide-764276d74cef?source=collection_archive---------6-----------------------

使用亚马逊股票数据的简单实践

照片由 SerpstatPexels 拍摄

欢迎阅读面向金融的 Python 完全入门指南。

在这篇文章中,我将带你完成一些很棒的实践练习,帮助你了解如何使用 Python 进行金融。首先,我将把你介绍给我们的朋友 Pyhton,然后我们将进入有趣的部分,即编程。正如副标题中提到的,我们将使用亚马逊股票数据。如果你想知道是否可以免费获得这些数据,答案是肯定的。股票数据可以在纳斯达克官方网站上找到。纳斯达克(全美证券交易商自动报价协会)是一个电子股票交易所,拥有 3300 多家上市公司。

亚马逊股票数据可以从这里下载。在这个网站上,你可以找到不同公司的股票数据,并使用这些数据集练习你的技能。我等不及了,让我们开始吧!

目录:

  • 计算机编程语言
  • 了解亚马逊股票数据
  • 数据清理
  • 数据可视化

计算机编程语言

Python 是一种通用编程语言,在分析数据方面越来越受欢迎。Python 还能让您快速工作,更有效地集成系统。世界各地的公司都在利用 Python 从他们的数据中收集知识。官方 Python 页面如果你想了解更多

理解数据

当您第一次将数据加载到 dataframe 中时,在开始操作它之前查看它是一个好习惯。这有助于理解你有正确的数据和一些关于它的见解。如前所述,在这个练习中,我们将使用一家纳斯达克公司的历史数据。我认为亚马逊是个不错的选择。在和我一起完成这个练习后,你将会学到一些技巧,让你能够使用不同的数据集来练习。

我们将使用的数据框架包含过去一个月(2020 年 6 月 24 日至 7 月 23 日)亚马逊股票的收盘价。

读出数据

import pandas as pd amzn = pd.read_csv('amzn_data.csv')

头部方法

为了对数据有所了解,我们要做的第一件事是使用 head 方法。当您在 dataframe 上调用 head 方法时,它会显示 dataframe 的前五行。运行这个方法后,我们还可以看到我们的数据是按日期索引排序的。

amzn.head()

结果

尾部法

另一个有用的方法我们称之为尾部方法。它显示数据帧的最后五行。假设您想查看最后三行,您可以在括号之间输入整数 3。

amzn.tail()

结果

描述方法

在深入之前,我们要调用的最后一个方法是 describe 方法。它返回给我们数据的统计摘要。默认情况下,describe 方法将返回所有数字列的汇总统计信息,例如在我们的示例中,所有列都是数字。汇总将包括以下项目:行数、平均值、标准偏差、最小值和最大值,最后是百分位数。

amzn.describe()

描述方法

为什么我们只得到 Volume 列的值,而没有得到其他列的值?这就是我们所说的数据准备。清理数据并为分析做好准备是一个主要步骤。在我们进行下一步之前,有几件事我们必须注意。请随意查看下面的帖子,了解更多关于使用不同列数据类型时的数据清理。

[## 清理 Python 中的数据(数据类型)

使用 pandas 操作数据类型的简单说明

medium.com](https://medium.com/python-in-plain-english/cleaning-data-in-python-data-types-46f9ebf2feef)

数据清理

我们前面提到 describe 方法专门处理数值,这意味着 Volume 列是我们的数据帧中唯一的数值。让我们检查列的数据类型。

amzn.dtypes

列数据类型

正如您在上面看到的,Volume 列是唯一的整数类型,其余的是对象类型。所以我们必须注意数据类型。但是在转换它们之前,我们已经清理了美元符号,否则,当我们试图将美元符号转换成数值时,我们的程序将会混乱。

amzn = amzn.replace({'\$':''}, regex = True) amzn.head()

去掉美元符号后

很好,现在我们可以转换数据类型了。我们不需要对日期和数量列做任何修改。我们将把 rest 列转换成一个数值,对于这个练习,我们可以使用 float 数值类型。

# Renaming column names and converting the data typesdf = amzn df.columns = ['Date', 'Close', 'Volume', 'Open', 'High', 'Low'] # Converting data types
df = df.astype({"Close": float, "Volume": int, "Open": float, "High": float, "Low": float}) df.dtypes

更改后的数据类型

太好了,我们解决了数据类型问题。现在,让我们尝试运行 describe 方法,看看它是如何工作的。

df.describe()

结果

干得好!现在,正如您在上面看到的,describe 方法与我们所有的数字列配合得非常好。我们还可以通过使用不同的参数来定制 describe 方法的结果。Describe 有三个我们将在本例中使用的参数:include、percentiles 和 exclude。

df.describe(include = "float")

结果

df.describe(include = "object")

结果

df.describe(exclude = "int")

结果

df.describe(percentiles = [0.1, 0.5, 0.9])

结果

过滤数据

比较运算符

  • <
  • <=
  • =

  • ==
  • !=

我们将使用这些运算符将特定值与列中的值进行比较。结果将是一系列的布尔值:真和假。如果比较正确,则为真,如果比较不正确,则为假。

被收盘价掩盖

当我们使用 loc[]运算符将一个布尔序列传递给一个数据帧时,将返回一个只包含真值的新数据帧。

# Closing price more than 3000mask_closeprice = df.Close > 3000 high_price = df.loc[mask_closeprice] high_price.head()

结果

Pandas 提供了运算符来组合布尔比较的不同结果。这些运算符是:And、Or、Not。我们可以使用这些运算符来创建更复杂的条件。例如,假设我们要查看收盘价超过 3000 且成交量超过 500 万的 AMZN 股票数据。我们是这样做的:

# Closing price more than 3000 and traded volume more than 5mask_closeprice = df.Close > 3000 
mask_volume = df.Volume > 5000000millionhigh_price_volume = df.loc[mask_closeprice & mask_volume]

high_price_volume.head()

结果

数据可视化

可视化数据是理解数据的重要一步。它帮助我们看到的不仅仅是一行行的值,它让我们对数据有了更好的了解。当我们想要在不同的数据值之间进行比较时,它也是有帮助的。

可视化数据也是理解和查看不同列之间关系的好方法。

Matplotib

最常用的 2D 绘图库叫做 Matplotlib。这个库非常强大,它也有一个学习曲线。在这个学习曲线的帮助下,围绕这个库建立了其他库。

让我们画出过去一个月的股票价格。我们的 x 轴是日期,y 轴是每天的收盘价。这将向我们展示股票价格在一个月内的变化。从商业角度来说,这种线图被称为价格波动图,它有助于检测股价的季节性模式。

df.plot(x='Date', y='Close')

线形图

旋转

plot 方法提供了许多有趣的参数,您可以尝试一下。其中一个是旋转参数,使用这个参数我们可以旋转图的标签。下面是一个将日期标签旋转 90 度以便于阅读的例子。

df.plot(x='Date', y='Close', rot=90)

线形图

标题

如果你想给你的情节一个标题,这是使用的方法。我们将传递一个字符串到我们的标题参数中。

df.plot(x='Date', y='Close', rot=90, title="AMZN Stock Price")

线形图

更多绘图类型

绘图方法的默认类型是折线图,但是根据我们的使用情况,还有许多其他绘图类型可供使用。其他一些绘图类型可以列举如下:

  • 线条
  • 酒吧
  • 馅饼
  • 分散
  • 柱状图

我们来做一个散点图的例子。我们将在我们的方法中添加一个名为 kind 的新参数。是的,就是这么简单。

df.plot(x='Date', y='Close', kind='scatter', rot=90, title="AMZN Stock Price")

散点图

现在我们来做一个直方图的例子。直方图是查看数值分布的好方法。

df.plot(x='Date', y='Volume', kind='hist', rot=90, title="AMZN Stock Price")

直方图

感谢你阅读这篇文章,我希望你喜欢并且今天学到了一些新的东西。如果您在执行代码时有任何问题,请随时通过我的博客联系我。我非常乐意帮忙。你可以找到更多我发表的与 Python 和机器学习相关的帖子。保持安全和快乐的编码!

我是贝希克·居文,我喜欢分享关于创造力、编程、动力和生活的故事。

跟随 我的博客 走向数据科学 留下灵感。

[## 面向数据科学的 Python 简介

面向初学者的简单交互式教程

towardsdatascience.com](/introduction-to-python-for-data-science-6d1dba7c305c) [## 用 Python 构建语音识别器

使用谷歌云语音 API 将您的音频文件转换为文本

towardsdatascience.com](/building-a-speech-recognizer-in-python-2dad733949b4)

Python 为 FPL(!)数据分析

原文:https://towardsdatascience.com/python-for-fpl-data-analytics-dadb414ccefd?source=collection_archive---------23-----------------------

使用 Python 和 Matplotlib 进行虚拟足球数据分析和可视化

作者图表

介绍

这个作品有两个原因:(1)我想用 Python 自学一些数据分析和可视化技术;(2)我需要阻止我的梦幻足球队下滑几个排行榜。但首先,感谢大卫·艾伦提供了关于访问梦幻英超 API 的有用指南,可以在这里找到

首先,我们需要设置我们的笔记本以使用 Pandas 和 Matplotlib(为此我使用 Jupyter),并连接到 Fantasy Premier League API 以访问分析所需的数据。

#Notebook Config
import requests
import pandas as pd
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('ggplot')#API Set-Up
url = '[https://fantasy.premierleague.com/api/bootstrap-static/'](https://fantasy.premierleague.com/api/bootstrap-static/')
r = requests.get(url)
json = r.json()

然后,我们可以建立我们的熊猫数据框架(想想数据表),它将被查询以获得有价值的见解——希望如此。我们创建的每个数据帧(_df)都与一个可通过 FPL API 访问的 JSON 数据结构相关。要获得完整的列表,运行 json.keys() 。我们对“元素”(球员数据)、“元素类型”(位置参考)和“球队”感兴趣。

elements_df = pd.DataFrame(json['elements'])
element_types_df = pd.DataFrame(json['element_types'])
teams_df = pd.DataFrame(json['teams'])

默认情况下, elements_df 包含许多我们现在不感兴趣的列(关于每个数据帧的概述,请参阅 David 的文章)。我创建了一个新的 DataFrame — main_df — ,其中包含我可能想要使用的列。

main_df = elements_df[['web_name','first_name','team','element_type','now_cost','selected_by_percent','transfers_in','transfers_out','form','event_points','total_points','bonus','points_per_game','value_season','minutes','goals_scored','assists','ict_index','clean_sheets','saves']]

需要注意的是 elements_df 使用键来引用球员的位置和球队等信息。例如,在' element_type ' 列中,值为“1”=守门员,在 ' 列中,值为“1”=阿森纳。这些是对我们创建的另外两个数据帧的引用( element_types_df,teams_df)

如果我们预览 element_types_df ,我们会看到这里的每个“id”号对应一个位置:

element_types_df.head()

作者的表格输出

teams_df 中,“id”对应每个团队名称:

teams_df.head()

作者的表格输出

在这一点上,我们还可以看到没有一个团队的统计数据被更新,这可能是一个稍后的问题——我特别希望每个团队玩的游戏。为了节省时间和/或缺乏更好的解决方案,我通过以下方式手动添加数据:(1)创建一个新字典,(2)将其转换为两列数据帧,(3)用我创建的数据覆盖 teams_df 中的“已播放”列。

#create new dictionary
games_played = [['Arsenal','4'], ['Aston Villa','3'], ['Brighton','4'], ['Burnley','3'], ['Chelsea','4'], ['Crystal Palace','4'], ['Everton','4'], ['Fulham','4'], ['Leicester','4'], ['Leeds','4'], ['Liverpool','4'], ['Man City','3'], ['Man Utd','3'], ['Newcastle','4'], ['Sheffield Utd','4'], ['Southampton','4'], ['Spurs','4'], ['West Brom','4'], ['West Ham','4'], ['Wolves','4']]#turn into a DataFrame
played_df = pd.DataFrame(games_played,columns=['team','games_played'])#overwrite existing DataFrame column
teams_df['played'] = played_df['games_played'].astype(str).astype(int)#voila
teams_df.head()

作者的表格输出

出于我们分析的目的,我们将使用实际的位置和团队名称,而不是数字标识符。为了避免以后引用不同地方的数据,我们现在可以将我们的数据帧合并在一起,形成一种“主”表。我们将使用 main_df 作为基础,使用 pd.merge 来执行到其他数据帧、 elements_types_dfteams_df 的连接。

这里有三个要素:

  1. 使用 pd.merge ,其中 " left_on =" 获取我们要加入的 main_df 中的唯一标识符。 " right_on =" 是我们要连接的目标数据帧中的等效列(在这两种情况下, ' id ' )。例如 main _ df[' element _ type ']= element _ types _ df[' id '],但我们实际上想在 display 中使用 element _ types _ df[' singular _ name ']。我们使用 "=" 来列出我们正在跨越的每一列。
#merging elements_types_df onto main_df
main_df = pd.merge(left=main_df,right=**elements_types_df**[['id','singular_name']],left_on='element_type', right_on='id', how='left')

2.使用 df.drop ,删除合并后不需要的列。虽然我们需要使用“id”列来连接,但我们不希望它们出现在最终的数据帧中。我们也不再需要原来的'element _ type'' team ' 列,因为我们现在已经将用户友好的数据合并到了 main_df 中。使用“轴=1”指定我们正在删除一列而不是一行。

main_df = main_df.drop(["id", "element_type"],axis=1)

3.使用 df.rename ,清理我们的数据帧。在 element_types_df 中,位置名称存储在‘singular _ name’下。我们将把它重命名为“位置”,使它更直观。

main_df = main_df.rename(columns = {'singular_name': 'position'})

要合并 teams_df 数据,我们可以调整上面的内容:

#merging teams_df onto main_df
main_df = pd.merge(left=main_df,right=**teams_df**[['id','name','played','strength_overall_away','strength_overall_home']],left_on='team', right_on='id', how='left')
main_df = main_df.drop(["id", "team"],axis=1)
main_df = main_df.rename(columns = {'name': 'team'})

最后,我们先发制人地将一些现有列转换为浮点数,以避免运行计算和排序值的潜在问题,我们创建了一个新列“total_contribution”(进球和助攻的总和):

#Additional columns stored as floats
main_df['value'] = main_df.value_season.astype(float)
main_df['ict_score'] = main_df.ict_index.astype(float)
main_df['selection_percentage'] = main_df.selected_by_percent.astype(float)
main_df['current_form'] = main_df.form.astype(float)#Total Goals Contribution column = Goals + Assists
main_df['total_contribution']= main_df['goals_scored'] + main_df['assists']

main_df 的设置,我们可以使用。loc() 过滤掉所有值为< 0 的玩家,以避免我们的结果被那些没有获得游戏时间的玩家歪曲:

main_df = main_df.loc[sel_df.value > 0]#preview of current state
main_df.head(3)

作者的表格输出

位置

现在,使用 groupby() 函数,我们可以按位置快速查看数据。第一个参数“position”选择要分组的列,而“as_index=False”防止该列被删除并用作索引。使用聚合函数,我们可以找到每个位置的平均值和总分。我已经用一个 roundby() 到把小数限制到两位。

position_group = np.round(main_df.groupby('position', as_index=False).aggregate({'value':np.mean, 'total_points':np.sum}), 2)position_group.sort_values('value', ascending=False)

作者的表格输出

从花费来看,守门员目前返还了最多的分数,但是他们也只占球队总分数的很小一部分。由于游戏中很多门将都是 0 分钟出场,这里就不算了(因为他们的值= 0)。许多外场球员如果在比赛还剩 5 到 10 分钟的时候替补上场,将会得到 1 分的回报,拉低了平均得分。

球队层面的统计数据可以给出一个大致的指示,表明哪支球队打得好,或者哪里的球员可能被低估/高估。

team_group = np.round(main_df.groupby('team', as_index=False).aggregate({'value':np.mean, 'total_points':np.sum}), 2)
team_grp_df = team_group.sort_values('value', ascending=False)
team_grp_df['games_played'] = teams_df['played']
team_grp_df.head(5)

作者的表格输出

我个人并不认为西汉姆和布莱顿的资产在这个阶段(或任何阶段)价值会排名前五。然而,我们知道有些球队——包括曼联和曼城——比其他球队少打了一场比赛。让我们通过创建一些每场价值和每场得分指标来调整这一点:

team_group = np.round(main_df.groupby('team', as_index=False).aggregate({'value':np.mean, 'total_points':np.sum}), 2)
team_grp_df = team_group
team_grp_df['games_played'] = teams_df['played']
team_grp_df['value_adjusted'] = np.round(team_grp_df['value']/teams_df['played'],2)
team_grp_df['points_adjusted'] = np.round(team_grp_df['total_points']/teams_df['played'],2)
team_grp_df.sort_values('points_adjusted',ascending=False).head(5)

作者的表格输出

即使调整了比赛,曼联和曼城也没有进入前 5 名。鉴于他们最近对热刺和莱斯特的表现,这并不奇怪。阿森纳和利物浦都在每场比赛中获得大量的分数,但他们的价值分数表明你必须为此付出代价。

让我们使用 Matplotlib 来创建这些数据的一些更好的图形表示。使用 subplot 函数,我们可以并排绘制两个图形,以便于比较。我们会将团队“价值”和“总积分”与我们根据所玩游戏创建的调整数字进行比较。

fig,axes = plt.subplots(nrows=1, ncols=2, figsize=(20,7))
plt.subplots_adjust(hspace=0.25,  wspace=0.25)
team_grp_df.sort_values('value').plot.barh(ax=axes[0],x="team", y="value", subplots=True, color='#0087F1')
team_grp_df.sort_values('value_adjusted').plot.barh(ax=axes[1],x="team", y="value_adjusted", subplots=True, color='#2BBD00')
plt.ylabel("")fig,axes = plt.subplots(nrows=1, ncols=2, figsize=(20,7))
plt.subplots_adjust(hspace=0.25,  wspace=0.25)
team_grp_df.sort_values('total_points').plot.barh(ax=axes[0],x="team", y="total_points", subplots=True, color='#EB2000')
team_grp_df.sort_values('points_adjusted').plot.barh(ax=axes[1],x="team", y="points_adjusted", subplots=True, color='#FF8000')
plt.ylabel("")

作者的图表:价值和总点数根据所玩游戏进行调整

阿斯顿维拉在调整了他们只打了三场比赛的事实后更加突出。看看他们的结果,不难看出为什么:1 比 0(对谢夫联特),3 比 0(对富勒姆),7 比 2(对利物浦!).显然,我们正在寻找小规模的样本,但在我们决定装载维拉的资产之前,也许要考虑到他们的两场胜利和零失球都来自于这两支本赛季场均得分最差的球队。我们能对去年冠军利物浦的比赛结果赋予多大的意义呢?

球队层面的数据只能告诉我们这么多——毕竟我们每队最多有三名球员——所以让我们缩小关注范围。我们将使用。再次锁定 以过滤每个位置并创建更多数据帧:

gk_df = main_df.loc[main_df.position == 'Goalkeeper']
gk_df = gk_df[['web_name','team','selection_percentage','now_cost','clean_sheets','saves','bonus','total_points','value']]def_df = main_df.loc[main_df.position == 'Defender']
def_df = def_df[['web_name','team','selection_percentage','now_cost','clean_sheets','assists','goals_scored','total_contribution','ict_score','bonus','total_points','value']]mid_df = main_df.loc[main_df.position == 'Midfielder']
mid_df = mid_df[['web_name','team','selection_percentage','now_cost','assists','goals_scored','total_contribution','ict_score','current_form','bonus','total_points','value']]fwd_df = main_df.loc[main_df.position == 'Forward']
fwd_df = fwd_df[['web_name','team','selection_percentage','now_cost','assists','goals_scored','total_contribution','ict_score','current_form','minutes','bonus','total_points','value']]

守门员

从守门员开始,我们将绘制一个简单的散点图,显示成本 v 点(“价值”指标)。Matplotlib 允许我们很容易地定制一些东西,比如绘图透明度(alpha=)、大小(figsize=)和线型(ls=)。出于本文的目的,我将保持一切一致。

ax = gk_df.plot.scatter(x='now_cost',y='total_points', alpha=.5, figsize=(20,9), title="goalkeepers: total_points v cost")
for i, txt in enumerate(gk_df.web_name):
    ax.annotate(txt, (gk_df.now_cost.iat[i],gk_df.total_points.iat[i]))
plt.grid(which='both', axis='both', ls='-')
plt.show()

作者图表

在赛季初期,门将价格和总积分之间没有任何关系。麦卡锡是大量球员的季前赛价值选择,到目前为止,这一点得到了回报。马丁内斯在季前赛中被低估了,因为他是阿森纳的第二选择——他最近转会维拉给了那些把他带进来的人回报。纽卡斯尔的达洛目前在 500 万选秀权中得分最高,这令人惊讶,因为他们在四场比赛中只保持了一场零失球。还有什么解释?知道守门员每三次扑救也能得一分,我们可以用“扑救”数据重新绘图。

作者图表

看来达洛的扑救次数是大多数守门员的两倍多,这有助于解释他的总得分。这也表明他的辩护人没有给他提供多少保护。在任何情况下,不失球通常会带来更多的分数,所以我宁愿选择一个更有潜力的门将。马丁内斯和麦卡锡以更低的成本提供了更多的平衡。切尔西新签下的门迪在他的处子秀不失球中不需要任何扑救,500 万的身高有着长期的价值,如果你相信他们的防线会继续改善的话。

*他的举动没有回报那些把他带进来,让他坐冷板凳的人。我敢肯定,如果他们换成皮克福德,这些人会更加自责——皮克福德是一个竭尽全力帮助对方球队将球送入自己球门的守门员。

结论:皮克福德出局,麦卡锡/梅斯利尔进。

防守

至于后卫,我们想要不失球或者进攻威胁——理想的是两者都要。亚历山大-阿诺德和罗伯逊去年在防守方面的期望达到了顶峰,但给利兹联进了 3 个球,给阿斯顿维拉进了 7 个球,这表明了问题的存在。那么哪些后卫赛季开局不错呢?

def_df.sort_values('total_points',ascending=False).head(5)

作者的表格输出

很多人都注意到了卡斯塔涅本赛季的梦幻开局(现在有 19.2%的球队)。另一方面,西汉姆的克雷斯韦尔仍然在很大程度上被忽视了——尽管他的总得分仅为 490 万。他的 ICT 指数得分也高达 27.7,对于任何不熟悉的人来说,这代表着影响力、创造力和威胁。这本质上是衡量球员在球场两端重要时刻的投入程度。这有助于评估一名球员是否为他人创造了好机会,或者进入了他们可能得分的位置。

为了快速查看与价格相关的最高表现后卫,我将制作一个新的数据框架 topdef_df ,仅选择值>为 3 且至少有 1 个进球贡献(进球或助攻)的后卫。

topdef_df = def_df = def_df.loc[def_df.value > 3]
topdef_df = topdef_df = topdef_df.loc[def_df.total_contribution > 0]

作者图表

ICT 分数高但总分数低的球员可能运气不好,如果机会转换得更早而不是更晚,那些从分数角度看“表现不佳”的球员现在可能仍然是一支球队有价值的补充。我们能知道是否有“不幸的”防守者存在吗?我们可以尝试为 ICT 得分> 10 的捍卫者创建一个数据框架,看看谁得到了奖励,谁没有。

unluckydef_df = def_df.loc[def_df.ict_score > 10]
unluckydef_df.sort_values('ict_score', ascending=False).head(5)

作者的表格输出

作者图表

亚历山大-阿诺德(7.5 米)和罗伯逊(7.0 米)没有出现在之前的图中,因为我们过滤了值> 3。鉴于他们本赛季的缓慢开局,拥有其中任何一个的球员都会高兴地看到他们仍然是游戏中最具威胁的球员之一,应该坚持下去——尽管他们付出了代价。切尔西的詹姆斯凭借他的进攻价值进入了很多人的球队,尽管他最近在排名上落后于阿兹皮里库塔。迪格内并不便宜(6.1 米),但他在一支强大的埃弗顿队中为理查德森和卡尔弗特-勒温服务——期待他的助攻数继续增加。在“不幸”的一面,弗雷德里克斯(440 万)、艾林(450 万)和达拉斯(450 万)到目前为止都相当严重地卷入了他们的比赛,没有分数显示出来。在这样的价格下,这三个人都是很好的替补人选。

结论:迪格内和奇尔威尔看起来都比我现在的多赫蒂(590 万)更好。我还听从了一个朋友的坏建议,把斯特鲁克(4.0 米)作为替补——弗雷德里克斯/艾林/达拉斯中的任何一个都是可以承受的升级。

中场

中场球员:很可能是球队得分最多的地方。为了立即关注高水平球员,我们可以像对待后卫一样,创建另一个新的数据框架——这一次,只选择 ICT 得分> 25 且总得分> 15 的中场球员。

topmid_df = mid_df.loc[mid_df.ict_score > 25]
topmid_df = topmid_df.loc[mid_df.total_points > 15]
topmid_df.sort_values('total_points',ascending=False).head(5)

作者的表格输出

作者图表

萨拉赫(1220 万英镑)和孙正义(900 万英镑)是迄今为止仅有的证明其价格合理的大牌资产。德布鲁因和斯特林有一场比赛在手,但他们的前三场比赛没有太多表现。格里利什(710 万英镑)和罗德里格斯(780 万英镑)是目前的中层价值选择,鉴于阿斯顿维拉和埃弗顿的攻击性比赛有多少是通过他们进行的,你会期望这种情况继续下去。鲍文(6.3 米)和若日尼奥(5.2 米)看起来很有价值,尽管后者在四场比赛中进了三个点球,增加了他早期的得分回报。

但是 FPL 球员喜欢(或者忽略)哪些中场球员呢?我保持了> 15 个总点数参数不变,但是按照总体选择百分比而不是成本来绘制结果。

作者图表

作者的表格输出

鲍文再次脱颖而出——在赛季开局相当强劲之后,只有不到 2%的球员选择了他。在 FPL 语中,他实际上是一个“与众不同”的选择。拥有足够低的所有权百分比的人,如果他回报良好,他会帮助你获得排行榜位置(因为很少其他人也会获得这些分数)。很多人希望优质资产奥巴姆扬和德·布鲁因能尽快开拍。

作者图表

根据 ICT 的判断,德布鲁因的持有者可以放松一点,因为他的开局很好——伤病意味着曼城缺少一名彻头彻尾的前锋,他本可以奖励他的机会创造。如果你选择了斯特林,你可能会稍微担心他会像汤森或麦吉恩一样有威胁性(费用加倍)。在另一端,儿子和萨拉赫看起来像必须的。

结论:萨拉赫和德布鲁因可能会在本赛季余下的比赛中保持领先。我会尽快让儿子回来,在他因为一个不存在的伤被转移出去之后。引进巴恩斯和佩雷拉还没有奏效——如果他们的贡献不能迅速提高,我将根据我的预算为格里利什/罗德里格斯转会。

向前

在球场的顶端,有一些更多的惊喜,看看早期的价值来自哪里。我已经排除了每个人还没有贡献一个目标来整理剧情:

topfwd_df = fwd_df[fwd_df.total_contribution > 0]

作者的表格输出

作者图表

价格和积分之间仍然没有太大的关联。像英格斯和吉米内兹这样的中等价值球员做得还可以,不算伟大。大部分的分数似乎来自 6.0-6.5 米的关口,或者 10.0 米以上。卡尔弗特-勒温本赛季的开局令人印象深刻,他的身价从 700 万英镑稳步上升到 760 万英镑。与瓦迪、威尔逊和穆佩不同,卡尔弗特-勒温的进球也没有一个来自点球。48%的玩家现在让他加入——另外 52%的玩家不会承认他们错了,即使这会让他们付出代价(我以前见过这种情况……)。

在其他地方,即使是 1060 万,凯恩仍然提供了很多价值——直接促成了本赛季迄今为止的最多进球(9)。马夏尔和沃纳可能是最大的失望,沃纳不知何故被亚伯拉罕得分超过,这是他签约取代的前锋。

以稍微不同的东西来结束,我们可以看看 FPL 球员对球员状态的反应。每个人都提到“此刻不能错过”的状态良好的前锋。理论上,人们会希望在状态正佳的球员状态正佳的时候抓住他们。在 FPL,形式=三十天内每场比赛的平均总分数。

#Add the 'transfers_in' column from our original main_dffwd_df['transfers_in'] = main_df['transfers_in']
informfwd_df = fwd_df[fwd_df.current_form > 5]

作者图表

在一个小样本量的状态良好的球员中存在一定程度的相关性(其中状态> 5)。凯恩的低转会数量可能只是反映了他已经在许多球队开始了这个赛季的事实。基于前几场比赛,很多人选择了巴福特、瓦迪和威尔森,但仍然没有多少人喜欢西布朗的卡勒姆·罗宾逊——尽管他在对切尔西的比赛中进了两个球。人们在卡尔弗特-勒温上发言,在过去几周增加了近 300 万个团队。

结论:我一直很固执,紧紧抓住理查德·里森不放,但很明显,明智的选择是他的搭档。吉米内兹有一个不错的赛程,所以他可以暂时留下来。布鲁斯特(4.5 米)很可能会坐上我的板凳,如果他在谢菲尔德联队开局不错的话。否则,我会考虑重新平衡我的团队,引进沃特金斯或巴福特。

全部的

最后,这里是按位置排列的前 5 名价值(价值=点数/成本)玩家的视图。尽管值得记住的是,由最高“价值”球员组成的球队不会在许多排行榜上名列前茅,但这都是为了在总体预算限制下最大化积分。找到好的价值可以让你在那些能打出最大比分的球员(萨拉赫,凯恩)身上花更多的钱。

作者图表

为了绘制这个图,我使用 nlargest() 按位置制作了一个前 5 名的数据框架

top5_gk_df = gk_df.nlargest(5, 'value')
top5_def_df = def_df.nlargest(5, 'value')
top5_mid_df = mid_df.nlargest(5, 'value')
top5_fwd_df = fwd_df.nlargest(5, 'value')

通过将第一个图定义为“ax ”,然后在第二个、第三个和第四个图中引用“ax=ax ”,在同一图形上对每个数据帧进行分层之前:

ax = top5_gk_df.plot.scatter(x='value', y='total_points', color='DarkBlue', label='GK', s=top5_gk_df['value']*10, alpha=.5, figsize=(15,9), title="Top 5 Value Players by Position")
for i, txt in enumerate(top5_gk_df.web_name):
    ax.annotate(txt, (top5_gk_df.value.iat[i],top5_gk_df.total_points.iat[i]))top5_def_df.plot.scatter(x='value', y='total_points', color='DarkGreen', label='DEF', s=top5_gk_df['value']*10, ax=ax)
for i, txt in enumerate(top5_def_df.web_name):
    ax.annotate(txt, (top5_def_df.value.iat[i],top5_def_df.total_points.iat[i]))top5_mid_df.plot.scatter(x='value', y='total_points', color='DarkOrange', label='MID', s=top5_gk_df['value']*10, ax=ax)
for i, txt in enumerate(top5_mid_df.web_name):
    ax.annotate(txt, (top5_mid_df.value.iat[i],top5_mid_df.total_points.iat[i]))top5_fwd_df.plot.scatter(x='value', y='total_points', color='DarkRed', label='FWD', s=top5_gk_df['value']*10, ax=ax)
for i, txt in enumerate(top5_fwd_df.web_name):
    ax.annotate(txt, (top5_fwd_df.value.iat[i],top5_fwd_df.total_points.iat[i]))

“s=top5_gk_df['value']*10”参数使每个散点图气泡的大小成为“value”列的函数。也就是说,‘价值’越大,泡沫越大。然而,鉴于规模较小,上述结果几乎可以忽略不计。

结论

以上主要是使用 Python 掌握数据帧创建、操作和图形表示的练习,但是在可视化和定制方面还有很多工作要做。从数据的角度来看,不可否认,一个赛季有三到四场比赛还为时过早,但分析数据的工具/方法将在很大程度上保持一致。随着赛季的进行,不断重新运行代码来观察事情的发展会很有趣。只需不到 1 秒钟的时间,就可以重新运行生成这里所有内容的所有代码——在 FPL 应用程序上,这无疑节省了大量时间。

Python 投资:一月晴雨表策略

原文:https://towardsdatascience.com/python-for-investing-january-barometer-strategy-25812ba9a904?source=collection_archive---------48-----------------------

深入分析。

一月气压计真的有用吗?

投资时,市场时机至关重要。一种市场理论是一月份的晴雨表,它表明一月份的表现决定了今年剩余时间的市场表现。换句话说,如果 1 月份的回报是正的,那么今年剩下的时间很可能也会是正的。我想在指数水平和部门水平上检验这个理论。这个假设在标准普尔 500、纳斯达克综合指数或罗素 2000 指数上行得通吗?这个理论在某些领域比其他领域更成功吗?此外,2020 年,我们能期待什么?该指标能应对冠状病毒爆发的影响吗?

让我们潜心研究数据,找出答案!

数据源

Python 使得获取我分析所需的数据变得非常容易。我用来获取财务数据的两个包是 Quandl 和 pandas_datareader。

Quandl 是一个包含许多数据集的金融图书馆,如果你注册的话,你可以免费访问其中的一些。通过在 Python 中安装这个包,可以直接将数据调用到 dataframe 中。以下是我如何检索 S&P 综合数据。

import pandas as pd
import numpy as np
import datetime 
#For graphing
import matplotlib.pyplot as plt
%matplotlib inline# quandl for financial data
import quandl# Retrieve SP500 data from Quandl
sp = quandl.get(“YALE/SPCOMP”, authtoken=unqiue_token, collapse=”daily”)

我还使用 pandas_datareader 来获取 Yahoo Finance 数据,因为 Quandl 没有太多我要寻找的历史数据。Pandas_datareader 是一个简洁的库,允许你从网站中提取数据。下面是一个例子,我如何检索历史 NASQAD 综合价格。

import pandas_datareader as dr
df = dr.data.get_data_yahoo('^IXIC', start='1971-12-31', end = '2019-12-31')

一月份标准普尔 500 晴雨表的表现

使用耶鲁大学经济系从 1872 年至今的 S&P 综合数据,我计算了每年 1 月和 2 月到 12 月的回报率。在这 148 年中,1 月回报率为正的有 98 次。在这 98 次中,从 2 月到 12 月的回报也是正的 65 次。总体而言,一月回报成功预测全年回报的次数有 91 次,成功率为 61.49%。

下面的图 1 显示了假设成功的 91 次。根据 1 月份的数据,1933 年和 1879 年的 2-12 月回报率最高,分别为 40.6%和 37.4%。晴雨表也有助于避免市场损失。例如,在 2008 年、1907 年和 1917 年,该指标为负,暗示不要投资。在那几年,市场实际上跌幅最大,2 月至 12 月的回报率分别为-36.4%、-31.3%和-28.9%。

图 1:一月晴雨表正确预测全年表现的实例

这是我如何制作图 1 的:

sp3 = sp2[sp2['jan_sign'] == sp2['FebDec_sign']][['spreturn','FebDecreturn']]
width = 0.75  # the width of the barsfig, ax = plt.subplots(figsize=(40,20))
rects1 = ax.bar(sp3.index - width/2, sp3['spreturn'], width, label='Jan Return')
rects2 = ax.bar(sp3.index + width/2, sp3['FebDecreturn'], width, label='Feb-Dec Return')ax.set_ylabel('Return', fontsize=40)
ax.set_xlabel('Year', fontsize=40)
ax.set_title("Jan Barometer on SP500",fontsize=40)
ax.legend(fontsize=40)
ax.tick_params(axis='both', which='major', labelsize=40)

下面的图 2 显示了一月份气压计失灵的 57 次。当跟随指标时,投资者可能会错过大的市场收益。例如,明智的做法是不要在 1927 年和 2009 年遵循这一理论,当时晴雨表预测今年为负,但当年剩余时间的回报率实际上为正,分别为 30.3%和 28.3%。另一方面,晴雨表也可能有风险,它预测一个积极的一年,但最终却是消极的一年。例如,在 1931 年,1 月份的回报率为正 3.1%,但当年剩余时间的收益率大幅下跌-47.1%。

图 2:一月份的晴雨表错误预测全年表现的实例

气压计在其他指标上的表现

我使用雅虎财经的纳斯达克综合指数、道琼斯指数和罗素 2000 指数的每日收盘价数据,应用晴雨表来观察它的表现。在图 3 中,如果忽略晴雨表,总回报代表在数据中所有年份都保持投资的年化回报。如果投资者仅在 1 月份回报率为正的年份投资(假设 1 月份没有投资),则晴雨表回报率是年化回报率。有趣的是,通过遵循一月晴雨表理论,投资者将获得比忽视该指标更大的回报。每个指数的成功率都比抛硬币要好,其中纳斯达克综合指数的成功率最高(67%)。无论 30 种证券或 500 种证券或大型技术公司或小型公司的指数,1 月份的晴雨表表现良好。

图 3

图 4

气压计在行业层面的表现

利用雅虎财经 21 年的 S&P500 板块数据,我发现了每个板块的晴雨表强度。该理论在医疗保健和公用事业领域的效果最好,成功率分别为 67%和 62%。金融部门表现最差,只有 38%的成功率。

图 4

下面的代码是我如何制作组合条形图和折线图的,它清楚地显示了正确预测的年份和成功率之间的趋势和关系:

fig, ax1 = plt.subplots(figsize=(15, 5))
plt.style.use('seaborn-white')
ax2 = ax1.twinx()
chart = df_sector.set_index('Sector')['Correctly Predicted Years'].plot(kind='bar',color = 'y', ax=ax1)
df_sector.set_index('Sector')['sucess_rate'].plot(kind='line', marker='d', ax=ax2)ax1.set_ylabel("Correctly Predicted # of Years",fontsize=14)
ax2.set_ylabel("Success rate",fontsize=14)
ax1.set_ylim([0,16])
chart.set_xticklabels(chart.get_xticklabels(), rotation=45,fontsize=16)
ax2.legend(loc=9, bbox_to_anchor=(1, -0.2),fontsize=14)
ax1.legend(loc=9, bbox_to_anchor=(1, -0.3),fontsize=14)
plt.title("Jan Barometer Success Rate by Sectors", y=1.02, fontsize=20)
plt.tick_params(axis='both', which='major', labelsize=12)
ax1.tick_params(axis='both', which='major', labelsize=12)

图 5

如果忽略该指标,并投资所有 21 年,非必需消费品行业的年化回报率最高(6.6%)。非必需消费品板块是唯一一个在忽略晴雨表(6.6%)时表现好于遵循理论(6.1%)的板块。当投资于晴雨表预测为正年的年份时,所有其他行业都有较高的回报。公用事业部门的平均回报率最高,为 10.1%,而金融行业的平均回报率最低,为-1.8%。

图 6

图 7

从统计学的角度来说,混淆矩阵是显示预测模型错误的一种直观方式。我计算了四个指标:真阳性、假阳性、假阴性和真阴性。真正的积极是当气压计正确预测一个积极的一年。假阳性是指气压计错误地预测了一个正年份,导致投资者亏损。假负是指一月份的回报为负,但一年中的其他时间回报为正,因此投资者错过了一项有利可图的投资。真正的负值是当晴雨表正确地预测到一个不利的年份,帮助投资者避免一个糟糕的投资。真正的积极和真正的消极衡量一月晴雨表理论的成功。假阳性和假阴性衡量指标的误差。材料行业的假阴性案例最多,投资者错过了好的投资机会。当投资者在投资组合中失去收益时,金融类股的误判率最高。

图 8

一月气压计和过去的流行病

随着当前 COVID 19 疫情的爆发,我很想看看 1 月份关于以往流行病和大流行的晴雨表的表现。以 LiveScience.com 为参照,我选取了最近的 8 次疫情,发现标准普尔 500 1 月和 2 月至 12 月为疫情爆发的第一年。一月晴雨表对 8 次爆发中的 5 次有效,成功率为 62.5%。2020 年,1 月份的回报率为负(-0.99%),因此,如果遵循该指标,今年剩余时间的回报率也可能为负。2009 年,当猪流感出现时,1 月份的回报是负的,但与其他疫情相比,当年其余时间的回报是最高的。然而,这在很大程度上是由于央行非常规的量化宽松货币政策。这与今天美联储使用同样的货币工具的情况相当。尽管晴雨表预测,随着美联储在 2020 年的干预,市场可能会经历一场繁荣。

图九

图 10

总的来说,一月晴雨表确实有效,跟踪它,回报比忽略它要高。然而,投资者应谨慎使用,因为许多其他因素,如美联储的货币政策和地缘政治因素也会影响市场。

Git Hub Repo:

https://github . com/joohirana/mediu article _ januarybarometer 2020 . git

参考:

[## 历史上 20 次最严重的流行病和大流行

纵观历史,疾病爆发蹂躏人类,有时会改变历史进程…

www.livescience.com](https://www.livescience.com/worst-epidemics-and-pandemics-in-history.html)

[1] O. Jarus,历史上 20 次最严重的流行病和大流行(2020 年),《生活科学》。

Python 函数-工具技巧!

原文:https://towardsdatascience.com/python-function-tools-tricks-127a0eea87ed?source=collection_archive---------34-----------------------

一个简单的方法来提升你的代码,使它更干净,更实用,有时甚至更快!

图片来自这里

在这篇文章中,我将展示 Python 标准库 Functools 模块的一些最佳用法。

Functools (Function-tools)能为我们做什么?

STL 库的 functools 有很好的特性,允许我们用很少的代码甚至不用代码就能修改自己的函数,并给它们添加功能。

所有这些都会产生更清晰、更有效的代码,易于理解、监控和审查。所以,事不宜迟,让我们开始吧!

减少

Reduce 采用一个包含两个参数和一个 iterable 的函数,并在整个 iterable 上累积执行操作!

例如,如果我们用一个函数来增加数字,使用 reduce,我们就可以累加我们想要的每一个列表!或者串连字符串!

这里有一个例子:

这在想要在一列项目上实现的自定义函数中会派上用场,如果它是唯一的乘法,或者特殊的对象操作!

部分功能

部分函数是第二个函数,在许多参数中有用户固定的值。这使我们能够使用和创建简单方便的功能,而无需重写原来的功能!

一如既往——代码胜于文字。

缓存属性

我把这个放在最后,主要有两个原因:首先,它是 python 3.8 中的新特性,并不是每个人都已经更新了。第二个原因是它有更多的高级用途,主要是在大数据应用中。

我们都知道类属性的用法;它们是在访问时计算的,通常与对象的其他参数一起计算。

有时您只需计算一次,因此从 Python 3.8 开始,您可以通过缓存这些值来节省大量计算时间,而不必每次访问属性时都重新计算它们,如下所示:

最后的想法

Python 标准库有很棒的工具供您使用。functools 模块有很好的方法让你的代码更干净,更简单,有时甚至更快!

如果您对此感兴趣,请发表评论,我将写更多关于 Python 标准库特性的文章,这些特性没有足够多的人知道。

希望你喜欢这个!

成为真正程序员的 Python 基础,第 1 部分

原文:https://towardsdatascience.com/python-fundemtales-to-become-a-true-programmer-part-1-d9962f7eca6d?source=collection_archive---------20-----------------------

您必须知道的事情-提高您的 Python 技能

图像来源

Python 路径

Python 有这种魅力。人们近乎浪漫地谈论它,说它是“简单的英语”。它是如此“简单易懂”,以及引入开源社区奇妙模块的力量——一切尽在掌握之中。

嗯,难道不是吗?

这是毫无疑问的,但我的朋友是第一级。

第一级是每个 python 开发者成为真正的 python 开发者的必经之路,我希望在这篇文章结束时,带你进入更高级的层次,并向你展示你必须走的路。

照片由大卫·马尔库Unsplash 上拍摄

"知道特征并不能让一个人成为专家,理解特征才能做到."

起初

这篇文章将随着时间的推移而进步,但是我想从更好地理解类开始。

类被认为是一个对象的蓝图,init 创建这个对象,或者说构造它(很多构建的类比参与进来)。

这个定义是公平的,但是它遗漏了 python 类的一个重要方面。

这个物体是什么?

照片由元素 5 数码Unsplash 上拍摄

您创建的这个对象可能会有属性和自我操作,但是 python 通过“dunder 方法”给了您更多

基础知识

让我们从简单的事情开始——假设我们需要一个类来表示一个多项式,它可能看起来像这样:

我们希望能够将它们相加或相减,甚至以简单适当的方式将它们打印到屏幕上,这里有三个最基本的“dunder 方法”,您可以添加适当的方法,并且可以使用这些操作!

如果这看起来是因为 zip 函数而完成的,不用担心,zip 只是将两个可重复项捆绑成一个可重复项的方法。

对我们来说最重要的是理解语法并不重要,你认识到数据模型函数(“dunder 方法”)允许你操作对象本身。

这是我在这里提出的至关重要的概念,它开始很简单,但会变得越来越有趣。

第三级——世界是一个对象

这句话是俗语,从 python 3 开始,一切都是对象,但这句流行语是什么意思呢?

乔恩·泰森在 Unsplash 上的照片

这里有一个典型的例子来说明它的意义。假设我们想测量一个函数运行的时间。

现在我解决了一个局部问题,如果我想把它加到 20 个函数上呢?这种方式是错误的,它没有考虑到 python 中的一切都是对象,包括函数 sub。
我可以调用子函数并修改它,调用的子函数会在函数上添加一个时间检查。

第 5 步——核心概念,第 7 步,是以语法的方式。

第 5 步和第 7 步没有区别。是一样的;这个 叫做装饰器装饰器让程序员 在自己的函数中添加 功能性而不触及核心函数本身。

更多关于“args”、“kwargs”的数据,请点击此处:

[## 用一个额外的字符改变你写 Python 代码的方式

一个小小的语法变化,是你编码技能的一大步

medium.com](https://medium.com/swlh/change-the-way-you-write-python-code-with-one-extra-character-6665b73803c1)

不要急于求成!

霍尔格连杆Unsplash 上拍照

同时这也暗示了第 2 篇文章(目前是最后一篇)的开始概念。
下一篇文章将更深入地挖掘这种语言的核心和特性,并希望让您更好地理解 python 是什么,而不仅仅是一些花哨的导入和看起来像这样的东西:
我希望您喜欢这篇文章,我知道我喜欢,我想把所有东西都挤在一篇文章中,但它感觉太紧凑了,我希望在下一篇文章中看到您,我也希望这篇文章给您带来一些新的东西!

在这篇文章的第二部分之前,请阅读以下内容:

[## 您应该始终使用的 Python 集合

Python collections 是一个被低估的库,它可以将您的编码提升到下一个级别。

medium.com](https://medium.com/swlh/python-collections-you-should-always-be-using-b579b9e59e4)

感谢阅读!

Python 生成器

原文:https://towardsdatascience.com/python-generators-393455aa48a3?source=collection_archive---------27-----------------------

使用 yield 关键字开发 python 生成器函数的教程

图片来自皮克斯拜

简单地说,Python 生成器促进了维护持久状态的功能。这使得增量计算和迭代成为可能。此外,生成器可以用来代替数组以节省内存。这是因为生成器不存储值,而是存储带有函数状态的计算逻辑,类似于一个准备启动的未赋值函数实例。

生成器表达式

生成器表达式可以用来代替数组创建操作。与数组不同,生成器将在运行时生成数字。

>>> import sys
>>> a = [x for x in range(1000000)]
>>> b = (x for x in range(1000000))
>>> sys.getsizeof(a)
8697472
>>> sys.getsizeof(b)
128
>>> a
[0, 1, ... 999999]
>>> b
<generator object <genexpr> at 0x1020de6d0>

我们可以看到,在上面的场景中,通过用生成器代替数组,我们节省了大量内存。

用收益代替回报的函数

让我们考虑一个简单的例子,你想产生任意数量的素数。下面是检查一个数是否是质数的函数,以及将产生无穷多个质数的生成器。

def isPrime(n):
    if n < 2 or n % 1 > 0:
        return False
    elif n == 2 or n == 3:
        return True
    for x in range(2, int(n**0.5) + 1):
        if n % x == 0:
            return False
    return Truedef getPrimes():
    value = 0
    while True:
        if isPrime(value):
            yield value
        value += 1

正如你在第二个函数中看到的,我们在一个 while 循环中迭代并产生质数。让我们看看如何使用上面的生成器。

primes = getPrimes()>>> next(primes)
2
>>> next(primes)
3
>>> next(primes)
5

首先,我们调用函数并获取生成器实例。虽然这可以模拟一个无限数组,但是还没有找到任何元素。如果你调用list(primes),你的程序可能会因为内存错误而崩溃。然而,对于质数,它不会到达那里,因为质数空间对于在有限时间内达到内存限制的计算是稀疏的。但是,对于发电机,你不会事先知道长度。如果您调用len(primes),您将得到下面的错误,原因与数字只在运行时生成的原因完全相同。

----------------------------------------------------------------
TypeError                      Traceback (most recent call last)
<ipython-input-33-a6773446b45c> in <module>
----> 1 len(primes)

TypeError: object of type 'generator' has no len()

迭代次数有限的生成器

虽然我们的质数例子有一个无限的迭代空间,但在大多数日常场景中,我们面对的是有限的计算。因此,让我们来看一个例子,我们可以用它来读取一个包含文本数据和下一行句子的语义分数的文件。

为什么我们需要使用收益率?

假设文件是 1TB,词的语料库是 500000。它不适合存储。一个简单的解决方案是一次读取两行,计算每行的单词字典,并在下一行返回语义得分。该文件如下所示。

The product is well packed
5
Edges of the packaging was damaged and print was faded.
3
Avoid this product. Never going to buy anything from ShopX.
1
Shipping took a very long time
2

很明显,我们不需要马上打开文件。此外,这些线条必须矢量化,并可能保存到另一个可以直接解析的文件中,以训练机器学习模型。因此,给我们一个干净代码的选项是使用一个生成器,它可以一次读取两行,并以元组的形式给我们数据和语义得分。

实现文件解析生成器

假设我们在一个名为test.txt的文件中有上述文本文档。我们将使用下面的生成器函数来读取文件。

def readData(path):
    with open(path) as f:
        sentiment = ""
        line = ""
        for n, d in enumerate(f):
            if n % 2 == 0:
                line = d.strip()
            else:
                sentiment = int(d.strip())
                yield line, sentiment

我们可以在一个for循环中使用上述函数,如下所示。

>>> data = readData("test.txt")
>>> for l, s in data: print(l, s)
The product is well packed 5
Edges of the packaging was damaged and print was faded. 3
Avoid this product. Never going to buy anything from ShopX. 1
Shipping took a very long time 2

发电机如何退出?

在一个普通的 for 循环中,当生成器不再生成时,迭代停止。然而,这可以通过我们在生成器实例上手动调用next()来观察到。超出迭代限制调用next()将引发以下异常。

----------------------------------------------------------------
StopIteration                  Traceback (most recent call last)
<ipython-input-41-cddec6aa1599> in <module>
---> 28 print(next(data))StopIteration:

使用发送、抛出和关闭

发送功能

让我们回忆一下质数的例子。假设我们想将我们的生成函数的值重置为 100,如果它们是质数,就开始产生大于 100 的值。我们可以在生成器实例上使用send()方法将一个值推入生成器,如下所示。

>>> primes = getPrimes()
>>> next(primes)
2
>>> primes.send(10)
11
>>> primes.send(100)
101

注意,在调用send()之前,我们必须至少调用next()一次。让我们看看我们必须如何修改我们的函数来适应这个目的。因为该函数应该知道如何分配接收到的值。

def getPrimes():
    value = 0
    while True:
        if isPrime(value):
            i = yield value
            if i is not None:
                value = i
        value += 1

我们将产生的值存储在变量i中。如果那不是None类型,我们把它赋给value变量。None检查至关重要,因为第一个next()value变量中没有要产出的值。

投掷功能

假设您想要在大于 10 的值处结束迭代,以避免溢出或超时(假设)。throw()功能可用于提示发电机暂停引发异常。

primes = getPrimes()for x in primes:
    if x > 10:
        primes.throw(ValueError, "Too large")
    print(x)

这种技术对于验证输入很有用。逻辑取决于发生器的用户。这将产生以下输出。

2
3
5
7----------------------------------------------------------------
ValueError                     Traceback (most recent call last)
<ipython-input-113-37adca265503> in <module>
 **12** for x in primes:
 **13**     if x > 10:
---> 14         primes.throw(ValueError, "Too large")
 **15**     print(x)

<ipython-input-113-37adca265503> in getPrimes()
 **3**     while True:
 **4**         if isPrime(value):
----> 5             i = yield value
 **6**             if i is not None:
 **7**                 value = i

ValueError: Too large

关闭功能

处理闭包时没有异常通常是优雅的。在这种情况下,close()函数可以用来有效地关闭迭代器。

primes = getPrimes()for x in primes:
    if x > 10:
        primes.close()
    print(x)

这将为我们提供以下输出。

2
3
5
7
11

请注意,我们的值是 11,这是最后一个大于 11 的计算值。这模拟了 C/C++中 do while 循环的行为。

我相信这篇文章将有助于你将来开发更好的软件和研究程序。感谢阅读。

干杯😃

Python:遗传算法和旅行推销员问题

原文:https://towardsdatascience.com/python-genetic-algorithms-and-the-traveling-salesman-problem-f65542fae5d?source=collection_archive---------10-----------------------

当分类和回归…没用的时候怎么办!

信用:Pixabay

在过去的 5 年里,数据科学受到了疯狂的复仇者级别的炒作。但是你知道运筹学也同样有趣、有益和具有挑战性吗?然而,与数据科学不同的是, OR 并不是 100%专注于将分类和回归技术应用于任何和所有问题。

我说这话有点言不由衷。

不过是~真的。很少有任务不能被强制成分类或回归问题。但是今天让我们换个话题,讨论其中的一些问题。两个高度影响的问题包括“旅行推销员问题”和“车辆路径问题”后者要复杂得多,涉及到时间因素,而且常常涉及到几辆车。但是在这篇介绍性的文章中,让我们关注两者中更容易的一个。

什么是旅行推销员问题?(TSP)

考虑一个推销员,他离开任何给定的地点(我们说是芝加哥),在回家之前必须在其他 x 个城市停留。维基百科方便地列出了美国前十大城市,所以我们只关注前 25 个。

像任何可以优化的问题一样,必须有一个代价函数。在 TSP 的上下文中,必须尽可能地减少总行驶距离。一个强力的解决方案对于 25 个城市来说是 100%可能的,然而,它比你想象的要复杂的多。25 个城市有 15,511,210,043,330,985,984,000,000 种不同的排列。这大约是 15.5 亿英镑。你知道七月是一个词吗?

有了这么多可能的组合,找到全局最优解有点像在针堆里找一根干草。是的,你没看错。作为回应,我们的目标不是找到全局最优解——而是找到无数个近似最优解中的一个,并避免无数个中等好的(和绝对糟糕的)解。这是遗传算法的一大进步。

什么是遗传算法?

遗传算法是一类从遗传学中获取灵感的算法。更具体地说,“基因”通过交叉(繁殖)和突变经过多次迭代而进化。这可能有点乱伦,但请原谅我。在最简单的情况下,我们从两个基因开始,这些基因相互作用(交叉),产生一个新基因,从一个基因获得一些属性,从另一个基因获得其余属性。然后,随机变化(突变)被引入新基因。现在有三个基因,两个父母和一个孩子;所有这三个都根据成本函数进行评估。如果孩子是最弱的,我们删除它,重新开始。否则,我们去掉双亲中较弱的一个,然后用剩下的两个基因重复整个过程。从概念上讲,这就是全部。

它基本上是进行 x 猜测,创建 y 混合猜测,评估基因库的适应性并做一些修剪。冲洗并重复,直到你收敛于一个解决方案。(你会收敛到一个解,它很可能是全局最优解而不是。)是的,因为计算机正在从遗传学中汲取灵感,但并没有受到遗传学特性的内在限制,所以算法在每次迭代中可以有任意数量的父母和子女。

变异和交叉起什么作用?

早期,变异是王道。这是“探索-利用”范式中的探索(在强化学习术语中很常见。)突变学习什么“管用”。然而,随着系统开始学习什么是有效的,什么是无效的,重要的是改变方式,开始很好地利用我们的知识——通过交叉——并利用我们所学的知识。有几种方法可以做到这一点。它可以是突然的转变,也可以是逐渐的变化。但关键是以科学家的思维开始,从环境中学习,以商人的思维结束,从学到的经验中获利。

好吧,但这在实践中意味着什么?

在 TSP 的上下文中,每个“基因”将是一个城市序列,以芝加哥开始和结束。任何给定基因的“适应度”是其往返总距离。我们从随机产生的 x 基因开始。如果我们只是偶然发现了全局最优解,那将是不可思议的,但这是不可能的;同样,任何起始基因都不太可能是字面上最糟糕的旅行。但是,有些基因会比其他基因更“适合”。注意我们只随机生成基因一次。 过了这一点,每一个新的基因都是交叉和突变的函数。在 TSP 的上下文中,这意味着随机地从先前的基因中继承城市和它们各自的索引。例如,我们可能从一个父母基因中继承“达拉斯”作为第五个元素,从另一个父母基因中继承“纳什维尔”作为第六个元素。请注意,我们随机选择了这些城市及其指数;我们不知道这是否有益。我们只是简单地去做,然后抱最大的希望。如果这不是有利的,新的基因被丢弃,我们重新开始。但是如果这个随机选择 有益的,我们就丢弃较弱的亲代基因并继续。我们仍然不知道达拉斯获得第五个指数是否有什么神奇之处,但在当时它似乎是有利的,所以最新的基因进化来保持它。

这个过程一遍又一遍地重复。

最终,一个基因将会“非常好”,并且在随后的迭代中不会被替换。我们的基因将很有可能陷入局部最优。但这是可以接受的,因为有超过 1570 亿种选择,而绝大多数都非常糟糕。但这是普遍生活的真实情况。种类繁多,谁说老虎进化而狮子进化错了?当然,一只古代通灵串联战象会胜过这两者(谷歌一下),但是这种可能性还没有在我们的物理宇宙中实现,而且(可悲的是)它可能永远不会实现。

现在是代码!

一对夫妇注意,(A)我已经包括了一个小功能,将查询谷歌地图之间的距离位置。(B)我从这里得到了排名前 25 的城市,以及(C)我是否使用了作为迭代函数逐渐减少的ε参数,有利于早期探索和后期开发。

现在让我们来看看结果。我们开始时总持续时间超过 25,000 英里,后来减少到大约 10,000 英里。(对于一个运行了~3 秒的算法来说,已经不错了!)

如你所见,我们被卷入了我几乎可以肯定是局部最优的情况,但是公路旅行实际上是有意义的,这真的很酷!您需要对这段代码进行大量的修改,以适应不同的目的,但是市场上有更健壮的遗传算法实现。我只希望这篇文章扩展了您对分类和回归世界之外的可能性的认识。

感谢阅读!如果你认为我的内容没问题,请订阅:)

Python 图形用户界面应用

原文:https://towardsdatascience.com/python-gui-app-in-no-time-ea7282e33024?source=collection_archive---------8-----------------------

Tkinter 图书馆的近距离观察

当今应用程序最重要的部分之一是图形用户界面本身。

这是因为市场竞争激烈,已经饱和,甚至不再关注功能,而是谁能让它看起来更漂亮,使用起来更简单。

今天我们将学习如何用最流行的编程语言之一 Python 创建和构建 GUI 应用程序。

这个简短的教程将会逐行解释,并且非常容易理解,尽管你可能没有太多 Python 或编程的经验。

环境

对于这个应用程序的开发,你不会需要太多,如果你已经熟悉 Python,你可以跳到本文的下一章。

代码和软件开发我个人选择的是 Visual Studio 代码

接下来,我们需要安装 Python,所以如果你使用的是 Ubuntu 或类似的 Linux 发行版,Python 是预装的。

如果不是这样,您可以像这样安装它:

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get update
sudo apt-get install python3.8

*在撰写本文时,Python 3.8 是最新的稳定版本,建议 PPA 使用 deadsnakes。

在其他操作系统上,如 windowsmac ,您将通过下载可执行安装并运行它来安装它。

Tkinter 库

我们还必须安装用于开发的 Tkinter 库:

sudo apt-get install python3-tk

[tkinter](https://docs.python.org/3/library/tkinter.html#module-tkinter)包(“Tk 接口”)是 Tk GUI 工具包的标准 Python 接口。

编码

在我们开始导入所需库的编码时:

import tkinter

一旦我们导入了它们,我们就能够在我们的代码中使用它们,通常,您的代码编辑器将能够从那些库中识别出关键字,并尽可能地使您的输入更容易。

接下来是创建窗口,我们将使用它来添加元素并作为 GUI 应用程序的主窗口。

window = tkinter.Tk()

Tk 的顶层小部件,主要代表应用程序的主窗口。它有一个相关的 Tcl 解释器。

初始化窗口后,你所要做的就是调用 Tk 的主循环,它将执行你为 GUI 设置的所有命令。

window.mainloop()

主循环负责任何事件,比如按钮点击或者文本框输入,从运行到窗口关闭。

使用以下命令运行 Python 文件:

python3 GUI.py

这里是我们的第一个窗口!

这只是我们应用程序的开始,我们接下来要做的是定制我们的窗口!

标题

向我们的窗口添加标题非常简单:

window.title("Python GUI")

“Python GUI”主窗口

这里需要注意的一件重要事情是,我们希望为我们的窗口执行的每一条 命令 都必须在“window.mainloop()”之前,因为否则它不会显示在 GUI 中。

窗口大小

设置一个特定的窗口大小是相当重要的,因为你可能需要更多的空间来放置我们稍后将要添加的元素!

方法是:

window.geometry("450x250")

第一部分是宽度,后面是分隔为“x”和高度的数字。

设置完基本的窗口设置后,我们就可以向 GUI 应用程序添加元素了。

元素

这里我们可以使用不同种类的元素,它们是由 Tkinter 库提供给我们的,但是我们将把重点放在对每个 GUI 应用程序最重要的四个元素上。
分别是:标签按钮条目(输入)、和文本

标签

在每一个 GUI 中,为使用程序的用户创建某种文本显示是很重要的。

label = tkinter.Label(window, text="Some label text",width = 50)

我们将标签保存在名为“变量”的变量下,并将其定义为属于我们的主“窗口”,包含一些文本,并且可以定义额外的参数,如宽度等。

定义标签后的一个重要步骤是,我们必须将它打包并设置到窗口中。有一个名为 pack()的函数正好可以做到这一点:

label.pack()

该几何管理器在将微件放入父微件之前,将微件组织成块。

纽扣

我们使用按钮来执行某种类型的命令或我们的应用程序可能需要的后端功能。

因为我们需要某种功能,所以我们定义‘clicked’来在每次按钮被点击时创建一个新标签。

def clicked():
  label = tkinter.Label(window, text="Button label",width = 50)
  label.pack()butt = tkinter.Button(window, text="Click button!", command=clicked,width = 10)butt.pack()

每次点击按钮,都会创建一个带有类型标签的新对象,显示在前一个对象的下方。

条目(文本框)

这个元素在 Tkinkter 库中被称为条目,但对于许多其他编程语言来说,它在术语文本框下也很常见。

让我们看看如何实现它:

entry = tkinter.Entry(window, width=10)entry.pack()

Entry 元素的有用功能是我们可以检索用户在里面写了什么,但是在二进制转换器的例子中有更多的内容。

文本

专门的文本框,比常规条目更具可定制性。

我们是这样使用它的:

text = tkinter.Text(window, width=20, height=5)text.insert(tkinter.INSERT, "Hello")text.insert(tkinter.END, "World")text.pack()

我们有像 INSERT 和 END 这样的参数,所以我们可以指定我们想要的文本的位置。欲了解更多信息,请点击这里

一旦我们完成了所有必要的元素,让我们用刚刚学到的知识来构建一个实际的应用程序。

从头开始构建我们自己的应用程序

我们应该创造一些对我们有意义和有用的东西。

我的第一个想法是简单的计算器,这样我们可以利用我们在教程中谈到的所有元素。

让我们来看看我在这里写的完整代码:

我们基本上使用了我们讨论过的所有元素,我在 addsub 函数中创建了简单的文本和条目操作。

每次单击添加两个数字时,文本元素都会被清除,并插入新值。
还有 ValueError 处理,它将捕捉除数字之外的任何内容,这很好。

以下是教程和计算器示例的完整代码。

[## lazargugleta/Python-Gui

在 GitHub 上创建一个帐户,为 lazargugleta/Python-Gui 开发做出贡献。

github.com](https://github.com/lazargugleta/Python-Gui)

今天就到这里吧,我美丽的人们。

结论和后续步骤

这只是一个非常简单的 Python 图形用户界面,在我看来,如果每个人都跟着做,他们就能做到!

虽然简单,但它是一个非常强大的软件,可以用来创建现实世界的应用程序!

保持创意,关注我以获得更多像这样的教程!

Python:从头开始的哈密顿蒙特卡罗

原文:https://towardsdatascience.com/python-hamiltonian-monte-carlo-from-scratch-955dba96a42d?source=collection_archive---------10-----------------------

物理学和统计学即将发生碰撞,这并不像你想象的那么可怕

信用:Pixabay

如果你对马尔可夫链蒙特卡罗(MCMC)方法的体验和我一样,那就是无止境的寻找答案。每当你得到一个问题的答案,就会有十几个问题冒出来!你不断地学习你不知道的东西。我最近接受了一份全职工作,在一个组织担任数据科学家,该组织广泛使用贝叶斯统计,并通过扩展使用 MCMC 方法。所以我决定和这个数学分支一战到底!关于 Metropolis,Metropolis-Hastings,哈密顿蒙特卡罗的详细回顾,请访问我的公共 Google Colab 笔记本😃

在深入研究新材料之前,我将重温 Metropolis-Hastings (MH)背后的关键思想,因为哈密顿蒙特卡罗(HMC)是 MH 的扩展。

大都会黑斯廷斯

大都会-黑斯廷斯是一个美化的随机漫步。你需要四个要素:一个起点,一个目标分布,一个提案分布,一个公正的评委(随机事件。)目标分布可以是您想要从中取样的任何分布;你需要的只是概率密度函数(PDF)。同样,建议分布可以是任何 PDF(尽管如果分布是对称的,数学会更简单。)整个想法是从使用建议分布的随机点开始。将其追加到数组中。将这一点输入目标的 PDF 以获得概率密度(也称为可能性)。现在,通过建议分布生成一个扰动,将它添加到当前位置,为这个变量指定一个新名称,并通过目标的 PDF 评估它的可能性。比较可能性

acceptance = target_PDF(proposed)/target_PDF(current)

这个数字将落在[0,inf 范围内的任何地方。如果小于 1,你有 x%的机会移动。任何高于 1 的都是保证运动。这就是“公正的法官”的用武之地。观察一个随机事件(通常是从均匀分布中抽取的[0,1]中的一个数。)如果这个数字小于或等于接受度,您就移动到建议点。否则,你留在原来的位置。将获胜者追加到数组中。这就是大都会算法。

如果提案分布不对称,事情会稍微复杂一些。如果你从正态分布、均匀分布等中抽取运动样本,这一步是不必要的。但是,如果使用分布,如伽玛、泊松、指数、对数正态等。那么你需要考虑固有的偏见。在我在开头链接的 Colab 笔记本中,我使用了一个β建议分布,带有一个(-0.5 常数项),偏向 1(与对称或偏向 0 相反。)需要注意两件事:首先,Beta 分布被定义为[0,1]意味着我们将永远不会观察到负扰动,这意味着我们的建议将越来越多地只向一个方向移动。我增加了-0.5 的偏置,这样正负样本就可以对扰动进行采样。第二个,不过,分布还是偏向 1,也就是说它只会在一个方向慢慢蠕动。我们需要对此做出解释。我们通过获得扰动和反向扰动的可能性来做到这一点。**

def correct(prop,curr,a=3,b=2):
    x0 = curr - prop + 0.5
    x1 = prop - curr + 0.5
    b0 = beta.pdf(x=x0, a=a, b=b)
    b1 = beta.pdf(x=x1, a=a, b=b)
    return b0/b1

这个修正项(你将在 Colab 笔记本中看到)乘以似然比;它解释了提议分布的不对称性。(注意,这个比率被称为黑斯廷斯比率,因为它是 Metropolis 和 MH 算法之间的唯一区别。)

您可以使用 MH 算法从大多数分布中进行采样。然而,在一天结束时,它基本上是一次随机漫步。没有逻辑告诉我们在当前位置应该有多大的跳跃。当对 1 变量分布进行采样时,这不是问题。但是随着维度的增加,高可能性区域仅构成总面积的一小部分,而中等和低可能性区域构成(指数地)总面积的更多部分。当对低维分布进行采样时,这种效应对 MH 仅造成轻微的低效。但是随着维数的增加,MH 冒着返回不代表目标分布的样本的风险。

原因是在峰值附近进行小幅度跳跃是合适的,因为相对于其可能性而言,过度勘探该区域的风险较低;然而,当我们向尾部移动时,相对于它们的可能性,对这些区域的过度勘探会成为一个相当大的风险。(从上下文来看,一条尾巴上有许多样本而另一条尾巴上没有样本是不可取的。)那么…我们如何在考虑可能性的情况下提出跳跃呢?

哈密顿蒙特卡罗

物理学有答案——万岁!在这篇文章的剩余部分,我们不会把地点看成是随机漫步。相反,我们将把分布的绝对峰值视为一个行星。一颗卫星将环绕这颗行星运行,收集样本。哈密顿力学使用微分方程将动能和势能联系起来。这些微分方程有非常棘手的精确解,但使用蛙跳积分友好的近似解。微分方程的积分将给出我们的卫星将遵循的路径。这些微分方程(或哈密顿方程)根据动能和势能定义了系统的能量。当你把球抛向空中时,它的动能被势能所代替。当球下落时,它的势能被动能所代替。哈密尔顿方程定义了位置和动量之间的关系:

T = time
Q = position 
P = momentum 
K = kinetic energy
V = potential energydQ/dT = P
dP/dT = dV/dQ 

请注意,上述等式是在统计学背景下推导出来的。物理世界必然要复杂得多。

值得注意的是,我们的微分方程是 dQ/dT,位置 wrt(相对于)时间的变化,和 dP/dT,动量 wrt 时间的变化,其评估为势能 wrt 位置的变化。我们可以根据 PDF 本身来定义位置。因此,动量的变化是 PDF 中位置的函数,也就是离峰值的距离。请注意,正态分布的梯度分别在峰值和尾部之间的拐点处最陡。相反,负对数正态分布的梯度在尾部最陡,接近峰值时接近(并达到)0。正如我们之前讨论的:我们希望我们的跳跃大小 ro 与分布中的位置成比例。在接近顶峰时,我们想进行小幅度的跳跃。当我们接近尾部时,我们希望跳跃越来越大。事实证明,负对数正态分布梯度完美地实现了这一效果。(而正态分布梯度会从峰值* 和尾部 提出小的跳跃,这是我们不想要的!)*

分布与梯度

该算法

该算法分为四个部分:

  1. 设置:取前一个位置复制,这样你就有了 q0 和 q1。从 N(0,1)中随机采样一个动量,然后复制,这样你就有了 p0 和 p1。对于单变量高斯,求 PDF 相对于位置-(x-mu)/sigma^2的梯度。
  2. 蛙跳:使用蛙跳积分更新 q1 和 p1(即哈密顿运动或一个质点。)实际上,这是最敏感的部分;小的调整会导致不稳定的行为。
  3. MH Dance :最后,将 p1 乘以(-1),这保证了可逆性(即给定动量 p0 可以从 q0 到达 q1,给定动量-p1 可以从 q1 到达 q0)。这给了我们大都会-黑斯廷斯“舞蹈”所需要的信息。请记住,我们使用的是负对数概率,所以数学就是加法和减法。然后接受/拒绝移动。
  4. 重复固定次数的迭代。

你可能已经注意到,在第一步中,我们从一个高斯样本中抽取动量。这是怎么回事?使用我们之前的卫星比喻,哈密顿运动将引导我们围绕特定可能性的轨道路径(访问与相同可能性相关的位置)。)然而,我们对探索一种可能性不感兴趣,我们想探索所有的可能性。为了实现这种效果,我们对动量“踢”进行采样,这可能导致我们的卫星跳跃或坠落轨道距离(也称为访问不同的可能性。)

代码

再来看看性能!

N(0,1) HMC 采样器输出

扩展ˌ扩张

如果你想运行我的代码,请从头跳到 Google Colab 链接。您只有查看权限,没有编辑权限——但是您可以复制到您自己的 Google Drive 进行实验,下载 iPython 笔记本文件,等等。如果您仔细研究代码,您会注意到路径长度和步长是非常敏感的超参数。最轻微的调整可能会导致无意义的样本。这是基于梯度的 MCMC 采样器的诅咒。然而,还有希望——更新的方法,如无 U 形转弯采样器(NUTS ),通过动态选择路径长度和步长来构建 HMC。

但是为什么这是一个问题呢?从我们假设的卫星轨道示例来看,哈密尔顿方程将指导卫星的运动,“围绕”特定的可能性,这意味着它提出了类似可能性附近的新位置。但是围绕任何给定可能性的轨道长度是不同的。在较高的可能性下,圆周很小,但是当环绕较低的可能性(更接近尾部)时,圆周更大。)我们可以通过简单地观察高斯分布来直观地证实这一点。当 me 围绕给定的可能性做 360°轨道运动时会发生什么?我们提出我们目前的相同观点。在 HMC 的行话中,这被称为“U 型转弯”,意思是我们回到我们刚刚去过的地方。对路径长度和步长的动态调整控制了整合的程度(轨道路径。)如果你稍微摆弄一下代码,你就会发现,这些超参数非常敏感——因此在实践中你很可能会使用螺母而不是 HMC。

我必须给它应得的荣誉。谷歌的软件工程师科林·卡罗尔写了一个更具伸缩性的 HMC 实现。(我的只能用来采样一元高斯。)可扩展性是有代价的——可解释性。我发现要真正“理解”这个概念,我必须把它变得愚笨,然后从头开始构建一个。希望你喜欢这本书!

感谢您的阅读——如果您认为我的内容没问题,请订阅!😃

Python 有一个内置的数据库——下面是如何使用它

原文:https://towardsdatascience.com/python-has-a-built-in-database-heres-how-to-use-it-47826c10648a?source=collection_archive---------2-----------------------

如何利用内置数据库进行数据存储和操作

数据库是存储数据的一种伟大、安全和可靠的方式。所有主要的关系数据库都有一个共同点——SQL——一种操作数据库、表和数据的语言。SQL 是一个涉及面很广的话题,尤其是在与不同的数据库供应商打交道时,比如 Microsoft、IBM 或 Oracle,所以让我们从 SQLite 开始,它是最轻量级的数据库系统。

克里斯蒂娜@ wocintechchat.com 在 Unsplash 上的照片

那么,SQLite 是什么?很高兴你问了这个问题。它是一个为我们提供数据库或关系数据库管理系统的库。术语“Lite”的意思是“轻量级”,这意味着它对于数据库领域的设置和管理来说是轻量级的。

我为什么要关心?因为你不需要下载软件或创建云数据库,然后弄清楚如何与 Python 连接,就可以获得数据库体验。当然,这不是最安全的选择,但它仍然远远胜过 CSV 和 Excel 文件,因为每个人都不能更改数据。

今天的文章结构如下:

  • 问题概述
  • 创建表格
  • 创建、读取、更新、删除
  • 测试时间
  • 结论

因此,我们将介绍一些基础知识——如何创建表、插入数据、更新数据、删除数据、获取所有数据以及根据条件获取数据。它是构建应用程序所需的一切。

问题概述

你喜欢电影吗?是啊,我也是。今天,我们将通过创建一个数据库和一个表来存储电影标题和附加信息,来关注这一点。在我们制作好表格之后,我们需要声明几个函数:

  • 要插入电影
  • 获取所有电影
  • 去买一部电影
  • 若要更新单部电影
  • 若要删除单部电影

听起来很多,其实不是。我们将使用 Python 与 SQLite 数据库通信,并且我们将从IMDB.com获取电影信息。

厉害!我们开始吧!

创建表格

我们不能直接在数据库中存储数据,我们需要表格。数据库存储表,表存储数据。我们的过程如下——仅当 movies 表不存在时才创建它。这将需要两个 SQL 查询,一个检查具有给定名称的表是否存在,另一个创建一个表。

首先,我们需要导入 SQLite 库,建立一个数据库连接,并创建一个游标。下面的代码片段可以做到这一点:

import sqlite3 conn = sqlite3.connect('movies.db') 
c = conn.cursor()

如果 movies.db 数据库不存在,它将被创建,如果存在,只建立一个连接。

接下来,我们将声明一个函数来检查一个表是否存在。表名作为函数参数传递,如果表存在,则返回 True ,否则返回 False :

def table_exists(table_name): 
    c.execute('''SELECT count(name) FROM sqlite_master WHERE TYPE = 'table' AND name = '{}' '''.format(table_name)) 
    if c.fetchone()[0] == 1: 
        return True 
    return False

新的 f-strings 由于某种原因不能工作,所以我们必须使用旧的语法——这不是问题,但是请记住这一点。下一步是使用声明的函数检查一个表是否存在,如果不存在就创建它。下面的代码片段可以做到这一点:

if not table_exists('movies'): 
    c.execute(''' 
        CREATE TABLE movies( 
            movie_id INTEGER, 
            name TEXT, 
            release_year INTEGER, 
            genre TEXT, 
            rating REAL 
        ) 
    ''')

厉害!这部分到此结束,我们接下来将进入有趣的内容。

创建、读取、更新、删除

好了,我们已经配置好了一切,现在是处理数据的时候了。首先,我们需要一个向表中插入电影的函数(创建部分)。这很容易编写,因为我们需要执行一个 INSERT 语句并提交事务。代码如下:

def insert_movie(movie_id, name, release_year, genre, rating): 
    c.execute(''' INSERT INTO movies (movie_id, name, release_year, genre, rating) VALUES(?, ?, ?, ?, ?) ''', (movie_id, name, release_year, genre, rating)) 
    conn.commit()

就是这样!我们将测试部分留到以后,现在我们将继续进行读取部分。

我们将在这里声明两个函数——第一个获取所有电影,第二个只获取一个电影,由电影 ID 指定。您可以轻松地将逻辑浓缩到一个函数中,但是我选择了这种方法。

下面是获取所有电影的函数:

def get_movies(): 
    c.execute('''SELECT * FROM movies''') 
    data = [] 
    for row in c.fetchall(): 
        data.append(row) 
    return data

获取一部电影的代码片段:

def get_movie(movie_id): 
    c.execute('''SELECT * FROM movies WHERE movie_id = {}'''.format(movie_id)) 
    data = [] 
    for row in c.fetchall():  
        data.append(row) 
    return data

太好了!接下来是更新部分。这个比较棘手。我们希望根据给定的电影 ID 更新元素,但是我们将更新什么呢?我们是否为每个字段声明了一个特定的函数?听起来不太对劲。我们将使用字典来执行更新。

我来详细说明一下。我们的更新函数将接受两个参数:

  • 电影 ID —您要更新的电影的 ID
  • 更新字典—要更新的键/值对

更新字典中的键必须根据表列命名,否则会引发异常。此外,我们需要处理数字和文本字段的更新。这是迄今为止最棘手的函数,但是您可以处理它:

def update_movie(movie_id, update_dict): 
    valid_keys = ['name', 'release_year', 'genre', 'rating'] 
    for key in update_dict.keys():  
        if key not in valid_keys: 
            raise Exception('Invalid field name!')     for key in update_dict.keys(): 
        if type(update_dict[key]) == str: 
            stmt = '''UPDATE movies SET {} = '{}' WHERE movie_id = {}'''.format(key, update_dict[key], movie_id) 
        else: 
            stmt = '''UPDATE movies SET {} = '{}' WHERE movie_id = {}'''.format(key, update_dict[key], movie_id)         c.execute(stmt) 
    conn.commit()

看到了吗?没那么难。让我们完成删除部分。它比前一个简单得多,因为我们只需要执行一条语句并提交事务。代码如下:

def delete_movie(movie_id): 
    c.execute('''DELETE FROM movies WHERE movie_id = {}'''.format(movie_id)) 
    conn.commit()

这部分到此结束。接下来我们将测试我们的函数。

测试时间

首先,让我们插入几部电影:

insert_movie(1, 'Titanic', 1997, 'Drama', 7.8) 
insert_movie(2, 'The Day After Tomorrow', 2004, 'Action', 6.4) 
insert_movie(3, '2012', 2009, 'Action', 5.8) 
insert_movie(4, 'Men in Black', 1997, 'Action', 7.3) 
insert_movie(5, 'World War Z', 2013, 'Romance', 10)

执行这五行代码不会像预期的那样向控制台输出任何内容——我们只是向表中插入数据。接下来,我们将使用预定义的函数来抓取所有电影:

print(get_movies())

厉害!现在让我们只看一部电影:

print(get_movie(2))

这很简单。现在我们来看看如何更新电影。最后一个插入的是世界大战 Z ,故意给了 10 分和一个爱情类型,所以让我们改变一下:

update_movie(5, {'genre': 'Horror', 'rating': 7.0})

现在事情说得通了。剩下要做的唯一一件事就是删除一部电影——让我们看看如何做:

delete_movie(3)

这不会像预期的那样返回任何内容。我们可以快速获取所有电影,看看删除功能是否有效:

这就做到了——一切都像广告宣传的那样。让我们在下一部分总结一下。

在你走之前

我希望这很容易理解。我们讨论了基础知识,留下了许多未触及的东西。构建基本的、数据库驱动的应用程序或 API 已经足够了,但是以后可以更多地使用 API。

请随意扩展它,添加新的函数或表,或者提高整体代码质量。

感谢阅读。

加入我的私人邮件列表,获取更多有用的见解。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@radecicdario/membership)

原载于 2020 年 10 月 1 日 https://betterdatascience.com

Python:如何获取实时市场数据(滞后小于 0.1 秒)。

原文:https://towardsdatascience.com/python-how-to-get-live-market-data-less-than-0-1-second-lag-c85ee280ed93?source=collection_archive---------0-----------------------

这篇文章会有点特别。我将测试 Yahoo Finance API for Python 的最新版本,它提供了免费获取不到一秒钟延迟的实时数据的可能性。

UnsplashActionVance 拍照

来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

在本文中,您将学习如何使用 Python 包获得实时股票市场数据,而无需调用昂贵的 API,如彭博。我已经帮你测试过了。那有用吗?让我们看看。

如果你现在热衷于自己动手,你可以在本文末尾找到完整的 Python 代码

您将能够使用 Python 包获得股票市场数据,如价格、交易量和基本面数据。(滞后小于 0.01 秒)

本文是下面文章的补充,在下面的文章中,我演示了如何用不到 3 行代码获得市场数据:

[## 如何从纽交所获取不到 3 行的市场数据(Python)。

在本文中,您将学习使用 Python 获取股票市场数据,如价格、交易量和基本面数据…

towardsdatascience.com](/how-to-get-market-data-from-the-nyse-in-less-than-3-lines-python-41791212709c)

好,我们开始吧。

开始前

首先,如果你想跟踪我的进度,在开始之前,你需要在你的机器上安装一个 Python 3 版本和以下软件包:

  • 熊猫
  • NumPy
  • y 金融
  • plottly(非强制,但对绘图有用)

如果这些软件包中的任何一个尚未安装,您可以使用 pip 命令,如下所示。

pip install yfinance
pip install plotly

一旦您确保安装了以下软件包,我们就可以开始了。

如果你已经有了使用 Python 的经验,可以跳到第二步。第一步是导入数据。

一、进口包装

第一步将包括导入必要的包。

首先,您将使用以下代码行导入先前安装的软件包:

上面几行是查询要导入的 numpy,pandas,yfinance & plotly。

一旦我们成立了,让我们进行下一步。

既然库已经导入,我们现在可以导入市场数据。

二。与市场接轨

既然已经上传了所需的不同包。我们将以 UBER 为例,通过 Yahoo Finance API 设置我们的导入。

Yahoo Finance API 将需要 3 个强制参数,顺序如下:

  • 跑马灯 (1)
  • 开始日期+结束日期或期间 (2)
  • 音程 (3)

对于我们的例子,股票代号(参数 1) 将是 UBER 。此外,在本例中,我们将选择最后 5 天的时间段(参数 2) ,而不是定义开始和结束日期。我们将设置 5 分钟的间隔(参数 3) 。快速提醒一下,优步的股票代码是优步

要调用您的数据,您必须使用以下结构:

上面描述了获取我们感兴趣的市场数据的结构。

在进一步讨论之前,我将带来第三个论点的一些细节(区间)。

区间快速查找

我想给你一个快速拍摄不同的间隔,你可以使用雅虎财经 API 设置。

下面详细列出了可能需要的间隔的完整列表:

上面列出了可以选择的不同间隔。

该间隔不会干扰获取实时数据的选项。

我们继续。

现场测试

当我执行下面的行时,我们是 2020 年 10 月 23 日,实际上是伦敦时间下午 5:13,这意味着市场是开放的。

仅供参考:英国时间下午 5:13 相当于纽约时间下午 1:13。

我们已经定义了 3 个参数,让我们执行下面的代码:

下面几行代码都是调用雅虎财经 API

简单回顾一下,下面的代码行调用 Yahoo finance API 并请求获得最近 5 天的数据,间隔为 5 分钟。

这里是的输出:

使用上面的代码发布的输出。

价格已经即时更新;我将数据与当前值进行了比较,我们匹配。

轰!

如您所见,每秒钟都有一个更新发布。例如,如果您查看下面的输出,所提供的最新数据是 1:13 PM 和 50 秒。如果您重新运行您的内核,数据将再次更新。

任务完成。

我把现场测试推得更远,你可以看到数据每秒都在更新,令人印象深刻。此外,您可以在下面的解释视频中获得完整的代码解释:

完整的现场测试编码和解释在上面的视频。

这是使用 Python 和 Plotly 传播的最终实时图:

最终输出:实时图表随时间更新。

赛义德·莱萨尼

如果你想在这个话题上更进一步,这里是本文的第二部分,有一个真实的算法交易例子:

[## Python:我已经测试了实时交易数学技术。

我用 Python 实时测试了一个著名的预测市场的数学技术的实现…

medium.com](https://medium.com/analytics-vidhya/python-i-have-tested-a-trading-mathematical-technic-in-realtime-658a80381151)

来源:

(1)一天学会算法交易:

[## 2021 年:一天学会算法交易

你好,我是赛义德·莱萨尼。我一直在伦敦的多家银行担任数据科学家,是一名…

www.udemy.com](https://www.udemy.com/course/python-for-algorithmic-trading/?couponCode=LOVE_SEPTEMBER)

完整的 python 代码:

完整的 Python 代码

2021 年的 Python 时间表和即将推出的功能

原文:https://towardsdatascience.com/python-in-2021-timeline-and-upcoming-features-c8369abbcc52?source=collection_archive---------13-----------------------

Gabriela Gomez 在 Unsplash 上拍摄的照片

Python 3.10 的一些新特性的预览

我们目前生活在 Python 3.8稳定时代,Python 的最新稳定版本 3.8.4 于上周发布。 Python 3.9 已经处于测试开发阶段,一个测试版 (3.9.0b4)于 2020 年 7 月 3 日预发布,第五个测试版预发布定于明天。3.9 的第一个稳定版本预计在 2020 年 10 月发布。Python 3.10 的开发也于 2020 年 5 月启动,第一个测试版预计于 2021 年 5 月发布。

显然,对于 Python 爱好者来说,有趣的时代就在前方。浏览三个版本(3.8、3.9 和 3.10)的发布时间表促使我在有趣的 Python 开发即将到来的时间表中编辑关键日期

“我妈妈总是说生活就像一盒巧克力。你永远不知道你会得到什么。”——《阿甘正传》

Python 开发周期中的关键日期(未按比例)来源:https://www.python.org/dev/peps/

通常,在开发周期中会有 4–5 个测试版,在第一个测试版发布之后的版本中不会引入新的特性。对于 3.8,beta-1 于 2019 年 6 月发布,对于 3.9,beta-1 于 2020 年 5 月发布。虽然未来 Python 3.10** 刚刚启动,官方网站已经提供了一些的亮点。**

这篇文章旨在提供一个时间表的简要概述和一个即将到来的新 Python 版本的突出特性的预览,改编自 Python 网站的官方示例。请注意,我们可以期待在 3.10 版本中有更多的新功能,我会随时更新下面的列表。

突出 Python 3.10 中的功能

1)二进制表示中 1 的频率

将引入一个新方法bit_count(),该方法将返回整数的二进制表示中存在的个一。结果将是独立于整数的符号。这个功能的一个用例是在信息论中,对于两个等长的字符串,您可以找到两个字符串不同的地方的总数。这种差异被称为汉明距离(参见 Wiki )。阅读这里的了解 Python 中这一功能的历史。****

这个方法简单地将str类型的count方法称为str.count('1')。下面的例子解释了这一点

# Positive integer 
>>> num = 108# Let's first get the binary representation of num
>>> bin(num)
'0b1101100'**>>>** num.bit_count()
4# Negative integer
>>> num = -108>>> bin(num)
'-0b1101100'**>>>** num.bit_count()
4# Under the hood
>>> bin(num).count('1')

2)拉链会“更严格”

一个新的可选关键字参数strict将被添加到zip函数中。如果你通过了strict=True,你正在压缩的的长度必须相等,否则ValueError将被抛出。在 Python 3.9 之前,如果您压缩两个长度不等的列表,您将得到长度等于较小列表的输出。

在下面的例子中可以看到,在 Python 3.10 之前,zip()函数忽略了第一个列表中不匹配的'D'。相比之下,Python 3.10 会抛出一个ValueError。鉴于压缩相同数量的项目的直观性,我喜欢这个功能,因为它可以唤醒你重新检查你的输入。在 PEP 618 阅读更多关于这个问题的内容。

Python 3.10 之前

>>> list(zip(['A', 'B', 'C', 'D'], ['Apple', 'Ball', 'Cat']))
[('A', 'Apple'), ('B', 'Ball'), ('C', 'Cat')]

在 Python 3.10 中

>>> list(zip(['A', 'B', 'C', 'D'], ['Apple', 'Ball', 'Cat'],
             strict=True))
Traceback (most recent call last):
  *...*
ValueError: zip() argument 1 is longer than argument 2

3)字典的只读视图

字典的三个关键方法,keys()values()items(),返回类似集合的对象,分别对应于字典的键、值和项的动态视图。您在这些视图中所做的任何更改也将反映到原始词典中。

在 Python 3.10 中,上述三种方法返回的所有视图都有一个名为mapping的附加属性,该属性将返回映射的一个只读代理。这个只读代理将包装视图引用的原始字典。下面的例子说明了这一点:

让我们定义一个字典,并将它的键和值存储在不同的变量中

>>> fruits = {'Mangos': 12, 'Figs': 100, 'Guavas': 3, 'Kiwis': 70}
>>> keys = fruits.keys()
>>> values = fruits.values()>>> list(keys)
['Mangos', 'Figs', 'Guavas', 'Kiwis']

现在让我们使用del语句从这个字典中删除两个元素。如果您现在打印键和值,您将看到它只返回剩余的项。原始字典中的变化现在反映在视图中(这里的keysvalues)。

>>> del fruits['Figs']
>>> del fruits['Guavas']>>> print (list(keys), list(values))
['Mangos', 'Kiwis'] [12, 70]

现在,有了mapping,你仍然可以得到原始字典的只读代理。酷!不是吗?

*# returns a read-only proxy of the* ***original dictionary***
>>> values.mapping
mappingproxy({'Mangos': 12, 'Figs': 100, 'Guavas': 3, 'Kiwis': 70})>>>values.mapping['Guavas']
3

4)移除一些向后兼容性

从 Python 3.10 起将取消对集合模块的抽象基类(ABCs)的别名支持。因此,现在是停止忽略相应的反对警告并调整代码的好时机。****

到 Python 3 . 9 . 0 B4(2020 年 7 月 3 日发布)

直接从collections模块导入任何这些ABC 将导致到目前为止的DeprecationWarning

>>> from collections import ABC_NameDeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3,and in 3.9 it will stop working

这让我想到了这篇文章的结尾。因为 Python 3.10 将会公布更多的发布亮点,所以我会将它们添加到本文中。敬请期待 让我们一起期待 Python 3.10 。你可以在这里关注当前版本和即将发布版本的发布时间表: 3.83.93.10 。如果您也想了解 Matplotlib 和 Scikit-learn 的最新特性,请阅读我最近发表的关于 Matplotlib 3 新特性和 Scikit-learn 新特性的文章。

用 Altair 实现 Python 交互式数据可视化

原文:https://towardsdatascience.com/python-interactive-data-visualization-with-altair-b4c4664308f8?source=collection_archive---------4-----------------------

用不到 20 行代码创建交互式图表。

一个简单的例子

在我们进入细节之前,我想向您展示一个不到 20 行代码的交互式图表。

这个图表是用 Python 数据可视化库 Altair 创建的。Altair 是 Python 的一个声明性统计可视化库,基于 VegaVega-Lite 。Altair 提供了强大而简洁的可视化语法,使您能够快速构建各种各样的统计可视化。

这个库的关键思想是你在数据列可视编码通道之间声明链接,比如 x 轴、y 轴、颜色等。其余的情节细节是自动处理的。基于这种声明性的绘图思想,可以使用相对简洁的语法创建一系列从简单到复杂的绘图和可视化。

下面是来自官方示例图库的部分示例截图。

来自官方示例图库的一些牛郎星示例

装置

这个库有很多依赖项,我强烈建议创建一个新的虚拟环境。此外,避免使用 base(root) 也是一个最佳实践,因为这可能会破坏您的系统。

关于创建 Python 虚拟环境的教程,你可以看看:

[## 使用“virtualenv”创建虚拟环境,并将其添加到 Jupyter 笔记本中

你是机器学习工程师,正在使用 Python 和 Jupyter Notebook 吗?在这篇文章中,你会看到为什么…

towardsdatascience.com](/create-virtual-environment-using-virtualenv-and-add-it-to-jupyter-notebook-6e1bf4e03415) [## 使用“conda”创建虚拟环境,并将其添加到 Jupyter 笔记本中

你正在使用 anaconda 和使用 Jupyter Notebook 和 Python 吗?在这篇文章中,你将看到如何创建虚拟的…

medium.com](https://medium.com/analytics-vidhya/create-virtual-environment-using-conda-and-add-it-to-jupyter-notebook-d319a81dfd1)

以下是安装 Altair 的两个选项:

  • 终端— pip/conda
  • 阿南康达-领航员

通过 pip/conda 的终端

假设您已经处于想要安装 Altair 的环境中。

Altair 可以与示例数据集一起安装在 vega_datasets 中,

pip install altair vega_datasets

如果您使用的是 conda 软件包管理器,则等同于:

conda install -c conda-forge altair vega_datasets

成功安装后,您应该能够打开 Jupyter Notebook 或 JupyterLab,并执行来自示例库的任何代码。

巨蟒领航员

启动anaconda-Navigator,导航到 环境 ,选择您喜欢安装 Altair 的环境,例如“数据可视化”。然后从下拉菜单中选择未安装

重要提示:您应该始终避免使用 base(root) ,因为库及其依赖项的更新可能会破坏您的系统。

使用 Anaconda-Navigator 安装 Altair

搜索字段中搜索牛郎星,并选择库。之后点击应用应该可以安装 Altair 及其依赖项。可以按照同样的方法安装示例数据集 vega_datasets

一旦成功安装,返回主页并确保您处于正确的环境 你应该能够启动 Jupyter Notebook 或 JupyterLab,并执行示例库中的任何代码。

从 Anaconda Navigator 启动 JupyterLab 或 Jupyter Notebook

牛郎星图表基础指南

牛郎星官方用户指南里有很多概念,但是数据标志编码 是基本的。理解以下概念应该足以让您创建基本的交互式图表。

数据

Altair 内部使用的数据以 Pandas DataFrame 格式存储,但有四种方式可以传入:

下面是一个导入 Pandas 和 Altair 的示例,并创建一个简单的数据帧来可视化,在列 col-1 中有一个分类变量,在列 col-2 中有一个数字变量:

**import altair as alt
import** **pandas** **as** **pd**data = pd.DataFrame({'col-1': list('CCCDDDEEE'),
                     'col-2': [2, 7, 4, 1, 2, 6, 8, 4, 7]})
chart = alt.Chart(data)

马克斯(英格兰人姓氏)

选择数据后,您需要选择各种图表,如条形图、折线图、面积图、散点图、直方图和地图。mark属性指定了这些属性应该如何在图上精确地表示。Altair 提供了许多基本标记属性:

牛郎星基本标志

除基本标记外,它还提供以下复合标记:

牛郎星复合标志

有了上面的图表对象,我们现在可以指定我们希望数据如何可视化。这是通过Chart.mark_*完成的。例如,我们可以使用mark_point()将数据显示为一个点。

import altair as alt
import pandas as pddata = pd.DataFrame({'a': list('CCCDDDEEE'),
                     'b': [2, 7, 4, 1, 2, 6, 8, 4, 7]})
chart = alt.Chart(data)
**alt.Chart(data).mark_point()**

通过执行上面的代码,它应该给你一个图表:

我们获得单点显示的原因是渲染由数据集中每行一个点组成,所有点都绘制在彼此之上,因为我们还没有指定这些点的位置。这将通过编码解决。

编码

在 Altair 中,编码是数据到视觉属性的映射,比如轴、标记的颜色、标记的形状等等。编码方法Chart.encode()定义了图表显示的各种属性,它是创建有意义的可视化的最重要的功能。官方用户指南提供了一长串受支持的属性。以下是最基本的编码属性,了解它们应该足以让您创建基本的图表。

位置通道

  • x:x 轴数值
  • y:y 轴数值
  • row:分面绘图的行
  • column:分面绘图的列

标记属性通道

  • color:标记的颜色
  • opacity:标记的不透明度
  • shape:标记的形状
  • size:标记的大小

文字频道

  • text:用于标记的文本

数据类型

  • quantitative:速记码 Q ,连续实数值
  • ordinal:简写代码 O ,离散订购数量
  • nominal:简写代码 N ,离散订购数量
  • temporal:速记代码 T ,时间或日期值

为了直观地将这些点从代码中分离出来,我们可以将各种编码通道,或者简称为通道映射到数据集中的列。例如,我们可以用x通道对数据的变量col-1进行编码,该通道代表点的 x 轴位置。这可以通过[**Chart.encode()**](https://altair-viz.github.io/user_guide/generated/toplevel/altair.Chart.html#altair.Chart.encode)方法直接完成:

import altair as alt
import pandas as pddata = pd.DataFrame({'**col-1**': list('CCCDDDEEE'),
                     '**col-2**': [2, 7, 4, 1, 2, 6, 8, 4, 7]})
chart = alt.Chart(data)
alt.Chart(data).mark_point()**.encode(
    x='col-1',
    y='col-2'
)**

这是输出

让图表互动

除了基本的图表,Altair 的一个独特功能是用户可以与图表进行交互,包括平移、缩放和选择一系列数据等控件。

在主题后面,只需调用interactive()模块就可以实现平移和缩放。例如:

import altair as alt
import pandas as pddata = pd.DataFrame({'col-1': list('CCCDDDEEE'),
                     'col-2': [2, 7, 4, 1, 2, 6, 8, 4, 7]})
chart = alt.Chart(data)
alt.Chart(data).mark_point().encode(
    x='col-1',
    y='col-2'
)**.interactive()**

Altair 还提供了用于创建交互式图像的选择 API。在selection()功能中,我们可以制作一些更酷的高级功能,比如本文开头所示的 GIF 允许对选定的数据点进行分析并生成实时直方图。

逐步构建交互式图表

有了牛郎星的基础知识,我们来做一个互动图。

对于本教程,我们将使用来自 vega_datasets 中示例数据集中的汽车数据,

from vega_datasets import datacars = data.cars()

首先,我们将使用[**selection_interval()**](https://altair-viz.github.io/user_guide/generated/api/altair.selection_interval.html#altair.selection_interval)功能创建一个区间选择:

brush = alt.selection_interval()

我们现在可以通过设置selection属性将这个画笔绑定到我们的图表:

alt.Chart(cars).mark_point().encode(
    x='Miles_per_Gallon:Q',
    y='Horsepower:Q',
    color='Origin:N'
)**.add_selection(
    brush
)**

上面的结果是一个图表,它允许您单击并拖动来创建一个选择区域,并在创建区域后移动该区域。这很简洁,但是这个选择实际上并没有做任何事情。

添加选择的结果()

要使用这个选项,我们需要在图表中以某种方式引用它。这里,我们将使用[**condition()**](https://altair-viz.github.io/user_guide/generated/api/altair.condition.html#altair.condition)函数来创建一个条件颜色编码:我们将把选择中的点的颜色绑定到"Origin"列,并将选择之外的点的颜色设置为"lightgray":

alt.Chart(cars).mark_point().encode(
    x='Miles_per_Gallon:Q',
    y='Horsepower:Q',
    **color=alt.condition(brush, 'Origin:N', alt.value('lightgray'))**
).add_selection(
    brush
)

条件()的结果

接下来,我们创建一个mark_bar()图表

alt.Chart(cars).mark_bar().encode(
    y='Origin:N',
    color='Origin:N',
    x='count(Origin):Q'
)

牛郎星条形图

为了将条形图与之前的散点图关联起来,我们需要使用transform_filter()并传递同一个brush。此外,对于组合多选图表,我们还需要为它们分别创建变量,并使用组合多选&

**points =** alt.Chart(cars).mark_point().encode(
    x='Horsepower:Q',
    y='Miles_per_Gallon:Q',
    color=alt.condition(brush, 'Origin:N', alt.value('lightgray'))
).add_selection(
    brush
)**bars =** alt.Chart(cars).mark_bar().encode(
    y='Origin:N',
    color='Origin:N',
    x='count(Origin):Q'
).**transform_filter(
    brush
)****points & bars**

而且,就是这样。这是输出

这是完整的代码:

学习建议

本文是一个快速教程,主要是给大家展示这个优秀的数据可视化库。学习没有捷径。你必须看文档,源代码,研究相关的例子,并在实践中应用它们。

尽情享受吧!

仅此而已。感谢阅读。

关于 Altair 交互式数据可视化的更多内容,您可以看看

[## 探索冠状病毒传播的交互式数据可视化

使用 Altair 创建不到 30 行代码的交互式复合图表

towardsdatascience.com](/interactive-data-visualization-for-exploring-coronavirus-spreads-f33cabc64043)

新冠肺炎数据中心的 Python 接口

原文:https://towardsdatascience.com/python-interface-to-covid-19-data-hub-c2b3f69497af?source=collection_archive---------38-----------------------

统一数据集有助于更好地了解新冠肺炎。

编者注: 走向数据科学 是一份以研究数据科学和机器学习为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

图片来自 Pixabay米洛丝拉娃·克里斯诺娃

新冠肺炎数据中心的目标是通过收集世界范围内的精细案例数据,结合有助于更好地了解新冠肺炎的外部变量,为研究社区提供一个统一的数据集。请同意使用条款,并在使用时引用以下参考:

参考

Guidotti,e . Ardia,d .(2020 年)。
https://doi.org/10.21105/joss.02376 数据中心
开源软件杂志5(51):2376
T37

设置和使用

管道安装

pip install covid19dh

导入主功能covid19()

from covid19dh import covid19
x, src = covid19()

返回值

函数covid19()返回 2 个熊猫数据帧:

  • 数据和
  • 对数据源的引用。

参数化

国家

国家名称(不区分大小写)或 ISO 代码(字母 2、字母 3 或数字)的列表。ISO 代码列表可在的处找到。

从特定国家获取数据:

x, src = covid19("USA") # Unites States

同时指定多个国家:

x, src = covid19(["ESP","PT","andorra",250])

如果省略country,则返回整个数据集:

x, src = covid19()

原始数据

合乎逻辑。跳过数据清理?默认True。如果是raw=False,则通过用NaN值填充缺失的日期来清除原始数据。这确保了所有地点共享相同的日期网格,并且没有一天被跳过。然后,NaN值被替换为之前的非NaN值或0

x, src = covid19(raw = False)

日期过滤器

日期可以用datetime.datetimedatetime.date或格式YYYY-mm-dd中的str指定。

from datetime import datetime
x, src = covid19("SWE", start = datetime(2020,4,1), end = "2020-05-01")

水平

整数。数据的粒度级别:

  1. 国家一级
  2. 州、地区或县一级
  3. 城市或自治市一级
from datetime import date
x, src = covid19("USA", level = 2, start = date(2020,5,1))

隐藏物

合乎逻辑。内存缓存?显著提高连续呼叫的性能。默认情况下,启用使用缓存数据。

可以通过以下方式禁用缓存(例如,对于长时间运行的程序):

x, src = covid19("FRA", cache = False)

过时的

合乎逻辑。检索在end日期生成的数据集快照,而不是使用最新版本。默认False

例如,获取 2020 年 4 月 22 日可访问的美国数据类型

x, src = covid19("USA", end = "2020-04-22", vintage = True)

葡萄酒数据在一天结束时收集,但在所有时区的一天结束后,会延迟大约 48 小时发布。

因此,如果vintage = True未置位,但end未置位,则发出警告并返回None

x, src = covid19("USA", vintage = True) # too early to get today's vintageUserWarning: vintage data not available yet

数据源

数据源作为第二个值返回。

from covid19dh import covid19
x, src = covid19("USA")
print(src)

结论

新冠肺炎数据中心协调了疫情各地的大量异构数据。它代表了新冠肺炎在开放公共数据标准和共享方面的首次努力。使用新冠肺炎数据中心的出版物可在此处获得。

感谢

新冠肺炎数据中心得到了加拿大数据评估研究所的支持。 covid19dh 包是由马丁·贝内什开发的。

[1]吉多蒂,即阿尔迪亚,d .(2020)。新冠肺炎数据中心,《开源软件杂志》,5(51):2376

Python 即将受到挤压

原文:https://towardsdatascience.com/python-is-about-to-get-the-squeeze-5ab15fce55bd?source=collection_archive---------0-----------------------

Python 在过去十年统治了数据科学和机器学习,但 Julia 和 Swift 准备废黜这一王者

Jakub Kapusnak 在 Foodiesfeed 上的照片

Python 是在 20 世纪 90 年代作为通用编程语言发布的。

尽管 Python 语法简洁,但它在第一个十年的曝光率并不令人鼓舞,它也没有真正进入开发人员的工作空间。Perl 是首选的脚本语言,Java 已经成为面向对象编程领域的首选。当然,任何语言都需要时间来成熟,只有当它比现有工具更适合某项任务时才会被采用。

对于 Python 来说,这一时刻在 21 世纪初首次到来,当时人们开始意识到它比 Perl 更容易学习,并提供了与其他语言的互操作性。

这种认识导致大量开发人员将 Python 整合到他们的应用程序中。Django 的出现最终导致了 Perl 的灭亡,Python 开始获得更多的动力。尽管如此,它的受欢迎程度甚至不如 Java 和 JavaScript,这两种语言都比 Python 更新。

快进到现在,根据 StackOverflow 开发者调查 2019 ,Python 已经超过 Java 成为第二大最受欢迎的语言。

它也是过去十年中发展最快的编程语言。Python 的流行与 2010 年代大数据的出现以及机器学习和人工智能的发展有很大关系。企业迫切需要一种低门槛的快速开发语言,以帮助管理大规模数据和科学计算任务。Python 非常适合所有这些挑战。

除了这些有利因素之外,Python 还是一种支持动态类型的解释型语言。更重要的是,它得到了谷歌的支持,谷歌为 Tensorflow 投资了 Python,这使它成为数据分析、可视化和机器学习的首选语言。

然而,尽管在本世纪初对机器学习和人工智能的需求不断增长,Python 不会存在太久。像每一种编程语言一样,它也有自己的弱点。这些弱点使得它很容易被更适合企业要求的普通任务的语言所取代。尽管有 R 的存在,但 Swift、Julia 和 Rust 等新语言的出现实际上对当前的数据科学之王构成了更大的威胁。

Rust 仍在试图赶上机器学习社区,因此我相信 Swift 和 Julia 是将取代 Python 并最终统治数据科学的语言。我们来看看为什么 odds 不利于 Python。

Python 缺乏类型安全,速度非常慢

一切美好的事物都是有代价的,Python 的动态类型化自然也不例外。它妨碍了开发人员,尤其是在生产环境中运行代码时。动态类型化使得在不定义类型的情况下快速编写代码变得容易,这增加了遇到运行时问题的风险,尤其是当代码库大小增加时。编译器很容易发现的错误在 Python 中可能无法识别,导致生产中的障碍,并最终减缓大规模应用程序的开发过程。

更糟糕的是,与编译后的代码不同,Python 的解释器在执行时分析每一行代码。这导致了一个开销,与其他语言相比,性能明显降低。

Julia 可以让你避免这些问题。尽管是动态类型的,但它有一个实时编译器。JIT 编译器要么在执行之前生成机器码,要么使用以前存储的、缓存的编译,这使得它与静态类型语言一样具有高性能。更重要的是,它有一个被称为多重分派的关键特性,类似于 OOPs 的函数重载,尽管是在运行时。多重分派的强大之处在于它能够处理不同的参数类型,而不需要创建单独的函数名或嵌套的 if 语句。这有助于编写紧凑的代码,这是数值计算中的一大胜利,因为与 Python 不同,您可以轻松地扩展解决方案来处理所有类型的参数。

更好的是,Swift 是一种静态类型语言,并且由于其 LLVM(低级虚拟机)编译器而得到了高度优化。LLVM 使快速编译成汇编代码成为可能,使 Swift 超高效,几乎和 c 一样快。此外,Swift 还拥有更好的内存安全和管理工具,称为自动引用计数。与垃圾收集器不同,ARC 更具确定性,因为它会在引用计数为零时回收内存。

作为提供类型注释的编译语言,Swift 和 Julia 在开发上比 Python 快得多,也健壮得多。仅这一点就足以推荐他们使用旧语言,但是还有其他因素需要考虑。

Python 在并行性方面有局限性

如果缓慢不是 Python 最明显的缺点,那么这种语言在并行计算方面也有局限性。

简而言之,Python 使用了 GIL(全局解释器锁),它可以防止多个线程同时执行,以便提升单线程的性能。这个过程是一个很大的障碍,因为这意味着开发人员不能使用多个 CPU 内核进行密集计算。

我同意一种常见的观点,即我们目前在利用 Python 与 C/C++库(如 Tensorflow 和 PyTorch)的互操作性方面做得很好。但是 Python 包装器并不能解决所有的调试问题。最终,当检查底层底层代码时,我们会退回到 C 和 C++。从本质上讲,我们不能在底层利用 Python 的优势,这就把它排除在外了。

这个因素很快就会在 Python 的没落和 Julia 和 Swift 的崛起中起到决定性的作用。Julia 是一种专门为解决 Python 缺点而设计的语言。它主要提供了三个特性:协同程序(异步任务)、多线程和分布式计算——所有这些都展示了并发和并行编程的巨大可能性。这种结构使 Julia 能够以远高于 Python 的速度执行科学计算和解决大数据问题。

另一方面,Swift 拥有开发移动应用程序所需的所有工具,并且在并行计算方面没有任何问题。

Swift 和 Julia 拥有 Python 的互操作性和强大的支持

尽管 Python 在速度、多线程和类型安全方面存在不足,但它仍然拥有一个庞大的生态系统,拥有大量的库和包。可以理解的是,Swift 和 Julia 在机器学习领域仍然是婴儿,并且只拥有有限数量的库。然而,它们与 Python 的互操作性大大弥补了 Julia 和 Swift 中库支持的不足。

Julia 不仅让程序员使用 Python 代码(反之亦然),还支持与 C、R、Java 以及几乎所有主流编程语言的互操作性。这种多功能性肯定会给这种语言一个很好的推动,并增加它在数据科学家中迅速采用的机会。

另一方面,Swift 通过 PythonKit 库提供了与 Python 的互操作性。Swift(源自苹果)最大的卖点是它从谷歌那里得到的强大支持,谷歌几十年前就完全支持 Python。看看形势是如何转变的!

此外,Swift 的创始人克里斯·拉特纳现在正在谷歌的人工智能大脑团队工作,这一事实表明 Swift 正在被认真培养为 Python 在机器学习领域的替代品。Tensorflow 团队投资 Swift 的 S4TF 项目进一步证明了该语言不仅仅被视为 Python 的包装器。相反,Swift 由于其差分编程支持和在 C 等底层工作的能力,将有可能被用来取代底层的深度学习工具。

结论

随着数据规模的不断增大,Python 的致命弱点很快就会被发现。易用性和快速编写代码的能力至关重要的日子已经一去不复返了。速度和并行计算是游戏的名字,而更通用的语言 Python 将不再解决这个问题。不可避免的是,当朱莉娅和斯威夫特看起来像是接班人的时候,这种感觉会逐渐消失。

值得注意的是,Python 作为一种编程语言不会很快消失。相反,它只会在数据科学中占据次要地位,因为更专门为深度学习设计的语言将占主导地位。

本文原载于内置的

Python 比 r 好。

原文:https://towardsdatascience.com/python-is-better-than-r-f7bb963a1c85?source=collection_archive---------37-----------------------

原因如下。

戴维·克洛德在Unsplash【1】上拍摄的照片。

目录

  1. 介绍
  2. 原因如下
  3. 摘要
  4. 参考

介绍

虽然说 Python 比 R 好对我来说是真的,但对你来说可能不是真的。出于各种原因,你当然会认为 R 比 Python 更有用。即使你反对我的声明,我仍然希望开始一个对话,让我们都能看到两种编程语言的好处。对于数据科学家来说,我相信 Python 比 R 有更多的好处。我确实意识到 R 有一些独特而强大的统计库,很可能会盖过 Python 库:然而;通过使用 Python,整个数据科学过程能够与数据工程师、软件工程师和机器学习工程师一起扩展,从而获得更多好处。

下面,我将讨论为什么我认为 Python 比 r 更好的五个主要原因。这些原因包括:可伸缩性、Jupyter 笔记本、库包、集成以及成为跨职能团队成员的能力。

原因如下

  • 扩展性

可伸缩性是在数据科学中使用的一个巨大优势。因为大多数数据科学家经常与工程部门的其他员工一起工作,建模可以变得更容易部署,模型的一般、整体流程也是如此。例如,一个典型的数据科学家可能只专注于执行建模,甚至是一次性的输出。然而,在建模之前有一个步骤,你很可能需要在训练你的机器学习模型之前完成。这一步是数据工程部分。在这个过程中,您可以从 SQL 数据库中自动读入新数据,以便您的模型在训练时总是最新的。流程的另一面是部署方面。第一次部署一个模型可能是相当令人生畏的,特别是因为它在学校里的教授不像建模过程那么多。

软件工程师和机器学习工程师可以和你并肩工作,因为 Python。

您可以创建气流定向非循环图(DAG ),当特定计划中有新数据或满足某些参数时,该图可以自动训练模型(例如,如果我们获得 100 条新的传入数据记录,则仅训练该模型)。一旦模型被训练,它可以评估新的数据,然后可以通过使用 Python 将这些数据输出到 SQL 表中。

  • Jupyter 笔记本

或者另一个类似的数据科学可视化工具,能够解释 Python。您可以运行代码单元、添加注释、创建标题,以及添加可以改进笔记本功能的小部件。你在这里写和分享的代码就是 Python。能够在 Jupyter 笔记本上用这种编程语言编码是数据科学家的一大胜利。

  • 库包

有几个功能强大的常用包可以用 Python 访问。想到的一些是 sklearn(也称为 sci-kit learn)和 TensorFlow。

sk learn【2】

这个强大的数据科学库打包了分类和回归模型,随时可用于您的数据集。

分类

Sklearn 对分类的定义是:识别一个物体所属的类别。一些流行的算法包括支持向量机(SVM)、最近邻和随机森林。Sklearn 还概述了垃圾邮件检测和图像回归,作为他们最受欢迎的应用程序用例。

回归

Sklearn 对回归的定义是:预测一个与对象相关联的连续值属性。流行的回归算法包括支持向量回归(SVR)和最近邻法,以及药物反应和股票价格等应用。

张量流【3】

对于深度学习,这个库是我建模更复杂情况的首选。人们可以用这个流行而强大的库进行的一些主要项目有:神经网络、一般对抗网络和注意力集中的神经机器翻译。

  • 集成

因为我在大部分数据科学项目中使用 Python,所以我成功地集成了模型。py 文件转换成面向对象的编程格式。这些文件是以模块化的方式有条不紊地开发的。用 Python 调用 API 有些简单,因为网站上有很多文档可以帮助获取网站/公司数据。

  • 交叉功能

这个原因在某种程度上是可伸缩性和集成的结合。如果您想在本地执行数据科学流程,并将结果交给利益相关方,这很好,但是使用 Python,您可以与来自工程领域的不同专家一起做更多事情。

当我第一次开始编码时,是在 R 中,当我为了部署的目的向数据工程师和软件工程师展示我的过程和代码时,需要一些额外的时间来准确描述代码背后的数据科学。

我还会发现,与我一起工作的大多数帮助我部署模型的工程师已经在使用 Python,因此他们可以相当容易地翻译我的数据科学代码,即使他们并不完全理解模型是如何工作的。

摘要

克里斯里德在Unsplash【4】上的照片。

如您所见,选择使用 Python 的数据科学家有很多好处。虽然这两种编程语言都非常有用和成功,但我从个人经验中发现 Python 比 r 更好。这些主要原因包括但不限于:可伸缩性、Jupyter 笔记本、库包、集成和交叉功能。最终,语言的选择取决于数据科学家,但本文的目标是展示我如何使用 Python 进行数据科学家项目,以及为什么使用 Python 比 R 编程更好。

我希望你觉得这篇文章既有趣又有用。感谢您的阅读!

参考

[1]照片由 David ClodeUnsplash(2018)上拍摄

[2] sklearn, sklearn 主页,(2020)

[3] TensorFlow, TensorFlow 主页,(2020)

[4]Chris Ried 在 Unsplash 上拍摄的照片,(2018)

Python 正在慢慢失去它的魅力

原文:https://towardsdatascience.com/python-is-slowly-losing-its-charm-9ca652726492?source=collection_archive---------0-----------------------

意见

编程语言的瑞士军刀有它的问题,可能会被其他更适合这项任务的语言所取代

塔玛拉·戈尔在 Unsplash 上的照片

自从 Python 在 20 世纪 90 年代早期发布以来,它已经产生了很多宣传。当然,编程社区至少花了 20 年才意识到它的存在,但从那以后,它的受欢迎程度已经远远超过了 C、C#、Java 甚至 Javascript。

虽然 Python 主导了数据科学和机器学习领域,并且在某种程度上主导了科学和数学计算领域,但与 Julia、Swift 和 Java 等新语言相比,它也有自己的缺点。

是什么让 Python 如此受欢迎?

Python 的飞速发展背后的一个主要驱动点是它的易学性和易用性,这使得它对初学者非常有吸引力,甚至对那些因为像 C/C++这样的语言的艰深、陌生的语法而回避编程的人也是如此。

这种语言的核心是广泛强调代码的可读性。凭借其简洁而富于表现力的语法,它允许开发人员表达想法和概念,而无需编写大量代码(如 C 或 Java 等低级语言)。鉴于其简单性,Python 可以与其他编程语言无缝集成(比如将 CPU 密集型任务卸载到 C/C++ ),使其成为多语言开发人员的额外收获。

Python 通用性的另一个原因是它被企业(包括 FAANG)和无数小型企业大量使用。今天,你会发现你能想到的几乎任何东西的 Python 包——对于科学计算,你有用于机器学习的 NumpySklearn 和用于计算机视觉的 Caer (我的计算机视觉包)。

[## 贾斯考斯/卡尔

用于高性能人工智能研究的轻量级计算机视觉库。Caer 包含强大的图像和视频处理操作…

github.com](https://github.com/jasmcaus/caer)

Python 有弱点

很慢,非常慢

尼克·艾布拉姆斯在 Unsplash 上拍摄的照片

这可能是显而易见的。速度通常被认为是开发人员的主要关注点之一,并且可能会持续一段不可预见的时间。

Python“慢”的主要原因有两个——Python 被解释为而不是编译,最终导致执行时间变慢;以及它是动态类型化的事实(变量的数据类型由 Python 在执行过程中自动推断)。

事实上,这种认为“Python 很慢”的观点在初学者中有很大的影响。是的,是真的。但只是部分地。

以 TensorFlow 为例,这是一个用 Python 编写的机器学习库。这些库实际上是用 C++编写的,并在 Python 中可用,在某种程度上形成了围绕 C++实现的 Python“包装器”。Numpy 也是如此,在某种程度上,甚至 Caer 也是如此。

它有一个 GIL

Python 缓慢的主要原因之一是 GIL(全局解释器锁)的存在,它一次只允许一个线程执行。虽然这提高了单线程的性能,但它限制了并行性,开发人员不得不实施多处理程序而不是多线程程序来提高速度。

不是内存密集型任务的最佳选择

当对象超出范围时,Python 会自动进行垃圾收集。它旨在消除 C 和 C++在内存管理方面的复杂性。由于指定数据类型的灵活性(或缺乏灵活性), Python 消耗的内存量可能会迅速爆炸。

此外,Python 可能没有注意到的一些 bug 可能会在运行时突然出现,最终会在很大程度上减慢开发过程。

在移动计算领域表现不佳

照片由 Yura FreshUnsplash 上拍摄

随着从桌面到智能手机的大规模转移,显然需要更健壮的语言来为移动设备构建软件。虽然 Python 在桌面和服务器平台上有相当大的代表性,但由于缺乏强大的移动计算处理,它往往会在移动开发中失利。

近几年来,这个领域有了很大的进步,但是这些新增加的库甚至不能与他们的强劲竞争对手如 Kotlin、Swift 和 Java 相提并论。

其他语言的兴起

最近,像 Julia、Rust 和 Swift 这样的新语言已经出现在雷达上,从 Python、C/C++和 Java 中借用了许多好的设计概念— Rust 非常好地保证了运行时的内存安全和并发性,并提供了与 WebAssembly 的一流互操作性; Swift 由于支持 LLVM 编译器工具链,几乎和 C 一样快,而Julia为 I/O 密集型任务提供异步 I/O,速度快得惊人。

结论

Python 从来不是为了成为最好的编程语言而构建的。它从来就不是为了应对 C/C++和 Java 而构建的。它是一种通用编程语言,强调人类可读的、以英语为中心的语法,允许快速开发程序和应用程序。

Python 和其他语言一样,归根结底是一种工具。有时候,它是最好的工具。有时候不是。最常见的是“还行”。

那么,Python 作为一种编程语言,是不是正在走向灭亡?

我不这么认为。

它正在失去魅力吗?

啊,也许有一点。就一点点。

用于自然语言处理的 Python 库

原文:https://towardsdatascience.com/python-libraries-for-natural-language-processing-be0e5a35dd64?source=collection_archive---------5-----------------------

用于自然语言处理的流行 python 库概述

用于自然语言处理的 Python 库

“Python 从一开始就是 Google 的重要组成部分,并且随着系统的成长和发展而保持不变。如今,数十名谷歌工程师使用 Python,我们正在寻找更多掌握这种语言的人。”

-彼得·诺威格谷歌搜索质量总监T5

ython 是目前世界上最热门的编程语言之一,因为它可以优雅地与其他编程语言集成,并作为首选编程语言完美地融入大多数新项目理念。

Python 也是人工智能社区中一种非常受好评的语言,这使得它成为人工智能的几个分支的首选编程语言,如软计算机器学习自然语言处理等。

随着未来越来越倾向于采用人工智能和智能解决方案,开发不仅能理解我们的命令,还能与我们自然交流的系统的需求越来越高。

什么是 NLP?

没有单词和驱动这些单词的语法,任何语言都是不完整的。正如人与人之间的交流需要语言和符号一样,与计算机的互动也是如此。

通过点击选项与计算机进行交互的传统方法正慢慢被一种更无缝的方法淘汰,这种方法包括对话。这种现代的交流方式包括以更自然的方式与计算机交谈,因为我们倾向于用语言与其他人交谈。

作为人工智能的一个分支,自然语言处理定义了人类如何更直观地与计算机互动背后的科学。

这样一个领域背后的目的是确定如何让计算机理解和理解除了通常和合理定义的指令集之外的人类常用语言。

作为人工智能的一部分,NLP 在很大程度上依赖于机器学习,NLP 的过程是这样的:

●捕捉人类输入,包括文本输入或语音输入

●将语音数据转换成文本

●使用语法、解析技术、语义和类似方法处理文本,以识别数据的含义

●通过在屏幕上显示或通过音频播放,将处理后的输出传递给人类

用于自然语言处理的 Python 库

自然语言处理被认为是制造智能系统的许多关键方面之一。通过使用从现实世界中收集的数据来训练您的解决方案,您可以使其更快、更贴近用户,从而对您的客户群产生重要的洞察力。

在本文中,我们将了解 Python 如何提供一些最有用、最强大的库,以便在项目中利用自然语言处理的能力,以及它们的确切用途。

●空间

空间(来源)

Python 中工业级自然语言处理的开源库。

通常被认为是高级自然语言处理的专业级 Python 库,spaCy擅长处理难以置信的大规模信息提取任务。

spaCy 使用 Python 和 Cython 构建,结合了两种语言的优点、Python 的便利性和 Cython 的速度,提供了一流的 NLP 体验。spaCy 是一个简洁的库,旨在通过最大限度地减少花费在日常任务上的时间来完成工作。spaCy 的主要收获是:

●词性标注

●符号化

●依存解析

●句子分割

●实体和句子识别

●与深度学习无缝集成

●清理和规范化文本的方法

资源-

[## 空间 101:所有你需要知道的空间使用文档

最重要的概念,用简单的术语解释,不管你是 spaCy 新手,还是只想温习一些…

空间. io](https://spacy.io/usage/spacy-101/)

● CoreNLP

Stanford CoreNLP 是一套为在你的项目中实现自然语言处理而构建的工具。最初是用 Java 编写的,CoreNLP 可以和其他语言一起工作,比如Python、JavaScript 等等。

它提供了几个语言特性,比如表达情感、提取实体之间的关系、标记句子结构、提供单词的基本形式等等。

用更花哨的术语来说,这些功能可以转化为词汇化、词性和词形标注、命名实体识别、标记化和句子拆分等更多功能。

如果您正在寻找一个 NLP 工具包,它是一个现代化的、健壮的、具有各种语法分析工具的工具包,这些工具定期更新并提供高质量的分析,那么它是一个完美的选择。

CoreNLP 的灵活特性允许它与其他语言很好地集成,使它成为满足您需求的平滑可扩展的功能性 NLP 选项。

资源-

NLTK — T 最广为人知的 NLP 图书馆

自然语言工具包的简称,NLTK 是 Python 的领先的和最好的自然语言处理库之一。它有超过 100 个语料库和相关的词汇资源,如 WordNet、Web 文本语料库、NPS Chat、SemCor、FrameNet 等等。

NLTK 的目标是通过为 NLP 库提供分类、词干、标记、解析、分类语义推理和包装器等特性,使学习和使用计算语言学变得更加容易。

这是一个免费的开源库,可以在 Windows、Mac OS 和 Linux 上使用,有大量的教程可以让你顺利进入 NLP 的世界。

使用 NLTK 可以做的事情—

NLTK —对一些文本进行标记和标记()

NLTK —识别命名实体()

资源—

  • NLTK 书 —用 NLTK 完成 Python 自然语言处理教程。
  • 深入 NLTK —使用 NLTK 进行文本处理的详细 8 部分教程。

● Gensim

Gensim 是用 Python 编写的用于主题建模、相似性检索和自然语言处理的库。

雷迪姆·řehůřek****于 2009 年开发的 Gensim 旨在擅长两件事,一个是自然语言处理,另一个是信息检索。它处理特定类别的大量数据,并从中提供非常精确的见解。

Gensim 为几种流行的算法提供了独立于内存的实现能力,例如潜在狄利克雷分配【LDA】随机投影(RP)****潜在语义分析(LSA/LSI/LVD)分层狄利克雷过程(HDP) 等等。

Gensim 附带了流畅的 API 支持,使与其他编程语言的集成变得轻而易举,而丰富的文档教程则在您的编程之旅中为您提供指导。使用 Gensim 的先决条件是使用 NumPy 和 Scipy 包。

资源-

  • gensim 文档 —官方文档和教程。教程页面非常有用。

PyNLPI

关于 FoLiA XML 和许多其他常见 NLP 格式(CQL、Giza、Moses、ARPA、Timbl 等)的广泛功能。).

读作“ 菠萝,是 Python 的开源自然语言处理库。PyNLPl 是各种任务的理想选择,包括构建简单模型、提取 n 元语法和频率列表,并支持复杂的数据类型和算法。

它还配备了对标准 NLP 文件格式的支持,如摩西Timbl吉萨等等。PyNLPl 的库由几个包组成,这些包详细介绍了它所提供的功能。

以下是其中的几个软件包:

● pynlpl.datatypes 增加了额外的数据类型

● pynlpl.formats.giza,用于从 GIZA++单词对齐中读取数据

● pynlpl.formats.tmbl 允许读取 Timbl 数据

● pynlpl.textprocessors 作为简单的标记器和 n-gram 提取

● pynlpl.formats.cgn 用于解析 cgn 词性标签

图案

Web(数据)挖掘/爬行和常见的 NLP 任务。

Pattern 主要是 Python 的一个 web 挖掘模块,包含了用于许多目的的工具,如数据挖掘、自然语言处理、机器学习和网络分析。

专注于模式的 NLP 方面,它很好地配备了任何 NLP 的基本功能,例如词性标记、n-grams、情感分析、WordNet、文本分类和标记化等等。

它完整地记录了超过 350 个单元测试和超过 50 个例子,让你马上开始使用它。对 web APIs 的支持可以轻松地与其他编程语言集成,从而扩展模式的功能。

谷歌趋势—一段时间内的兴趣模式

谷歌趋势-模式(来源)

●多语言

多语种和音译能力。

由 Rami Al-Rfou 开发的 Polyglot 是一个 Python 自然语言处理库,对于必须处理大量语言的应用程序来说是完美的。

由于支持一些传统的自然语言处理功能,如标记化、语言检测、词性标注等,它的每个自然语言处理功能都因支持多种语言而得到进一步增强。

对多种语言的支持使其成为本地化扮演重要角色的可行选择。它附带了详细的文档,简化了任何人的进入过程。

TextBlob

Textblob ( )

Textblob 是另一个开源 Python 库,用于处理基于文本的数据,并通过其 API 提供与其他编程语言的平滑集成。如果您急于执行标准的 NLP 操作,Textblob 可以成为您的救星。它提供了许多自然语言处理库的标准特性,例如:

●词性标注

●情感分析

●分类

●符号化

● n 元语法

●单词变形

● WordNet 集成

●由谷歌翻译支持的语言翻译和检测

●单词和短语频率

●解析

●拼写纠正

●通过扩展添加新的模型或语言

它附带了全面的教程,使新的学习者的学习曲线相对平滑。

资源-

结论

与任何系统的交互都是基本的行为之一,应该始终关注于让这个过程对用户来说尽可能的无缝。随着对话系统逐渐成为标准,我们的解决方案需要识别我们的日常语言。自然语言处理使我们能够为计算机简化这一点,并创造出比今天更智能的下一代解决方案。在这个不断变化的世界中,Python 已经证明了自己有足够的能力来适应、创新和交付解决方案,以解决过去困扰我们的各种现代计算问题。

其他来源—

我希望这篇文章对你有用!如果您有兴趣了解更多信息,以下是附加资源:—

[## 自然语言处理很好玩!

计算机如何理解人类语言

medium.com](https://medium.com/@ageitgey/natural-language-processing-is-fun-9a0bff37854e) [## 🚀Python 中的自然语言处理速度快 100 倍

如何利用空间&快速自然语言处理的一点技巧

medium.com](https://medium.com/huggingface/100-times-faster-natural-language-processing-in-python-ee32033bdced) [## 用于可解释机器学习的 Python 库

4 个用于更好地可视化、解释和诠释模型的库

towardsdatascience.com](/python-libraries-for-interpretable-machine-learning-c476a08ed2c7) [## 数据科学的 10 大 Python 库

为您的数据科学探索提供一些很酷的帮助!

towardsdatascience.com](/top-10-python-libraries-for-data-science-cd82294ec266)

关于作者

克莱尔 D 。在digital ogy是一个内容制作者和营销人员。这是一个技术采购和定制匹配市场,根据全球各地的特定需求,将人们与预先筛选的&顶尖开发人员和设计师联系起来。连接DigitalogyonLinkedinTwitterinsta gram**

Python 列表理解

原文:https://towardsdatascience.com/python-list-comprehension-711330271401?source=collection_archive---------26-----------------------

Python 列表终极指南!

成为列表理解专家

列表理解是处理 Python 列表时最强大的特性之一。这个功能已经触手可及。不需要导入任何库或模块,因为列表理解是 Python 的一个内置特性。

图片由约书亚·索蒂诺Unsplash 上拍摄

如何写列表理解

List Comprehension 可用于创建仅在一行中包含限制(用数学语句编写)的列表。除此之外,列表理解可以用来从另一个列表中创建一个新列表。

列表理解语法很容易理解,别担心,它很简单。做列表理解,需要先做一个方括号[]。在括号内,您需要使用 for 关键字,后跟一个或多个您选择的子句。这里的表达可以是任何东西,你可以倾注你的创造力。

基本语法

[**expression** for **element** in **list** if **conditional**]

以上列表理解等同于:

for **element** in **list**:
    if **conditional**:
        **expression** #appends the resulting element to the list

例子

当然,我会给你提供一些例子!否则这篇文章就不完整。我将从最简单的开始,继续讨论更高级的应用程序。

生成新列表

1.制作一个由前 5 个自然数组成的新列表。

ls = [i for i in range(1, 6)] #ls = [1, 2, 3, 4, 5]

2.制作前 5 个偶数自然数的新列表。

ls = [i for i in range(2, 11, 2)] #ls = [2, 4, 6, 8, 10] 

或者使用 if 来说明如何使用条件来创建新列表。

ls = [i for i in range(2, 11) if i % 2 == 0] #ls = [2, 4, 6, 8, 10]

3.列出前 5 个平方数

ls = [i**2 for i in range(1, 6)] #ls = [1, 4, 9, 16, 25]

使用我们声明的函数

列表理解的条件不需要明确地写在方括号内。你可以预先声明一个函数,然后在列表理解中调用它。在下一个例子中,我们将这样做。

4.列出 1 到 30 之间的质数

import mathdef isPrime(n):
    if n == 1:
        return False
    elif n == 2:
        return True
    elif n % 2 == 0:
        return False
    else:
        for i in range(3, int(math.sqrt(n)) + 1, 2):
            if n % i == 0:
                 return False
        return Truels = [i for i in range(1, 31) if isPrime(i)]
#ls = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

从另一个列表创建新列表

列表理解的另一个有用的用法是从另一个列表中创建一个新列表。你可以这样想,你正在从原始列表中选择满足你需求的元素。然后,将这些项目分组到一个新列表中。以下是一些例子:

5.只取原始列表中的偶数

ls = [15, 6, 1, 3, 10]result = [i for i in ls if i % 2 == 0] #result = [6, 10]

6.查找一个列表中也存在于另一个列表中的元素

ls = [15, 6, 1, 3, 10]
ls2 = [1, 2, 3, 4, 5, 6]result = [i for i in ls if i in ls2] #result = [6, 1, 3]

最后的话

Python 列表理解是您在编程工具箱中绝对需要的一项技术。它功能强大,易于在任何地方实现。过一段时间,相信我,你会习惯的。在这一点上,你可以随时轻松地使用它。如果您觉得这篇文章很有用,并且想了解更多关于 Python 的其他技巧,您可以阅读这篇文章:成为 Python“一行程序”专家

最诚挚的问候,

弧度克里斯诺

Python 中的列表理解

原文:https://towardsdatascience.com/python-list-comprehension-938ac36ad528?source=collection_archive---------56-----------------------

列表理解简介

来源

Python 提供了列表理解结构,使得定义列表、过滤列表、基于现有列表创建新列表等等变得容易。与传统的“for-loops”相比,list comprehension 是用 python 创建列表的一种更简洁、可读性更强的替代方法。在这篇文章中,我们将讨论如何使用列表理解在 python 中创建列表。我们也将在每个例子中比较列表理解方法和使用传统的“for-loops”。

我们开始吧!

首先,让我们考虑在“for-loop”中生成 1-10 的正整数列表的任务。让我们初始化一个名为“pos_list”的列表:

pos_list = []

通过在“for-loop”中迭代“range()”方法返回的生成器,我们可以将值追加到该列表中:

for i in range(1, 11):
    pos_list.append(i)

让我们打印结果列表:

print(pos_list)

这很简单。现在假设我们想生成一个偶数整数的列表。我们可以添加一个条件来检查元素是否能被 2 整除,并仅在条件为真时追加:

even_list = []
for i in range(1, 11):
    if i%2 == 0:
        even_list.append(i)

让我们打印结果:

print(even_list)

虽然使用“for-loop”可以完成工作,但列表理解提供了一种更简单的方法,可以用更少的代码获得相同的结果。首先,让我们看看如何使用列表理解来生成正整数的原始列表:

lc_pos_list = [i for i in range(1,11)]
print(lc_pos_list)

将这与我们不得不使用“for-loop”的最初三行代码进行比较:

for i in range(1, 11):
    pos_list.append(i)
print(pos_list)

现在让我们使用列表理解来生成偶数列表:

lc_even_list = [i for i in range(1,11) if i%2]
print(lc_even_list)

不过,与使用“for-loops”的五行代码相比,这只使用了两行代码:

even_list = []
for i in range(1, 11):
    if i%2 == 0:
        even_list.append(i)
print(even_list)

我们也可以使用列表理解很容易地过滤列表。让我们考虑使用“for-loop”从正整数列表中过滤小于 5 的值的任务:

pos_list_gt_5 = []
for i in pos_list:
    if i >= 5:
      pos_list_gt_5.append(i)
print(pos_list_gt_5)

使用列表理解:

lc_pos_list_gt_5 = [i for i in pos_list if i >= 5]
print(lc_pos_list_gt_5)

如你所见,我们使用了更少的代码。接下来,让我们考虑使用列表理解来迭代多个列表的任务。假设我们有一个从 1 到 10 的整数列表,和另一个从 20 到 30 的整数列表:

pos_list2 = []
for i in range(20, 30):
    pos_list2.append(i)
print(pos_list)    
print(pos_list2)

让我们编写一个“for-loop ”,对两个列表和进行迭代,并将它们的元素的乘积追加到一个新列表中:

multiply_list = []
for i, j in zip(pos_list, pos_list2):
        multiply_list.append(i*j)

print(multiply_list)

我们可以使用列表理解来执行相同的操作:

lc_multiply_list = [i*j for i,j in zip(pos_list, pos_list2)]
print(lc_multiply_list)

我们甚至可以应用条件。让我们将乘积小于 200 的元素的乘积相加:

lc_multiply_list_filter = [i*j for i,j in zip(pos_list, pos_list2) if i*j < 200]
print(lc_multiply_list_filter)

我就讲到这里,但是我鼓励你自己去研究代码。

结论

总之,在这篇文章中,我们将讨论如何使用 python 中的列表理解来构造列表。我们表明,虽然我们可以使用“for-loops”完成相同的任务,但列表理解提供了一种更容易和更易读的方法来构建列表。我希望你觉得这篇文章有用/有趣。这篇文章中的代码可以在 GitHub 上找到。感谢您的阅读!

Python 列表方法

原文:https://towardsdatascience.com/python-list-methods-fa7c53010300?source=collection_archive---------15-----------------------

Python 必须提供的列表方法的总结

马库斯·温克勒在 Unsplash 上的照片

什么是列表,什么是列表方法?

在 Python 中,列表是数据片段的集合。列表由方括号[ ]包围,每个项目由逗号(,)分隔,可以包含从零到无穷大的任何项目(或者您的计算机允许的任何数量)。字符串、数字、布尔值,甚至其他列表都可以是列表中的项目。列表是有序的和可变的(可改变的),这意味着每个项目被分配到一个特定的索引,可以排序,并有能力被改变。一旦你有了一个列表,你就可以使用所谓的“方法”来操作这个列表。像字符串方法一样,要使用列表方法,只需编写列表,后跟。【方法】()。例如,要在列表['意大利香肠','香肠','蘑菇']上运行 append() 方法,您只需编写['意大利香肠','香肠','蘑菇']。追加('洋葱');如果该列表被设置为一个变量,您应该使用 variable.append('onion ')。正如您在 append() 示例中看到的,一些方法接受所谓的“参数”,这些参数放在括号中,进一步定义了该方法将做什么。Python 语言有很多内置的方法,比如 append() ,允许你轻松地改变列表。

append()和 extend()

append() 方法允许您将另一个项目添加到列表的末尾。该方法使用一个必需的参数,这是您希望添加到列表中的项目。

Syntax: *list*.append(*item*)**toppings = ['pepperoni', 'sausage', 'mushroom']**toppings.append('onion') 
--> ['pepperoni', 'sausage', 'mushroom', 'onion']

extend() 方法类似于 append(),因为它允许您添加到列表中;但是,extend()方法允许您添加另一个 iterable(列表、元组、集合等)中的所有项。)作为单独的项目而不是一个项目添加到列表的末尾。该方法采用一个必需的参数,即 iterable。

Syntax: *list*.extend(*iterable*)**toppings = ['pepperoni', 'sausage', 'mushroom']
more_toppings = ['onion', 'bacon']**toppings.**extend**(more_toppings)
--> ['pepperoni', 'sausage', 'mushroom', 'onion', 'bacon'] *To contrast...**toppings.****append****(more_toppings)
--> ['pepperoni', 'sausage', 'mushroom', ['onion', 'bacon']]*

如上所述,当 extend()方法用于 iterable 时,iterable 中的每一项都被添加到列表中,作为不再有界的单独项。相反,当 append()方法使用 iterable 作为参数时,整个 iterable 作为一项添加到列表中。密切注意列表中的逗号和括号总是很重要的。

pop()和 remove()

pop() 方法允许您从列表中移除指定索引值处的元素。该方法可以接受一个可选参数,即您希望删除的索引的整数值——默认情况下,pop()将删除列表中的最后一项,因为默认值为-1。

Syntax: *list*.pop(*index*)**toppings = ['pepperoni', 'sausage', 'mushroom']**toppings.pop(1)
--> ['pepperoni', 'mushroom']toppings.pop()
--> ['pepperoni', 'sausage'] *If you wanted to retrieve the removed item...*extra = toppings.pop(1)
extra --> 'sausage'

像 pop()方法一样, remove() 方法允许您从列表中删除一个项目。不过,remove()方法删除列表中第一个出现的指定值。该方法使用一个必需的参数,即您希望移除的项目。

Syntax: *list*.remove(*item*)**toppings = ['pepperoni', 'sausage', 'mushroom']**toppings.remove('sausage')
--> ['pepperoni', 'mushroom']

对于 pop()和 remove(),如果参数超出范围或不在列表中,您将分别得到一个错误。

排序()和反转()

方法按照一定的标准对列表进行排序。该方法可以带两个可选参数。第一个参数是设置 reverse=Truereverse=False 。默认情况下,该参数设置为 reverse=False ,如果列表仅包含字符串,则按字母顺序排列;如果列表仅包含数字,则按升序排列。第二个参数允许您将一个 key= 设置为一个函数,如果它比 sort()方法的默认排序更复杂,您可以使用该函数来指定您希望列表如何精确排序。这可能是一个内置的 Python 函数,一个你在程序中其他地方定义的函数,或者是你写的一个内嵌的λ函数。

Syntax: *list*.sort(reverse=True|False, key=function)**toppings = ['pepperoni', 'sausage', 'mushroom']**toppings.sort()
--> ['mushroom', 'pepperoni', 'sausage']toppings.sort(reverse=True)
--> ['sausage', 'pepperoni', 'mushroom']toppings.sort(reverse=True, key=lambda x: len(x))
--> ['pepperoni', 'mushroom', 'sausage']
** Sorted in reverse order by length of the topping name* **prices = [1.50, 2.00, 0.50]**prices.sort(reverse=False)
--> [0.50, 1.50, 2.00]prices.sort(reverse=True)
--> [2.00, 1.50, 0.50]  **pies = [['bacon', 'ranch'], ['sausage', 'peppers']]**pies.sort(reverse=True)
--> [['sausage', 'peppers'], ['bacon', 'ranch']]
** Sorts iterators by their first value*

方法只是颠倒了列表中条目的顺序。该方法不带任何参数

Syntax: *list*.reverse()**toppings = ['pepperoni', 'sausage', 'mushroom']**toppings.reverse()
--> ['mushroom', 'sausage', 'pepperoni'] **prices = [1.50, 2.00, 0.50]**prices.reverse()
--> [0.50, 2.00, 1.50]

计数()

方法的作用是:返回一个列表中指定条目出现的次数。该方法接受一个必需的参数,这是您希望计算其计数的项目。如果您希望找出哪些项目在列表中出现了不止一次,这种方法会很有用。

Syntax: *list*.count(*item*)**toppings = ['pepperoni', 'sausage', 'mushroom', 'sausage']**toppings.count('sausage')
--> 2toppings.count('pepperoni')
--> 1toppings.count('bacon')
--> 0

索引()

index() 方法返回指定项目第一次出现的索引。该方法使用一个必需的参数,这是您希望查找其索引的项目。如果该项目不在列表中,您将得到一个错误。

Syntax: *list*.index(*item*)**toppings = ['pepperoni', 'sausage', 'mushroom', 'sausage']**toppings.index('mushroom')
--> 2toppings.index('pepperoni')
--> 0

插入()

方法的作用是:将一个指定的条目插入到一个指定索引的列表中。该方法采用两个必需的参数——您希望插入值的整数索引和您希望插入的项目。

Syntax: *list*.insert(*index*, index)**toppings = ['pepperoni', 'sausage', 'mushroom']**toppings.insert(1, 'onion')
--> ['pepperoni', 'onion', 'sausage', 'mushroom']

复制()

copy() 方法只是返回你的列表的一个副本。该方法不带参数

Syntax: *list*.copy()**toppings = ['pepperoni', 'sausage', 'mushroom']**toppings**2** = toppings.copy()
toppings**2** --> ['pepperoni', 'sausage', 'mushroom']

清除()

clear() 方法只是从一个列表中删除所有的条目,留下一个空列表。该方法采用无参数

Syntax: *list*.clear()**toppings = ['pepperoni', 'sausage', 'mushroom']**toppings.clear()
--> []

仅此而已。有了上述这些方法,您应该可以对 Python 列表执行所需的操作。更多信息和例子,请务必查看 w3schools 列表

祝你编码愉快,一定要看看我下面关于 Python 字符串方法的博客!

[## Python 字符串方法

Python 中最常用的字符串方法的总结

towardsdatascience.com](/python-string-methods-7ac76ed7590b)

参考资料:

[## Python 列表/数组方法

Python 有一组内置的方法,可以用在列表/数组上。注意:Python 没有对…的内置支持

www.w3schools.com](https://www.w3schools.com/python/python_ref_list.asp)

Python:蒙特卡洛遇上体育分析

原文:https://towardsdatascience.com/python-monte-carlo-meets-sports-analytics-12cf97f1a1d?source=collection_archive---------49-----------------------

使用模拟来收敛棘手的概率分布

信用:Pixabay

大约一个月前,当我在研究生院的最后一个学期和找工作的时候,我面试了一家体育分析公司。我的背景是商业分析,特别是在新颖的商业应用中使用 NLP、网络分析和推荐系统。总而言之,我不是理想的候选人。

在进入任何累人的数据科学面试问题之前,我接受了一次带回家的测试;这并不令人吃惊。许多公司知道这个过程可能成功也可能失败。因此存在一些固有的“我们只是在浪费时间”的风险。把测试带回家是公司消除这种风险的好方法;这对每个人都很好,除了求职者。如果你的提交被认为不令人满意,公司已经在你身上浪费了比预期更多的时间,并将立即转向下一个候选人。为您提供高质量的反馈是数据科学团队不必要的负担。在他们的辩护中,一些角色得到了成百上千的申请者。指导每个人如何做得更好是不可行的。尽管如此,作为一名数据科学家,执行大量的带回家测试并不一定能提高你的水平。让你进步的是从你的错误中学习——这是你的责任(也是你自己的责任)。)

我搞砸了带回家的考试,花了几个小时绞尽脑汁思考我本可以做得更好的地方,然后完全搁置了这个话题。直到昨晚我突然想到一个主意!不过我言过其实了,还是讨论一下面试问题吧。

在这次采访中,我需要(A)重现当前的 NBA 彩票概率,( B)为修改后的彩票产生新的概率。

NBA 彩票的运作方式如下:球队按常规赛表现排名,最好的球队排在最后,最差的球队排在第一。我的意思是,在有限数量的球队被选为第一,第二,…第 n 选秀之后,剩下的球队将按照他们常规赛表现的(相反)顺序(最好的最后,最差的第一— 希望让接下来的赛季更有趣。)在实际的 NBA 选秀中,从 14 支球队中选出 4 支球队。在提议的草案系统中,必须从 16 支队伍中挑选出 5 支队伍。

挑选队伍的方法是从彩票机中取出四个球,并确定球的独特组合来自哪个队伍。然后球被重新插入(该组合已被使用,但这些相同的球参与了许多更独特的组合网尚未检索)。)每个团队都分配到不同数量的组合。最差的团队组合最多,而最好的团队组合最少。

我完全不知道如何开始。我的统计知识较少植根于概率论,更多地与机器学习相结合。所以我做了一些谷歌搜索,发现了一篇 2020 平方的文章,以确定性的方式解决了离散概率分布。

[## NBA 选秀彩票的概率是如何构建的

9 月 28 日,NBA 理事会批准了对 NBA 选秀抽签系统的修改。这些变化是…

squared2020.com](https://squared2020.com/2017/09/30/how-nba-draft-lottery-probabilities-are-constructed/)

注意我说确定性的时候。这被证明是我心中的一个定位点。我决心理解这些方法、代码等,并复制我自己的方法。如果你跟随教程,你会注意到第一轮的选择只是,选择的概率(组合数除以总组合数。)第二轮的条件是任何其他队伍先被选中。并且这个过程在前四个选秀中重复。然而,一旦我们到了第五轮,我们不再选择队伍,而是简单地将剩下的队伍按照他们当前的顺序添加到被选择的队伍中。(我从来没有通过第四轮选秀!)

确定性地解决这个问题是一场噩梦,也是对一个人掌握概率论的真实证明。这就是我没有被选中参加下一轮面试的原因。

大约一个月后,我坐在沙发上,突然想到——也许我应该用蒙特卡罗方法从分布中取样?我暂停了在网飞的冒险,开始写代码。结果呢?这是可行的,当彩票设计发生变化时,它比确定性地写这个更具可扩展性。

我的方法

Python 非常适合生成随机数。事实上,您可以从给定概率分布的池中随机选择一个值。给定分配给每个团队的组合数量,确定它们的概率是微不足道的。

我定义了两个不同的函数,试验模拟。选拔赛是抽签的一次试运行,根据他们的选择概率选出四名候选人,剩下的队伍被添加到名单中。在我的设计中,当一个给定的团队被选中时,我将他们的值编入索引,并从 pool 和 dist 变量(列表)中与该索引对应的元素中删除。但是,一旦从 dist 变量中删除了一个概率,它的总和就不再是 1。我没有考虑到这一点,但很高兴地得知 python 的随机包将根据需要为您调整这一点!

模拟,有点棘手。给定提供的回合数,试验函数将被执行 x 次,结果将被附加到一个列表中。您将得到一个嵌套列表,其中外部列表包含 x 个元素,每个 x 元素都是长度为 14 的试运行。在这一点上,我们使用列表理解遍历排名的每个位置。我们不是查看 1000 个元素的嵌套列表(每个元素包含 14 个值),而是创建 14 个元素的嵌套列表(每个元素包含 1000 个值。)这是真正的秘制酱料。第一份这样的名单将包含第一次选秀被选中的每支球队。第二个这样的列表将包含第二次选秀被抽样的每支球队。诸如此类。

使用 Counter 函数(来自 collections),可以得到一个的计数,哪个队在哪个地方呆了多少次?“从这里开始,只需将每个计数除以总和(模拟的总数)就可以得到每个位置的概率分布。你会注意到这个矩阵是面向列的,而 NBA 官方的彩票概率分布是面向行的。我们只需将嵌套列表传递给 numpy 并进行转置。嘣。完成了。但愿我上个月就想到了这一点!

在下面的最终代码中,我注释掉了常规赛变量,并在每行下面定义了一个建议的系统变量。(实际上,它在建议的系统下找到了分布。)经过 5,000,000 次迭代,它收敛于精确值!

结果(提示,与维基百科比较)

感谢阅读!如果你认为我的内容没问题,请订阅:)

Python 多线程与多处理

原文:https://towardsdatascience.com/python-multi-threading-vs-multi-processing-1e2561eb8a24?source=collection_archive---------18-----------------------

基准测试并发任务执行的两种方法:Python 中的多线程和多处理。

克里斯·里德在 Unsplash.com 的照片

当处理大量要执行的任务时,人们宁愿不要顺序执行任务,因为这是一个漫长、缓慢且相当无聊的过程。相反,我们想要的是我们的程序同时启动所有的任务,这样它们可以并排完成。

并行性或并发任务执行并不是一个新概念,大多数主流语言都支持它。Python 也不例外,它确实提供了一个非常简洁的模块,可以很容易地用来以并行或并发的方式运行任务。我在这篇文章中的目标是提供关于 python 中多线程和多处理如何工作的简要概述,并且我将对两者的性能进行基准测试。本文将涵盖以下主题:

  • 并发和并行的区别。
  • Python 中的多线程。
  • Python 中的多处理。
  • 多线程和多处理的基准测试。
  • 什么样的节目用哪种方法比较好。

并发和并行的区别

并发性和并行性是两个经常被混淆的术语,它们虽然相同,但却有着非常不同的含义。

并发本质上被定义为同时处理大量工作或同一程序的不同工作单元。

在编程环境中,同一程序的不同部分被分配给处理器的不同内核,这些内核独立执行每个部分并相互通信,从而同时完成更多的工作。

另一方面,并行性可以简单地定义为

同时做同一程序的大量工作以加快执行时间。

在编程环境中,同一程序的不同部分并行执行,并且每个部分的执行同时发生,因此加快了程序的执行时间。

Python 中的多线程

在 Python 中,我们可以使用 concurrent.futures 模块实现多线程的功能。它为启动异步任务提供了一个高级 API。 ThreadPoolExecutor 类提供了一个启动和管理线程的接口。

import concurrent.futures
with concurrent.futures.ThreadPoolExecutor() as executor:
    executor.map(function_name, iterable)

我们用上下文管理器创建 executor 对象,并在我们想要并行执行的方法上调用 map 函数。 map 函数将为输入 iterable 的每个值创建一个线程。

Python 中多线程的工作原理:

尽管我们说 python 支持多线程,但是幕后发生的事情却非常不同。在 python 中,每个进程都在一个内核上执行。因此,当我们创建同一进程的多个线程时,每个线程都在同一内核上执行,因此共享资源和内存空间。为了防止一个线程因为共享相同的资源而改变另一个线程的执行结果,Python 引入了“全局解释器锁”的概念。

本质上,它一次只允许一个线程使用共享的内存空间和资源,并在线程之间进行智能上下文切换,因此没有线程可以改变其他线程的工作。因此,在 python 中使用多线程的并行性是一个相当牵强的术语,因为我们并没有以这种方式实现真正的并行性。

Python 中的多重处理

在 Python 中,我们可以使用同一个 concurrent.futures 模块实现多处理的功能。 ProcessPoolExecutor 类提供了一个启动和管理多个进程的接口。

import concurrent.futures
with concurrent.futures.ProcessPoolExecutor() as executor:
    executor.map(function_name, iterable)

就像在多线程中一样,我们用上下文管理器创建 executor 对象,并在我们想要并行执行的方法上调用 map 函数。 map 函数将为输入 iterable 的每个值创建一个过程。

Python 中的多处理是如何工作的:

在多处理的情况下,每个进程在不同的内核上运行,具体取决于机器上的内核数量。因此,在进行多重处理时不需要 GIL,因为所有进程都是独立的。因此,多处理实际上为我们提供了 python 中的实际并行性。但它只有在正确的情况下才会起作用。如果我们有 12 个任务和一个 4 核机器,那么每个核心一个进程将是理想的情况,给出我们想要的真正的并行性。如果我们产生的进程多于内核的数量,每个进程将竞争资源,这将导致上下文切换,从而导致并发性而不是并行性。

Python 中多线程和多处理的基准测试

在这一节中,我将分享我通过两个不同的实验获得的结果,以确定哪种并发执行方法更好,以及适合哪种任务。

大体上,我们将要执行的任务分为涉及 CPU 上大量计算的计算密集型任务或涉及大量 I/O 操作的 I/O 密集型任务,例如在目录之间移动文件或发出大量 HTTP 请求。

I/O 密集型任务

以下是我对 I/O 密集型任务的实现。

这个方法执行程序中的 I/O 操作。我们得到一个图像文件名的列表,并一次一个地将它传递给这个方法。它只是打开文件,执行灰度转换,创建图像的缩略图,并将其保存在已处理的目录中。

我们首先通过简单的串行执行来执行这个方法,然后通过多线程和多处理来执行。

计算密集型任务

以下是我对计算密集型任务的实现。

调用此方法时,计数变量会随着 9⁹.范围内的每个值而递增

同样,我们首先通过简单的串行执行,然后通过多线程,再通过多处理来执行这个方法。对于每个场景,compute _ intensive _ process方法被调用 4 次。

基准测试结果

在对 I/O 密集型操作和计算密集型操作执行上述方法后,获得了以下结果:

正如我们所见,在 I/O 密集型操作中,串行执行的性能最差,其次是多处理,多线程执行的性能次之。尽管我们说过多线程实际上并没有实现真正意义上的并行,但在 I/O 操作的情况下,我们并没有使用 CPU 进行大量计算,而是发出 I/O 请求并等待响应。

为什么多重处理在 I/O 操作的情况下性能很差?

原因是新进程的产生本身就是一个昂贵的操作,因此增加了创建和执行多个任务的开销。但它的性能仍然优于串行执行。

然而,在计算密集型操作的情况下,我们可以清楚地看到,多处理提供了最佳性能,令人惊讶的是,串行执行提供了第二好的性能,而多线程提供了最差的性能。

如前所述,单个进程在单个内核上执行,因此以并发或并行方式执行。

为什么多线程的性能不如串行执行?

这是因为一次只执行一个线程,线程之间的上下文切换会增加开销,从而增加总开销,降低整体性能。例如,如果串行执行需要 100 秒来完成 5 个任务,那么以串行方式执行的多线程需要 100 秒+上下文开销来完成同样的 5 个任务。

结论

正如我们在上面看到的,多线程和多处理在完成特定类型的任务时都有自己的优势。对于涉及大量 I/O 操作的任务,最好使用多线程;对于涉及大量 CPU 计算的任务,最好使用多线程。

我的这个特殊用例的完整项目可以在我的 GitHub 简介这里找到。

[## furqanshahid 85-Python/Python-多线程-Vs-多线程处理

在本模块中,我们将对 python 的多线程和多处理进行基准测试。我们正在进行 I/O 操作和计算…

github.com](https://github.com/furqanshahid85-python/Python-Multi_Threading-Vs-Multi_Processing)

如果你喜欢这篇文章,请在 medium 上关注我,看看我的其他精彩文章。就这些了谢谢:)。

Python Numba 或 NumPy:理解区别

原文:https://towardsdatascience.com/python-numba-or-numpy-understand-the-differences-b448dabd5b5b?source=collection_archive---------7-----------------------

有例子支持的简短描述。

帕特里克·托马索在 Unsplash 上的照片

N umPy 和 Numba 是两个很棒的用于矩阵计算的 Python 包。这两种方法都可以有效地处理多维矩阵。在 Python 中,列表的创建是动态的。向这样的列表追加值将动态地增加矩阵的大小。NumPy 的工作方式不同。它以固定的大小构建数组对象。添加或删除任何元素都意味着在内存中创建一个全新的数组。在本文中,我们正在寻找一种有效的对象结构来解决一个简单的问题。

要讨论的不仅是如何创建数组对象,还有如何对这些数组应用科学操作,尤其是扫描数组。当我们对它们应用一些昂贵的逻辑时,性能是拥有这些库的主要动机。例如,当我们开发机器学习(ML)模型时,尤其是在生产环境中,我们会花费合理的时间来优化生成训练数据的代码,应用任何所需的数据转换或任何其他 ETL 操作。使用一些编译过的编程语言如 C 或 Fortran 是理想的,但是这需要我们到处构建一些包装器来将管道返回到 Python。

在 Python 中实现数组

让我们举一个简单的例子:首先,我们将用 python 创建一个包含一千万个值的简单列表。较大的数字会很容易地突出性能上的差异。

# We need to import the random package to fillup the array with some random values.import random
array = []

我用的是 IPython 如果你是在 Jupyter 笔记本上运行这段代码,那么我推荐使用内置的 magic (time)。

%%time
for i in range(0,10000000):
    val = random.randint(0,1000)
    array.append(val)

计算频率

让我们在这个列表中搜索有多少行包含值 999?

%%time
freq = 0 
for value in array: 
    if value == 999: 
        freq = freq + 1

我的机器用了 461 毫秒,这个函数找到了值 999 的 10184 个实例。现在让我们看看如何使用 NumPy 数组完成同样的工作。

import numpy as np# We use the same list created earlier: 
np_array = np.array(array)
# To get a sense of the size of the bumpy array, simply call up the function 'shape'
print('The size of the numpy array: ', np_array.shape)

搜索 NumPy 数组中包含值 999 的行只有一行代码:

%%time
result = np.where(np_array == 999)

除了编写一些指令之外,我的机器花了 12.6 ms 来完成与列表数组相同的工作。

请注意,NumPy 数组的索引机制类似于任何普通的 Python 列表。

现在,我们将通过对数组值引入一些数学运算来使这个例子更有趣一些。首先,我们将从原始列表中构造三个向量(X,Y,Z ),然后使用 NumPy 做同样的工作。

def apply_operation_list(array): 
    # We need to build an X vector from the original array
    # The math operations in this function represents some random logic.
    x_array = [] 
    for array_v in array: 
        x_array.append(array_v * 2)

    # Building the Y vector
    y_array = []
    for array_v, x_array_v in zip(array, x_array): 
        y_array.append(array_v + x_array_v)

    # Building the Z vector
    z_array = []
    for array_v, x_array_v, y_array_v in zip(array, x_array, y_array):
        if x_array_v == 0: 
            z_array.append(0)
        else: 
            z_array.append((array_v - x_array_v ) + y_array_v)

    return x_array, y_array, z_array%%time
x_array, y_array, z_array = apply_operation_list(array)

在列表上应用操作花费了 3.01 秒。

让我们用 Numpy 定义同样的函数:

def apply_operation_numpy(array): 
    # We need to build an X vector from the original array
    # The math operations in this function represent some random logic.
    x_array = array * 2

    # Building the Y vector
    y_array = array + x_array

    # Building the Z vector
    z_array = ( array - x_array ) + y_array

    return x_array, y_array, z_array

使用 Numpy,只用了 132 ms。

数字巴

原始照片由 Faris MohammedUnsplash 上拍摄

Numba 与 Python 配合得非常好,它给了你使用你最喜欢的数学库的特权,但是要编译成本机指令[2]。使用 Numba 很简单,不需要您改变编写函数的方式:

# Loading the Numba package
# Jit tells numba the function we want to compile
from numba import jit

请注意,与上面定义的 Numpy 函数相比,我们需要做的所有更改。

[@jit](http://twitter.com/jit)
def apply_operation_numba(array): 
    # We need to build an X vector from the original array
    # The math operations in this function represents some random logic.
    x_array = array * 2

    # Building the Y vector
    y_array = array + x_array

    # Building the Z vector
    z_array = ( array - x_array ) + y_array

    return x_array, y_array, z_array

使用 Numba,计算三个向量只需要 71.5 毫秒。

选哪个?

“NumPy 是使用 Python 进行科学计算的基础包。其中包含:一个强大的 N 维数组对象、复杂的(广播)函数、集成 C/C++和 Fortran 代码的工具、有用的线性代数、傅立叶变换和随机数功能”[1]

NumPy 是一个巨大的容器,可以压缩向量空间并提供更有效的数组。最显著的优势是那些容器在执行数组操作时的性能。

另一方面,Numba 旨在提供镜像 python 函数的本机代码。Python 可以被看作 Numba API 代码的包装器。根据我的经验,每当已经提供的 Numpy API 不支持我们在向量上执行的操作时,我们就使用 Numba。如果实现的定制函数在我们的环境中不够快,那么 Numba 可以帮助我们在 Python 解释器中生成函数。这也是来自 Numba 文档的建议。

前面提供的例子没有显示出差异有多大?这是真的,因为我们只搜索单个值的频率。让我们通过计算一列中所有值的频率来重复这个实验。

在 Python 中,避免嵌套循环(O^2)的最有效方法是使用函数 count() 。只需一行代码,我们就可以计算整列的频率:

%%time
count = {x:x_array.count(x) for x in x_array}

但是,根据您的处理能力,这个函数可能需要几个小时来完成 1000 万条记录。接下来让我们看看 Numpy 能提供什么:

%%time
x_elements_np, x_counts_np = np.unique(x_array_np, return_counts=True)

使用 Numpy 计算一个百万值列的频率需要 388 毫秒。一个大的性能救济!请注意,该函数仅通过计算不同值的频率来增强。这个例子说明了在大数据环境中使用嵌套循环是多么不现实。

直到最近,Numba 还不支持 np.unique()函数,但如果与 return_counts 一起使用,您仍然不会得到任何好处。这只是为了说明有时 Numpy 可能是最好的选择。

最后,接下来的两个图显示了使用不同数据对象结构的运行时性能。x 轴代表数据大小从 10,000 行到 10 亿行的增量。

下图显示了 Numby with Numba 库的性能。请注意,该数字可能因数据大小而异。图中的数字表示重复实验五次的平均值。

更多示例

计算奇异值分解

频率示例只是一个可能不足以给人留下深刻印象的应用,所以让我们选择 SVD 作为另一个示例。SVD 是一种众所周知的无监督学习算法。它允许我们将一个大矩阵分解成多个小矩阵的乘积。奇异值分解在最大似然法中有许多应用,用于降低维数。这里是一篇推荐文章,供进一步阅读。

下面的例子只使用了两个维度(列),行数与前面的例子相同。

from scipy.linalg import svd# We will consider in this example only two dimensions. 
# m x 2 
# U: m x r 
# s: Diagonal matrix r x r
# VT: n x r
U, s, VT = svd(array_np[:, 0:2])
Sigma = np.zeros((array_np.shape[0], 2))
Sigma[:2, :2] = np.diag(s)

如果您尝试运行该代码,您可能会得到与下面的失败类似的错误:“ValueError:需要太大的工作数组—无法使用标准的 32 位 LAPACK 执行计算。”。这是因为 lapack-lite 的内部实现使用int作为索引。对于像我们的数组这样的大小,它肯定会导致溢出。我们要么减小向量的大小,要么使用另一种算法。如果 SVD 函数与 Numba 一起使用,我们也不会得到任何明显的好处,因为我们调用的是 LAPACK SVD 函数。

矩阵乘法

矩阵乘法是另一个展示 Numba 如何有助于提高处理时间的例子。即使没有 Cuda,我们也可以实现更好的性能。让我们一步步来看这个例子。正如我们之前所做的,我们将使用 Python list 实现一个函数。

def matrix_multiplication(A,B):
    row, col_A = A.shape
    col_B = B.shape[1] result = np.zeros((row,col_B)) for i in range(0,row):
        for j in range(0,col_B):
            for k in range(0,col_A):
                result[i,j] += A[i,k]*B[k,j] 
    return result

对于 1000 万行,列表处理乘法运算相当快。运行时间只有 1 分 7 秒。使用 Numpy,完成同样的工作需要 95 秒。

def matrix_multiplication_numpy(A,B):
    result = np.dot(A,B)
    return result %%time
result = matrix_multiplication_numpy(array_np, array_np)

现在用 Numba 代替 Numby,我们用一个简单的函数减少了高成本的乘法运算,结果只用了 68 秒,减少了 28%的时间。

[@jit](http://twitter.com/jit)
def matrix_multiplication_numba(A, B, result):
    for i in range(result.shape[0]):
        for j in range(result.shape[1]):
            tmp = 0.
            for k in range(A.shape[1]):
                tmp += A[i, k] * B[k, j]
            result[i, j] = tmp

下图显示了使用 Python 列表、Numby 和 Numba 库的矩阵乘法的性能。

本出版物中提供的示例已在 15 英寸 2018 MacBook Pro 上运行,容量为 16 GB,使用 anaconda 发行版。这些例子中使用的代码可以在 my Github repo 中找到。使用 GPU 环境可以提高性能,但在这次比较中没有考虑到这一点。

参考

NumPy 官方网站,可在线访问 https://numpy.org

Numba 官方网站,可在 http://numba.pydata.org在线访问

使用 Wordbatch Apply 的 Python 单行分布式加速

原文:https://towardsdatascience.com/python-one-liner-distributed-acceleration-with-wordbatch-apply-efccecec22dd?source=collection_archive---------15-----------------------

使用 Wordbatch Apply-decorator 通过分布式 Map-Reduce 处理任何函数

Python 单行分布式加速

并行分布式 Python

由于半导体制造工艺的进步,计算硬件正在经历一个快速发展的时期,64 核消费 CPU 和 80 核服务器 CPU 将于今年上市。在经历了十年的停滞发展后,这给 CPU 性能带来了质的飞跃。

在 Python 程序中利用这种增加的并行计算能力最好是使用多处理库,因为全局解释器锁(GIL)使高效的线程级并行变得复杂。然而,多处理限于单个计算节点,并且设置多处理任务需要为要并行化的每个任务提供额外的样板代码。

最近的分布式 Python 处理框架,如 RayDaskSpark 支持 Python 进程和数据的分布,很像多处理,但跨越了一个工人网络。Wordbatch 是一个工具包,支持将这些框架用作可交换的分布式后端。它提供了 orchestrator 类批处理程序,该程序将处理任务的管道分布在分布式后端或本地后端,如多处理或韩一菲。最基本的管道是 Apply-class,它接受一个输入函数,并在后端将其作为单个 Map-Reduce 操作运行。

简单的分布式 Map-Reduce 与应用装饰器

Apply 是一个最小的处理管道,它接受一个函数或方法,并将其作为对任何可迭代数据(如列表、Numpy 数组、Pandas 系列或 DataFrame)的 minibatch Map-Reduce 操作来执行。从 Wordbatch 1.4.4 开始,你可以导入一个装饰器包装器来应用,称为 decorator_apply,或者简单地导入为 Apply。Apply 可以用作 Python“@”装饰器,或者在函数上调用它来分发,就像本文中所做的那样。简单来说:

**from** wordbatch.pipelines **import** decorator_apply **as** apply
results = apply(function_or_method)(iterable_data)

这为列表操作产生了一个单行的 Map-Reduce 约定,可以方便地用于整个计算密集型 Python 程序,特别是人工智能和数据科学管道。

上面的例子使用默认的 Python 多处理后端,所有可用的内核都在计算节点上。我们可以通过传递一个已经用后端初始化的批处理程序对象来选择后端,也可以选择传递用于分布式处理的后端句柄。使用 Ray,这将按如下方式完成:

**import** ray
ray.init(redis_address=IP+":"+PORT) # Or ray.init() for local-only
batcher = Batcher(backend="ray", backend_handle=ray)results = apply(function_or_method, batcher)(iterable_data)

通过更改 Batcher 的 backend 和 backend_handle 参数,可以很容易地选择后端。事实上,后端是可交换的,因此只需在处理运行之间更改 batcher.backend 和 batcher.backend_handle 属性就可以更改调度程序。

Apply 最初是作为一个基本的最小管道模板添加到 Wordbatch 的。然而,如熟悉 Map-Reduce 框架的人所知,整个数据处理流水线可以作为大型计算节点网络上的 Map-Reduce 操作来执行。除了这篇博文中展示的特性工程管道,Apply 的其他实际任务包括分发:

  • 通过数据/参数子集的人工智能模型训练
  • 基于数据/参数子集的人工智能模型推理
  • 按输入子集划分的一般计算密集型函数
  • 通过超参数配置进行超参数优化

以下代码片段改编自基准测试脚本,该脚本使用不同的后端调度程序运行基准测试。这些例子可以很容易地调整为现实世界的用例。

加速全球和本地功能

作为第一个例子,我们可以将一个全局函数“normalize _ text”分布在一个可迭代的文本字符串上,并将结果作为列“text”存储在数据帧“df”中:

**def** normalize_text(text):
   text= **" "**.join([word **for** word **in** re.compile(**'[\W+]'**).sub(**" "**,text.lower()).strip().split() **if** len(word)>1])
   **return** textdf[**'text'**] = apply(normalize_text, batcher)(texts)

对全局函数和变量的引用会自动发送到每个新进程。这使得所有必需对象的序列化变得微不足道,但是对于较长的程序,留在全局命名空间中的不必要变量会增加并行化开销。局部函数的用法和全局函数一样,但是标准的 Python 多处理不会序列化局部函数。多重处理的韩一菲分叉和分布式后端将处理本地功能。

Lambda 函数和对象方法

其他类型的函数也同样容易加速,只是有一些小问题。我们可以加速一个λ函数:

df[**'first_word'**] = apply(**lambda** x: x.split(**" "**)[0], batcher)(df[**'text'**])

就像本地函数一样,lambda 函数不是由标准 Python 多处理序列化的。有很多解决方法,比如使用韩一菲,或者只是将 lambda 函数定义为一个全局函数。

一个对象方法可以用同样的方式加速:

**from** nltk.stem.porter **import** PorterStemmer
stemmer= PorterStemmer()df[**'first_word_stemmed'**] = apply(stemmer.stem)(df[**'first_word'**])

使用对象方法时,方法调用不会对原始对象进行更新,因为该方法是在并行副本上执行的。如果需要更改,Apply 的基本用法是不够的。在许多情况下,一种变通方法是使用更复杂的管道,既处理已处理的列表数据,又更新并行化的对象。

熊猫集团运营部

最后,Pandas GroupBy 聚合是一种非常常见的数据处理操作,经常形成人工智能和数据科学处理管道中的瓶颈,例如特征工程任务。这里有几种使用 Apply 的方法,例如:

batcher.minibatch_size = 200
group_ids, groups = zip(*df[[**'first_word_stemmed'**, **'text'**]].groupby(**'first_word_stemmed'**))
res = apply(**lambda** x: x[**'text'**].str.len().agg(**'mean'**), batcher)(groups)
df[**'first_word_stemmed_mean_text_len'**] = df[**'first_word_stemmed'**].map(
   {x: y **for** x, y **in** zip(group_ids, res)})

使用 GroupBy 的组 id 将聚集结果映射回原始数据帧。为了清楚起见,操作扩展为三行。Batcher 的 minibatch 大小从默认的 20000 修改为 200,因为与原始 DataFrame 行相比,需要迭代的组数量相对较少。

任何按组并行化的 GroupBy 操作的一个问题是,真实数据的组分布不均匀,通常遵循幂律分布,大多数组只有很少的成员。这通常会抵消并行化带来的任何好处,因为与收益相比,简单的按组操作会导致较大的并行化开销。一个简单的非最优解决方案是通过散列和宁滨来绑定分组变量,以产生一个不太稀疏的分组变量,然后在每个绑定的 GroupBy 内进行原始的 GroupBy 操作,如下所示:

batcher.minibatch_size = 10
df[**'first_word_stemmed_hashbin'**] = [hash(x) % 500 **for** x **in** df[**'first_word_stemmed'**]]
_, groups = zip(*df[[**'first_word_stemmed'**, **'text'**, 
**'first_word_stemmed_hashbin'**]].groupby(**'first_word_stemmed_hashbin'**))
res = pd.concat(apply(**lambda** x: x.groupby(**'first_word_stemmed'**).apply(**lambda** z: z[**'text'**].str.len().agg(**'mean'**)), batcher)(groups))
df[**'first_word_stemmed_mean_text_len'**] = df[**'first_word_stemmed'**].map(res)

与未绑定的并行 GroupBy 相比,“first_word_stemmed”变量现在是在每个小批内处理的未绑定变量,而“first_word_stemmed_hashbin”是将数据拆分到分布式小批中的已绑定分组变量。这里,500 个箱用于宁滨变量,批次的小批量大小减少到 10,因为每个小批量现在平均有更多的数据。这些的最佳值取决于数据。

迷你批处理加速选项:缓存和 Numba 矢量化

Apply 还提供了通过缓存和矢量化实现每迷你批次加速的基本选项。Cache 使用所选大小的 functools.lru_cache 来存储每个已处理的 minibatch 中的结果,并且应该在有多个重复值并且每个函数的计算成本都很高时使用。矢量化使用函数的 Numba 矢量化,可以在输入和输出变量类型事先已知的情况下使用。

以词干提取为例,可以简单地添加缓存:

df[**'first_word_stemmed'**] = apply(stemmer.stem, cache=1000)(df[**'first_word'**])

运行加速选项、后端和任务的组合揭示了一些需要解决方法的边缘情况。例如,用 lru_cache 缓存不能直接处理数据帧,因为数据帧是可变的,而 lru_cache 只接受不可变的输入数据。

对于基本情况,支持使用 Numba 加速小批量处理。下面显示了一个具有两个输入变量列的示例:

**def** div(x, y):
   **return** 0 **if** y==0 **else** x / ydf[**'len_text'**] = df[**'text'**].str.len().astype(int)
df[**'len_text_normalized'**] = df[**'text_normalized'**].str.len().astype(int)#Without Wordbatch, plain zip comprehension
df[**'len_ratio'**] = [div(x, y) **for** x, y **in** zip(df[**'len_text'**], df[**'len_text_normalized'**])]#With Batcher, no Numba
df[**'len_ratio'**] = apply(**lambda** x:div(*x), batcher)(df[[**'len_text'**, 
**'len_text_normalized'**]].values)#With Batcher and Numba vectorization
df[**'len_ratio'**] = apply(div, batcher, vectorize=[float64(int64, int64)])(df[[**'len_text'**, **'len_text_normalized'**]].values)

这里,用于向量化“div”函数的 Numba 变量类型被定义为参数“vectorize=[float64(int64,int 64)”]。Float64 定义输出变量类型,int64s 定义输入变量类型。Batcher 的输入通过从 DataFrame 列“len_text”和“len_text_normalized”中选择二维 Numpy 数组来构造。

Numba 的主要警告是,它仍然不是一个完全开发的框架,对于比这个更复杂的例子,需要很好地理解 Numba 的内部结构。例如,对数组输入进行矢量化需要 Numba guvectorize,而不是矢量化装饰器,并且需要进行一些更改。Numba 可以为数字多维数组操作提供超过原生 Python 代码的显著加速,包括使用 Cuda 的 GPU 加速。但是由于这些设置和扩展都很复杂,一个更有前途的小批量加速方法可能是使用用 C、Cython 或 Rust 等完全低级语言编写的 Python 扩展。

基准

可以将加速比与没有应用的基线函数进行比较,并与批处理程序的不同调度器后端进行比较。下面的数字是在每个后端分别运行基准脚本得到的。测试时间来自使用单个 i9–9900k CPU,具有 8 个内核和 16 个线程,所有内核均以 4.9GHz 运行。所有测试都是在来自 Tripadvisor 点评的超过 128 万行文本数据上进行的,除了 GroupBy 聚合之外,还使用了 5000 个小批量的函数。

第一个示例应用于分发全局文本规范化函数。这为每个被处理的字符串做了相对复杂的处理,所以韩一菲和射线后端的加速几乎是核心线性的,射线的加速是 6.9 倍,韩一菲的加速是 6.6 倍。

继续使用 lambda 函数分割每个 textline 的第一个单词,使用 object 方法对第一个单词进行词干处理,我们获得了较小的加速,但仍然比不使用 Wordbatch 或使用单个进程作为后端要快好几倍。对于分割,韩一菲加速了 1.8 倍,雷加速了 3.2 倍。对于词干,韩一菲是 3.1 倍,雷是 5.14 倍。这两种操作仍然相对复杂,因此尽管存在并行化开销,但还是会有所收获。

通过比较 GroupBy 平均聚合,我们得到了第一个并行化没有直接加速的例子。由于大多数分布式组只有几个成员,并且每个组的平均操作非常简单,因此并行化开销决定了简单并行化 GroupBy 的结果。当使用带有 Ray 后端的 binned GroupBy 时,我们仍然比不使用 Batcher 获得了 1.9 倍的加速。如果在每个入库的 GroupBy 中执行更密集的操作列表,加速将再次接近线性。

当应用于词干分析时,缓存似乎有很大的影响。由于输入是高度重复的,并且每个项目的成本很高,因此缓存在这种情况下是可行的。最好的结果是在没有批处理程序的情况下实现的,其中 1000 个项目的 lru_cache 实现了 0.37 秒,而没有缓存时实现了 10.72 秒。在 Ray 后端的每个迷你批处理中应用缓存,我们得到 0.42 秒。如果缓存非常有用,最好不要使用并行化。一些用例可以同时受益于并行化和迷你批处理内缓存。

最后,当在两列之间分配一个简单的除法函数时,我们可以看看 Numba 矢量化工作得如何。在每个 minibatch 中编译 Numba 函数的成本远远超过了并行化这个简单函数的收益。这里的“no Wordbatch”基线额外使用了列表理解,而不是 Numpy 矢量化数组除法,这样会快很多倍。总的来说,分布式 Numba 矢量化仅对更复杂的数学表达式有用,但这些可能会受到当前 Numba 能力的限制。

总结想法

这篇博文介绍了 Wordbatch 工具包中最近添加的 apply-decorator 的基本用例。这提供了一个简单的一行调用,它接受任何 Python 函数或方法,并基于 Map-Reduce 将它分布在所选的后端,或者在本地,或者分布在诸如 Ray、Dask 或 Spark 之类的调度器上。正确使用可以使许多处理任务的可用内核数量接近线性加速。

充分利用 apply-decorator 需要对并行化的计算成本和并行化的功能有所了解。如果与并行化开销相比,这些方法在计算上非常简单,那么收益很小。如果相反,那么就接近线性加速。

对于现实世界的人工智能管道,最好在最高级别进行并行化,将整个管道功能分布在大型迷你批处理上。这降低了向进程传输单个数据的并行化成本,并且每个大型小批量都可以用完整的流水线来处理。使用 apply-decorator,可以通过在大型组上分配每个数据帧的函数来实现这一点,如 binned GroupBy 示例所示。或者,Wordbatch 有一个相关的类 ApplyBatch 及其 decorator 函数 decorator_apply_batch。这些功能类似于应用,但将函数直接应用于平均分割的批处理,并且不需要像分箱分组那样设置可变宁滨。我的第一篇博文比较了 Python 分布式 AI 后端给出了一个使用 ApplyBatch 的例子。

Python:在线贝叶斯 A/B 测试!

原文:https://towardsdatascience.com/python-online-bayesian-a-b-testing-8a81ccbf4001?source=collection_archive---------28-----------------------

针对 A/B 测试的 Beta 分布、二项式可能性和共轭先验的速成课程

信用:Pixabay

常客背景

如果你和我一样,早在你对数据科学、机器学习等感兴趣之前,你就已经通过社会科学初步接触了统计学。在心理学、社会学等领域,一项研究通常要进行一段时间(可能是几天、几个月甚至几年)。)在新实验的情况下,收集结果,产生平均值和方差的最大似然估计,并构建置信区间。

或者,如果我们假设事情不像现任模型(又名零假设)所描述的那样运行,我们参考现有数据,检查均值、方差和置信区间,通过研究收集数据(从总体中抽取样本),并将样本均值与置信区间进行比较。如果样本均值是极值,我们拒绝零假设,得出结论,“在位模型的均值和方差不准确, 需要更多的研究 “或者我们只是未能拒绝现任模型的发现。极端是什么意思?这有点主观——这意味着根据现有模型的分布和任意阈值,这一发现是极不可能的。(即,给定分布,我们的样本只有 1%的时间被观察到如此之大(或更大)或如此之小(或更小),我们武断地决定,如果这样的发现有 5%的发生几率(或更小的概率),我们将拒绝现有模型。)

这是频率主义者的范式。它非常适合这样的情况:我们有足够的时间来收集足够的数据,以便在根据我们的理解采取行动之前,非常确定我们感兴趣的人群的形状和中心趋势。不幸的是,这种方法不适合资源(时间和数据)短缺的情况,我们需要根据目前已知的信息做出最佳决策。

输入贝叶斯统计!

在我们进入贝叶斯统计之前,让我们回顾一下频率主义范式的一些关键要素。支配分布的参数是固定的,我们只需要收集一个足够大的样本用于我们的估计(样本统计)以收敛于真实的总体参数。假设我们的参数是固有的标量值(固定数值),我们通过置信区间来表达我们对这些值的信心(换句话说,根据当前参数的最大似然估计,一个观察值将有多可能)。)

贝叶斯模型拒绝了参数是固定的这一观点,而是将它们视为分布本身。这使得数学变得非常非常不愉快。然而,它允许我们从一个关于参数(先验)的信念开始,将这个信念与观察到的数据(似然)本身联系起来,考虑所有其他的可能性(证据),并返回新的更新的信念(后验。换句话说,它是为在线学习而优化的,在线学习的一个广泛应用的例子是 A/B 测试。

在我们开始编码之前,让我们先谈谈策略——如果你以前谷歌过贝叶斯统计,你可能听说过像马尔可夫链蒙特卡罗(MCMC 方法)这样的术语。发明这些方法是为了从极其难以(如果不是不可能的话)分析整合的分布中取样,并且它们很大程度上以证据为导向。 见下面第 4 节关于贝叶斯法则的论述。

贝叶斯法则总结起来就是(A)选取一个先验分布;这是你对感兴趣的参数的推断前信念。然后(B)选择一种可能性,以先前的信念为条件,模拟数据有多令人惊讶(或不令人惊讶)。最后,(C)将分子与证据进行比较。从字面上看,这是在参数可能出现的任何下观察到数据的概率。证据评估为常数值,其 缩放 分子,使得它是有效的概率分布(积分为 1。)

事实上,你的模型越复杂,计算证据就越痛苦。输入共轭先验。如果后验(您对参数的更新信念)与前一个具有相同的形状(并且通常很容易计算),那么有一些前验和可能性的组合是“彼此共轭的”!)

在这篇文章中,我们将利用共轭先验,以减少计算的复杂性!一个完美的例子是贝塔先验,二项式似然配对,其中贝塔分布描述了后验分布

首先,欧拉贝塔函数 与贝塔分布 不同;现在就把这一点记下来,你会省去很多困惑。见下文第 1 节。事实上,欧拉贝塔函数是贝塔分布的分母(见第 3 节。)其目的是缩放分子,使贝塔分布整合为 1 ( 共同主题… )

二项式分布描述了伯努利试验的总和。θ的 x 次方(有多少次成功)乘以 1-θ的 n-x 次方(n 次试验失败)。)第一项,读作“n choose x”是在 n 次试验中总共成功出现 x 次的组合数(不考虑顺序)。对于我们的 A/B 测试,我们可以讨论任何二进制的成功/失败(老丨虎丨机转化率与网站总点击率等),这是一个合理的可能性选择。

β-二项式共轭证明第 1 部分

我警告过你证据非常非常糟糕,不是吗?请参见下面的第 4.3 节。值得注意的是,我们的策略依赖于将常数从积分中分解出来,即 n-Choose-x 除以欧拉β函数。在此之后,我们可以很容易地组合类似的项,得到看起来非常类似于另一个欧拉贝塔函数(指数值已经改变,但这将被证明是有益的。)

β-二项式共轭证明第二部分

最后,我们把它结合在一起。是的,这有点可怕。请注意,在等式 12 中,我们将 n-Choose-x 和欧拉β函数从分子中剔除。在步骤 13 中,这些值相互抵消。在等式 14 中,我们看到分母(再次)具有与欧拉β函数相同的形式,因此我们相应地替换它。现在,我们看到分子和分母遵循一个友好的模式——贝塔分布。这太棒了!我们看到,为了计算我们的后验分布,我们只需要四个元素——A、B、X 和 N,其中 A 和 B 是我们的先验信念,X 是成功的次数,N 是试验的总数。整齐!

β-二项式共轭证明第三部分

让我们来探索一下 Beta 发行版有多通用和有用。我鼓励你尝试这个绘图工具。这有助于理解为什么 Beta 分布对影响二元结果的参数建模如此有用。

质量均匀分布

具有相等 a 和 b 值(小于 1)的尾部质量的体积

质量的体积偏向 1,a 值越大

b 值越高,质量越偏向 0

质量体积偏向 0.5,a 和 b 值相等(大于 1)

让我们从一个简单的单臂强盗例子开始编码吧!我们将从统一的先验开始,并逐渐收敛到真实参数(25%的成功几率,对于赌场来说过高。对于那些不知道的人来说,独臂强盗就是一台老丨虎丨机。你投入一枚硬币(或指定的费用)拉动手臂,游戏将开始,各种图标旋转图标将对齐(支付!)还是没有(扫兴。)

独臂强盗

独臂强盗贝叶斯更新代码

好的,那么这段代码在做什么呢?首先,我们做一些常规进口。接下来,我们定义一个名为 beta 的类,它接收ab作为参数。我们将这些初始化为 1,每个(又名均匀先验。)然后,我们创建一个列表,其中每个元素基于范围(0,1)中的随机值数组为 1 或 0—如果值低于. 25,则返回 1,否则返回 0。这个列表平均值应该接近 0.25,但是,由于只生成 100 个样本,它可能会有一点变化。接下来,我们定义一个函数,experiment,它将这个列表分成大小相等的批次;对于每一批,我们找到成功和失败,并相应地更新我们的 Beta 类实例的ab参数。因为我们已经涵盖了上面所有的数学知识,所以这一部分很简单!

考虑下图。顺序如下:蓝色、橙色、绿色和红色。蓝色是我们的均匀先验,我们对θ接收的任何特定值没有偏见。在 orange 中,我们将 25%的数据输入到模型中;因此,根据可能性,我们对我们的制服先验不太有信心(吃角子老丨虎丨机不太可能是完全随机的;事实上,它似乎并不经常得到回报。)用橙色绘制的后验分布成为绿色的先验信念。并且该先验信念同样被更新,收敛于参数的真实值。递归地,前一批的后一批成为新批的前一批。请注意,方差在每次迭代中都在缩小(这一点随着峰值变得更加明显而变得明显——它变得更高、更紧。)

基于均匀先验的贝叶斯更新

我们已经研究了数学,并看到贝叶斯统计如何帮助我们迭代地“聚焦”真实参数,但这不完全是 A/B 测试。接下来是什么?

接下来,让我们考虑一下为什么这对 A/B 测试如此有利。注意,在每次迭代中,我们更新了我们的信念,缩小了均值的方差。在我们有多个强盗(恰当地命名为多臂强盗或 MAB)的情况下,将一半资金花在两台机器中的第一台上,然后探索第二台机器是一个糟糕的策略。我们必须同时作为科学家和商人来思考。这是“探索马得利”的一个很好的继续如果我们只玩一台机器,我们会将(这台机器的)方差缩小很多——但这并没有回答最根本的问题,它是不是最好的机器?同样,如果我们平等地玩所有的机器,我们会对它们的均值和方差有一个很好的了解——但是我们没有利用这些信息。

有几种算法可以回答这个问题;例子有 epsilon greedy,UCB1 等。这些主题很好地介绍了强化学习,但是我们有失去焦点的风险。因此,我们将保持简单;我们将在 固定顺序 中轮换每台机器,并使用与上一次迭代几乎相同的方法更新每个 Beta 类对象的属性。请注意,我做了一些简单的代码修改,例如(A)每个分布都有一个唯一的颜色,以及(alpha(透明度的倒数)从接近 0 开始,并随着每次迭代向 1 增加。我的目标是,你可以(从字面上)看到我们对每台机器的参数的估计是如何集中在它们的实际值上的。

MAB 贝叶斯更新代码

统一先验的 MAB 贝叶斯更新

结论

正如你从上面所看到的,红色的估计值每一轮都朝着它的真实值(0.25)增加,而蓝色和绿色的值都简单地估计它们的平均值高于真实参数值。这表明,更多的数据总是有助于微调我们对数据的理解,利用和探索真的很重要。我以后很可能会在 epsilon-greedy,UCB1 等上面写!我希望这些代码块、(乏味的)证明以及我对直观解释的尝试已经帮助你对 A/B 测试的贝叶斯方法感到更舒服了。

如果有任何你希望我在未来写的特定主题,请评论!

感谢您的阅读——如果您认为我的内容还可以,请订阅!😃

Python OpenCV:构建类似 Instagram 的图像过滤器

原文:https://towardsdatascience.com/python-opencv-building-instagram-like-image-filters-5c482c1c5079?source=collection_archive---------13-----------------------

使用图像变换技术构建图像过滤器的 Python OpenCV 教程。

OpenCV 是为解决大量计算机视觉任务而构建的库。它包含了大量的基本和高级特性,非常容易掌握,并且可用于多种编程语言。

在这篇文章中,我们将应用一些基本的图像变换技术,以获得图像过滤器。对于那些习惯了所有图像编辑软件的人来说,这些滤镜可能对你来说很基本。但是我认为对于第一次接触 OpenCV 的人来说,它们是很棒的,因为它们允许我们在不编写大量代码的情况下学习一些基本原理。😀

照片由诺德伍德主题Unsplash 上拍摄

本文原载于 程序员背包博客 。如果你想阅读更多这类的故事,一定要访问这个博客。

更感兴趣?在 Twitter 上关注我,地址是@ b _ dmarius,我会在那里发布每一篇新文章。

介绍

在这一节中,我将解释计算机如何存储和处理 RGB 图像背后的逻辑。如果你已经熟悉这些东西,请跳到下一节,我们将跳到更高级的细节。

图像中的基本单位数据是像素。像素只是图像中的一个点,并存储为范围在[0,256]内的数字。RGB 模型代表红绿蓝并告诉我们,对于每个像素,我们存储红、绿、蓝的强度(我们将这些通道称为)作为一个从 0 到 256 的数字。如果所有 3 个通道都是 256,则像素为白色;如果所有 3 个通道都是 0,则像素为黑色。如果相应的通道是 256 并且所有其他通道是 0,则像素是完全红色/绿色/蓝色的。你明白了,每种颜色都是由这三个通道混合而成的。

所以图像是像素的集合。比方说,如果我们的图像是 300x200,那么我们将把它存储为 300 行 200 列的 2D 数组,其中每个单元是一个像素。但是我们从上面知道,对于每个像素,我们将存储所有 3 个通道的信息,所以这实际上给了我们一个 3D 数组。

OpenCV 卷积和内核

这是完全由理论组成的最后一部分。如果你想直接跳到实用部分,请见下一节。

现在我们知道了图像是如何作为像素存储的,我们可以学习对这些像素应用变换。

卷积是通过将图像分割成称为窗口的小部分,并对每个部分应用称为内核的操作符来变换图像的操作。

内核通常是一个固定的、包含数字的小型 2D 数组。内核中的一个重要部分是中心,称为锚点

OpenCV 过滤器—内核示例

卷积通过以下步骤执行:

  1. 将内核放置在图像的顶部,内核锚点位于预定像素的顶部。
  2. 在内核数和被内核重叠的像素值之间执行乘法,对乘法结果求和,并将结果放在锚点下方的像素上。
  3. 重复这个过程,在图像上的每个可能的位置滑动图像顶部的内核。

如果你想知道如何选择核的值,请注意最流行的核是图像处理科学家大量研究的结果。你当然可以试着选择你自己的内核,但是对于最基本的转换,我们已经有了很好的内核,可以提供很好的结果。

项目设置

我们需要安装 2 个 python 包,然后就可以开始了。

pip3 install opencv-python
pip3 install scipy

我们将导入单个图像(这是我亲自拍摄的图像),并且对于每个转换,我们将制作该图像的副本。然后,我们通过一个单独的方法应用转换,这样我们可以保持代码的整洁。最后,我们将把结果保存为一个单独的图像。下面是基本流程:

initialImage = cv2.imread("image1.jpg")
blurredImage = gaussianBlur(copy.deepcopy(initialImage))
cv2.imwrite("blurred.jpg", blurredImage)

OpenCV 内核和卷积变换

在这一部分,我们将使用一组预定义的内核来应用卷积,以获得漂亮的效果。对于其他类型的转换,请跳到下一节。对于每一个转换,我将向你们展示内核和代码,在这一节的最后,我将展示一个画廊,展示初始图像和结果。

图像锐化

Python OpenCV 滤镜-图像锐化

这是用来锐化图片细节的内核。我们将使用 OpenCV 库中的 filter2D 方法,它将为我们执行卷积。

def sharpen(image):
    kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]])
    return cv2.filter2D(image, -1, kernel)

棕褐色效果

Python OpenCV 滤镜—棕褐色

def sepia(image):
    kernel = np.array([[0.272, 0.534, 0.131],
                       [0.349, 0.686, 0.168],
                       [0.393, 0.769, 0.189]])
    return cv2.filter2D(image, -1, kernel)

模糊效应

为了达到这个效果,我们可以使用一个基本的内核,就像上面所有的一样,但是结果是相当蹩脚的。幸运的是,OpenCV 实现了高斯模糊,它将为我们完成这项工作。我们需要做的就是:

def gaussianBlur(image):
    return cv2.GaussianBlur(image, (35, 35), 0)

浮雕效果

Python OpenCV 滤镜-浮雕

def emboss(image):
    kernel = np.array([[0,-1,-1],
                            [1,0,-1],
                            [1,1,0]])
    return cv2.filter2D(image, -1, kernel)

这是我们内核转换结果的图库。

这是最初的图像

从左到右,从上到下:模糊,浮雕,棕褐色,锐化

OpenCV —基于像素值的变换

接下来,我们将增加图像的亮度。为此,我们需要做的就是导航到图像的每个像素,然后导航到特定像素的每个通道。然后,我们将每个通道的值增加一个特定的值。这将给我们一个很好的亮度效果。

为了将我们从所有这些代码中解放出来,OpenCV 框架实现了一个方法,可以完全做到这一点。

def brightnessControl(image, level):
    return cv2.convertScaleAbs(image, beta=level)

这是我们亮度控制方法的结果。

左—明亮的图像,右—原始图像

OpenCV —查找表转换

我们将使用这种类型的变换来使图像看起来更温暖和更寒冷,但首先让我们看看我们如何使用查找表。

一个查找表只是一个简单的值对集合,如下所示:【值 1,值 2,…。,valueN],[modifiedValue1,modifiedValue2,…,modifiedValueN] 这背后的逻辑很简单——我们将获取每个像素值,并用查找表中的相应值替换它(意味着用 modifiedValue1 等替换 value1 )。

现在的问题是,有很多值需要替换(从 0 到 256),为此创建一个查找表是一个痛苦的过程。但是幸运再次站在我们这边,因为我们有一个工具可以利用它。

来自 scipy 包的 单变量线 平滑方法可以帮助我们。这种方法只取几个参考值,并试图找到一种方法来修改我们提供的参考值范围内的所有其他值。

基本上,我们将定义一个简短的查找表,如下所示

【0,64,128,256】,【0,80,160,256】

并应用 UnivariateSpline 变换,该变换将填充[0,256]范围内的其余值。

构建好查找表后,我们只需将它们应用于特定的通道。为了获得一个温暖的图像,我们将为图像中的所有像素增加红色通道的值,减少蓝色通道的值。为了获得冷图像,我们要做相反的事情:增加蓝色通道的值,减少红色通道的值。绿色通道在这两种情况下都不会被触及。

def spreadLookupTable(x, y):
  spline = UnivariateSpline(x, y)
  return spline(range(256))def warmImage(image):
    increaseLookupTable = spreadLookupTable([0, 64, 128, 256], [0, 80, 160, 256])
    decreaseLookupTable = spreadLookupTable([0, 64, 128, 256], [0, 50, 100, 256])
    red_channel, green_channel, blue_channel = cv2.split(image)
    red_channel = cv2.LUT(red_channel, increaseLookupTable).astype(np.uint8)
    blue_channel = cv2.LUT(blue_channel, decreaseLookupTable).astype(np.uint8)
    return cv2.merge((red_channel, green_channel, blue_channel))def coldImage(image):
    increaseLookupTable = spreadLookupTable([0, 64, 128, 256], [0, 80, 160, 256])
    decreaseLookupTable = spreadLookupTable([0, 64, 128, 256], [0, 50, 100, 256])
    red_channel, green_channel, blue_channel = cv2.split(image)
    red_channel = cv2.LUT(red_channel, decreaseLookupTable).astype(np.uint8)
    blue_channel = cv2.LUT(blue_channel, increaseLookupTable).astype(np.uint8)
    return cv2.merge((red_channel, green_channel, blue_channel))

这里的结果和预期的一样。

左侧—暖图像,中间—原始图像,右侧—冷图像

这很有趣!我们在这里看到了一点数学,一点代码,学到了很多关于计算机如何存储和处理图像,以及我们如何使用它来获得图像的美丽变换。如果你喜欢这篇文章,并想了解更多,那么请确保你在 Twitter 上关注我,因为不久我将发布另一篇关于使用 OpenCV 构建类似 Instagram 的面具的文章。

本文原载于 程序员背包博客 。如果你想阅读更多这类的故事,一定要访问这个博客。

非常感谢您阅读本文!有兴趣了解更多吗?在 Twitter 上关注我,地址是@ b _ dmarius,我会在那里发布每一篇新文章。

Python 操作者从零开始!!!—初学者指南

原文:https://towardsdatascience.com/python-operators-from-scratch-a-beginners-guide-8471306f4278?source=collection_archive---------22-----------------------

在本教程中,您将学习 python 中的一个基本且重要的概念——运算符,以及它们的语法和示例。

来源:oddsockvideogames,viaapk pure(CCO)

什么是运营商?

运算符是一个字符字符集,可以用来对操作数执行期望操作并产生最终结果

最终结果完全取决于所使用的运算符类型。

例如,假设您想要执行 5+3 的数学计算。现在 53 都称为操作数+ 是执行加法运算符,最终结果是 8

只是提醒一下,本教程的完整代码可以在下面我的 GitHub 资源库 中找到:

[## 塔努-北帕布/Python

github.com](https://github.com/Tanu-N-Prabhu/Python/blob/master/Python_Operators.ipynb)

运算符的类型

塔努·南达·帕布拍摄的照片

Python 支持的不同类型的运算符如下:

  1. 算术运算符
  2. 关系运算符
  3. 逻辑运算符
  4. 按位运算符
  5. 赋值运算符
  6. 身份运算符
  7. 隶属操作符

算术运算符

算术运算符用于执行数学运算,如加、减、乘、除、模、底除和指数

塔努·南达·帕布拍摄的照片

例子

下面是一个简单的 python 代码片段,可以作为参考:

**# Assigning values to variables** a = 10
b = 5**# Addition** print('a + b =', a + b)**# Subtraction**
print('a - b =', a - b)**# Multiplication**
print('a * b =', a * b)**# Division**
print('a / b =', a / b)**# Modulus**
print('a % b =', a % b)**# Floor Division**
print('a // b =', a // b)**# Exponent**
print('a ** b =', a ** b)

当您运行上述 python 脚本时,您将得到以下输出提示

a **+** b = **15** 
a **-** b = **5** 
a ***** b = **50** 
a **/** b = **2.0** 
a **%** b = **0** 
a **//** b = **2** 
a ****** b = **100000**

重要注意事项

  • 如果你用任何一个数字除以 0 ,你会得到一个错误提示**ZeroDivisionError**。不要用零(0)除任何东西。
  • 除法运算符生成的结果将始终是浮点数(用小数点表示)。
  • 底数除法返回去掉小数点后位数的商(答案或除法的结果)。但是,如果操作数(被除数和除数)之一是负的,则结果是 floored,即,远离零舍入(意味着,朝向无穷大的负数)。

出处: 菲尔优 ,via 泰克拉多(CCO)

关系运算符

顾名思义,关系运算符或比较运算符用于比较值。这些运算符的返回类型不是**True** 就是**False**。不同的比较运算符是大于、大于或等于、小于、小于或等于、等于和不等于

塔努·南达·帕布拍摄的照片

例子

下面是一个简单的 python 代码片段,可以作为参考:

**# Assigning values to variables** a = 10
b = 5**# Greater than** print('a > b =', a > b)**# Lesser than** print('a < b =', a < b)**# Equal to** print('a == b =', a == b)**# Not equal to** print('a != b =', a != b)**# Greater than or equal to** print('a >= b =', a >= b)**# Lesser than or equal to** print('a <= b =', a <= b)

当您运行上述 python 脚本时,您将得到以下输出提示

a **>** b = **True** 
a **<** b = **False** 
a **==** b = **False** 
a **!=** b = **True** 
a **>=** b = **True** 
a **<**= b = **False**

重要注意事项

  • 关系运算符也称为比较运算符。
  • 比较运算符可用于比较两个以上的值。例如5 **>** 3 **<** 1将导致**False**
  • 这些也被称为关系运算符,因为它比较值,然后决定它们之间的关系。比如5 **>** 4关系是这样的 5 大于 4 答案是**True**。这里的关系是大于

逻辑运算符

逻辑运算符用于评估操作数之间的条件。不同类型的操作员有**and****or****not**

塔努·南达·帕布拍摄的照片

为了使事情更清楚,您可以参考下面给出的逻辑运算符的真值表:

来源: 理查德鲍德温 ,viaopenstax(CCO)

例子

下面是一个简单的 python 代码片段,可以作为参考:

**# Assigning values to variable** a = True
b = False**# Logical and** print('a and b is',a and b)**# Logical or** print('a or b is',a or b)**# Logical not** print('not a is',not a)

当您运行上述 python 脚本时,您将得到以下输出提示

a **and** b is **False** 
a **or** b is **True** 
**not** a is **False**

重要注意事项

  • 逻辑运算符也被称为布尔运算符
  • 如果操作数不是布尔值,那么它将自动转换为布尔值进行计算。
  • 逻辑运算符可以应用于任何类型的值。例如,它们可以应用于如下所示的琴弦。在这种情况下,运算符返回第一个假值,如果有空值或假值,则返回最后一个值。返回第一个真值,否则返回最后一个值。

字符串上的逻辑“与”运算符

a = ""
b = "Python"
a **and** b**''**

字符串上的逻辑“或”运算符

a = ""
b = "Python"
a **or** b'**Python**'
  • **and****or**两种情况下,评估都是从进行的。

按位运算符

按位运算符在二进制级别上对操作数进行运算。这意味着按位运算符直接查看整数的二进制数字或二进制位。因此得名按位(逐位操作)。不同类型的按位运算符有按位与、或、非、异或、右移和左移

塔努·南达·帕布拍摄的照片

例子

下面是一个简单的 python 代码片段,可以作为参考:

**# Assigning values to variables** a = 10
b = 11**# Bitwise AND** print('a & b is',a & b)**# Bitwise OR** print('a | b is',a | b)**# Bitwise XOR** print('a ^ b is',a ^ b)**# Bitwise NOT** print('~a is',~a)**# Bitwise Left Shift** print('a << b is',a << b)**# Bitwise Right Shift** print('a >> b is',a >> b)

当您运行上述 python 脚本时,您将得到以下输出提示

a **&** b is **10** 
a **|** b is **11** 
a **^** b is **1** 
**~**a is **-11** 
a **<<** b is **20480** 
a **>>** b is **0**

重要注意事项

  • 逐位运算符对进行运算,并对操作数执行逐位运算。
  • 无论传递的操作数是什么类型,按位运算符都会分别将其转换为一系列二进制数字。例如,如果一个操作数是 2 ,那么它的二进制格式就是 10 ,同样, 9 将被渲染为 1001 等等。下面是不包括左移和右移运算符的位运算符的真值表。

塔努·南达·帕布拍摄的照片

赋值运算符

顾名思义,赋值操作符用来给变量赋值。让我给你举个简单的例子。

a = 5

很多时候,人们在阅读上面一行代码时会犯错误。人们说“ a 等于 5 ”,这听起来可能是正确的,但从程序上来说是不正确的。正确的做法是:

值 5 被分配给变量‘a’

因为赋值操作符的工作方式是把右边的值赋给左边的变量。所以记住它的从右到左

塔努·南达·帕布拍摄的照片

例子

下面是一个简单的 python 代码片段,可以作为参考:

**# Assigning the values to variables** a = 15
b = 5**# Simple assignment operator** b = a
print('b = a: ',b)**# ADD AND operator** b += a
print('b += a: ', b)**# SUBTRACT AND operatpr** b -= a
print('b -= a: ', b)**# MULTIPLICATION AND operator** b *= a
print('b *= a: ', b)**# DIVISION AND operator** b /= a
print('b /= a: ', b)**# FLOOR AND operator** b //= a
print('b //= a: ', b)**# MODULUS AND operator** b %= a
print('b %= a: ', b)**# EXPONENT AND operator** b **= a
print('b **= a: ', b)**# LESS THAN AND operator** b <= a
print('b <= a: ', b)**# GREATOR THAN AND operator** b >= a
print('b >= a: ', b)**# BINARY AND operator** a &= 5
print('a &= 5: ', a)**# BINARY OR operator** a |= 5
print('a |= 5: ', a)

当您运行上述 python 脚本时,您将得到以下输出提示

b **=** a:   **15** 
b **+=** a:  **30** 
b **-=** a:  **15** 
b ***=** a:  **225** 
b **/=** a:  **15.0** 
b **//=** a: **1.0** 
b **%=** a:  **1.0** 
b ****=** a: **1.0** 
b **<=** a:  **1.0** 
b **>=** a:  **1.0** 
a **&=** 5:  **5** 
a **|=** 5:  **5**

笔记

  • 我们可以为更多的操作符扩展赋值操作符,比如**-, /, *, //, %, <<, >>, &, |, **, ^**。例如:**a **= 5**,将是**a = a**5**,答案将是**298023223876953125**。确保您编写的操作符后跟赋值操作符

特殊操作员

python 编程语言中有两种特殊运算符,如下所示:

标识运算符

顾名思义,identity 操作符比较两个或更多 python 对象的 id (identity) ,比如变量、值等等。换句话说,别人说同样可以用恒等运算符比较两个对象的内存位置。有两种类型的恒等运算符,即**is****is not**

塔努·南达·帕布拍摄的照片

例子

下面是一个简单的 python 代码片段,可以作为参考:

**# Assigning values to variables** a = 10
b = 11**# Identity is operator** print('a is b is',a is b)**# Identity is not operator**
print('a is not b is',a is not b)

当您运行上述 python 脚本时,您将得到以下输出提示

a **is** b is **False** 
a **is not** b is **True**

重要注意事项

  • 通常,标识运算符不比较值或对象本身。相反,它会比较 id(身份)。下面是一个例子:
**# Assigning the values to variables** a = 5
b = 5
c = a**# Getting the id of the variables** print(id(a))
print(id(b))
print(id(c))**# Comparing the id of a and c** print(a is c)

要比较 id,您可以使用 python 中的**id** 函数。它返回内存位置的 id

id of a is: **10914624** 
id of b is: **10914624** 
id of c is: **10914624** 
**True**

成员运算符

成员运算符用于验证特定元素是否是序列的部分。现在一个序列可以是一个列表、字符串、集合、字典和元组。这两个成员操作符是**in****not in**

塔努·南达·帕布拍摄的照片

例子

下面是一个简单的 python 代码片段,可以作为参考:

**# Assigning a string value to a variable** a = "Python"**# Type of the variable** print(**type**(a))**# Checking whether 'y' is present in the variable a or not** print('y' **in** a)**# Checking whether 'P' is present in the variable a or not** print('p' **not in** a)

当您运行上述 python 脚本时,您将得到以下输出提示

<class '**str**'> 
**True
True**

重要注意事项

  • 虽然我们可以在字典上使用成员运算符,但是有一件事你应该知道,即我们只能测试键的存在,而不能测试值的存在,如下所示:
**# Dictionary with key as 1, 2 and values as 'A' and 'B'** a = {1: "A", 2: 'B'}**# Using 'in' operator** print(2 **in** a)**# Using 'not in' operator** print(3 **not in** a)

因此,上面的输出将是:

**True** 
**True**

干得好,干得好伙计们,你们已经到达教程“ Python 操作者从头开始”的结尾了!!!—初学者指南”。我希望读完这篇教程后,你对 python 操作符有了更深的了解。如果你对教程有任何疑问,请通过下面的评论区告诉我。我试着尽快回答。好的,下次见,祝你愉快,注意安全。

Python 包焦点:Faker

原文:https://towardsdatascience.com/python-package-focus-faker-7a1ccb1074ad?source=collection_archive---------49-----------------------

为任何情况生成测试数据的简单方法。

马库斯·斯皮斯克在 Unsplash 上的照片

有如此多的 Python 包,对于正在学习这门语言的人来说,知道有哪些工具可供您使用可能会让人不知所措。我希望发现一些鲜为人知但功能强大且有用的包,以帮助您踏上 Python 之旅。

那么,Faker 是什么?

根据他们的文档,Faker 是一个‘为你生成虚假数据的 Python 包’。“无论你是需要引导数据库、创建好看的 XML 文档、填充持久性以对其进行压力测试,还是匿名化来自生产服务的数据,Faker 都适合你。”

这立即吸引了我,因为它对学生、寻求建立文件夹/项目工作的专业人员,或者任何想要修补各种其他库但缺乏适当数据集的人来说都有很大的价值。在我自己的工作中,我经常想建立某种仪表板,但需要确保我使用的数据可以安全地共享。Faker 替我处理这些,因为我可以快速生成项目所需的几乎任何数据集。

安装和入门

这就像用 pip 安装一样简单:

pip install Faker

在那里,我们创建了一个 Faker“生成器”,我们将对生成的数据进行多次调用:

from faker import Faker
fake = Faker()

Faker 有许多所谓的内置提供者——从伪造的条形码、公司名称、电话号码、文件名等等。标准提供商的完整列表可在这里找到。利用它们非常简单!例如,假设我们正在构建一个测试数据库,并想要一个公司名称及其口号的列表。为此,我们将运行以下代码:

如果我们想要一些公司人员的数据——姓名、地址、职位等,会怎么样?使用 fake.profile()可以生成一个字典配置文件:

这是一个相当广泛的列表,但是如果您想要构建一些更具体的东西呢?您可以从标准提供商那里构建自己的配置文件:

播种

如果您正在进行测试,那么在您的生成器上设置一个种子来从相同的数据集进行提取可能会有所帮助。
这和使用 seed()方法一样简单:

from faker import Faker
fake = Faker()
Faker.seed(1234)

本地化

Faker 的另一个非常酷的特性是能够改变生成的数据集的本地化。默认情况下,它是英语美国,但有一大堆其他选项。例如,如果我们想生成一堆假的瑞典名字会怎么样?没问题!

当您创建 Faker 生成器时,只需将 locale 作为参数传递就可以了。通过向生成器传递一个区域设置列表,您甚至可以使用多个区域设置:

在上面的示例中,每个名称都是从 3 个区域列表中随机选择的。但是,您可以使用权重来创建符合您需求的分布。

总的来说,Faker 是一个非常通用和实用的库,我个人认为它有巨大的使用价值。
我鼓励您访问他们的文档以查看所有可用的可能提供商,因为这只是一个简短的概述。

照片由克里斯杨Unsplash 上拍摄

AWS Lambda 中的 Python 包变得简单

原文:https://towardsdatascience.com/python-packages-in-aws-lambda-made-easy-8fbc78520e30?source=collection_archive---------3-----------------------

创建自己的 Lambda 层的简单指南,这样你就可以在 Lambda 函数中使用任何 Python 包

AWS Lambda 是一个多功能的无服务器工具。有了 Lambda,你几乎可以运行任何你喜欢的东西——只需编写代码并上传到 Lambda。您每使用 100 毫秒就要付费,因此您只需为消耗的计算时间付费。

Lambda 支持 Python,如果你有使用它的经验,这是一个很好的选择。然而,Lambda 的一个缺点是默认情况下你不能导入你信任的包,比如熊猫。

我将向您展示导入 Lambda 函数所需的任何包的最简单方法。我将以熊猫为例,但是同样的方法也可以用于其他的包。

步骤 1:在 AWS 中启动一个 Cloud9 Linux 实例

  • 在 AWS 服务中搜索 Cloud9
  • 点击“创建环境”
  • 将您的环境命名为您喜欢的名称(例如 python_package_test ),然后单击下一步
  • 保持环境默认设置(为环境创建一个新的 EC2 实例;t2.micro 亚马逊 Linux 等..)并点击下一步
  • 点击“创建环境”,您就可以开始了

步骤 2:创建你的熊猫 Lambda 层

  • 在底部的终端中逐行键入以下代码。pip install pandas 命令可以替换为您选择的软件包。您也可以安装多个软件包*。
mkdir folder
cd folder
virtualenv v-env
source ./v-env/bin/activate
pip install pandas
deactivate
  • 然后逐行输入以下代码来创建图层
mkdir python
cd python
cp -r ../v-env/lib64/python3.7/site-packages/* .
cd ..
zip -r panda_layer.zip python
aws lambda publish-layer-version --layer-name pandas --zip-file fileb://panda_layer.zip --compatible-runtimes python3.7

步骤 3:添加熊猫层到 Lamda 函数中

  • 转到 AWS Lambda 服务并单击“创建函数”
  • 命名您的函数,将运行时设置为“Python 3.6”,然后单击“创建函数”
  • 点击功能设计器中的“层”,然后点击“添加层”
  • 在名称下拉列表中,你应该看到你的熊猫层。点击“添加”。

  • 让我们用下面的脚本来测试这一点。注意,我也可以导入 numpy,因为它是熊猫包的依赖项:
import numpy as np
import pandas as pddef lambda_handler(event, context):
    df2 = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),columns=["a", "b", "c"])
    number = np.pi
    print(df2)
    print(number)

成功了!我们可以看到熊猫数据帧输出和 pi 的数字,证明 numpy 和熊猫已经成功导入。

*限制:一个 Lambda 函数一次最多可以使用 5 层,但是,该函数和所有层的总解压缩大小不能超过 250 MB。

Python: Pagerank 遇上体育分析

原文:https://towardsdatascience.com/python-pagerank-meets-sports-analytics-28e4d395af57?source=collection_archive---------36-----------------------

重新利用一万亿美元的运动队排名算法

信用:Pixabay

前几天我发表了一篇关于使用蒙特卡罗模拟来收敛彩票概率分布的文章。名义上,它比我以前的一些文章更快地获得了关注。这可能意味着(A)读者对蒙特卡洛方法非常感兴趣,或者(B)读者对体育分析非常感兴趣。我敢打赌,体育分析是这里的主导因素,这篇文章将作为一个实验!(我很 meta,我知道。)

概观

这完全是一个“端到端”的项目,首先通过 SQLite 访问数据库数据,通过 Pandas 进行数据清理/管理,通过 NetworkX 进行网络建模,最后将我们的结果与官方的“种子”进行比较。

但是我想得太多了。我们的数据来自 NCAA(美国全国大学生体育协会)2019 年男子篮球常规(和后)赛季(s),仅限于 ACC(大西洋海岸会议)。我们的目标是挖掘输赢模式的数据,根据赢得联盟冠军的可能性对球队进行排名。

最后,让我们讨论一下“万亿美元算法。“22 年前,谷歌在加州门洛帕克成立,为庞大的信息网络带来了秩序和相关性。这个算法 Pagerank ,是对一个已建立的网络度量——特征向量中心性的改编。该算法期望接收一个转换矩阵作为参数;这个转移矩阵量化了网页之间的链接。当一个页面链接到另一个页面时,它与另一个页面共享部分可信度。很大程度上,共享的数量取决于(首先讨论的)节点有多少个出站链接。迭代执行该算法,直到特征向量收敛。这个特征向量就是page rank;换句话说,它包含了每个页面相对于其他页面的排名。Pagerank 已经被应用到学术期刊的网络中,在那里一篇非常受欢迎的文章链接到一篇祖父文章或开创性的文章。高人气的文章与开创性的文章分享了它的大部分可信度。由此可以得出结论,尽管许多文章没有引用这篇开创性的文章,但它们通过这篇高人气文章间接受到了这篇文章的影响。这才是 pagerank 真正的美好和强大。

我们需要对数据进行预处理,以便 Pagerank 可以将其作为参数接收。考虑两个团队,一个几乎整个赛季都没有输过,另一个几乎整个赛季都输了——但是——失败的团队碰巧打败了胜利的团队。在体育运动中,这通常被称为冷门。并且 Pagerank 将能够提取该事件的意义和全球背景。我们只需要一种有效的方法将输赢模式编码成一个矩阵。没有绝对正确或错误的答案,但有些方法比其他方法更好;我鼓励你集思广益,找出改进这种方法的方法,亲自实施,并将结果与 NCAA ACC 官方种子进行比较。

方法

在我的方法中,我迭代了每一场常规赛,并找到了分差。比如甲队赢乙队 20 分;ergo B 队给20 点可信度给a 队图可以是有向的,也可以是无向的。在我们的例子中,我们希望 引导 节点(团队)之间的边(关系),这样就有了一个单向关系。B 队给 A 队 20 分,不是 A 队给 B 队 20 分。网络可以在两个给定节点之间有多条边(多重图),也可以在两个给定节点之间有一条边(简单图)。)我已经简化了网络,这样,在两个给定的队相互比赛两次的情况下,同一个队赢了两次,连接他们的边将是他们获胜的平均值。

我将让你来决定这个方法是否可以改进。例如,如果 A 队以 90–80 击败 B 队,则差值为 10 分。然而,如果 A 队以 20 比 10 击败 B 队,那么差距仍然是 10 分。我们应该对此做些什么吗?我将让读者来决定、实现和评估:)

密码

存储库可以在这里找到,数据库等等。

但是为了简单起见,我也做了一个 GitHub 要点:

我的结果是:

NCAA ACC 常规赛排名

我们和官方种子相比如何?

鸣谢:维基百科

总的来说,我们做得不错!我们的结果和 NCAA 官方的种子不一样;这是由于(当然)他们使用了完全不同的算法。值得注意的是,我们将杜克大学列为第二名,而 NCAA 将他们列为第三名——最终杜克大学赢得了联盟冠军(万岁)。然而,我们种子选手佛罗里达州立大学比我们低得多,他们进入了最后一轮。

我想知道我们能做些什么来改善我们的结果!还记得我们讨论过 90–80 和 20–10 都反映了 10 的增量吗?也许答案就在那里。我鼓励你探索这种可能性,并分享你的成果。

感谢阅读!如果你认为我的内容没问题,请订阅:)

Python 熊猫和 SQLite

原文:https://towardsdatascience.com/python-pandas-and-sqlite-a0e2c052456f?source=collection_archive---------2-----------------------

使用 SQLite 存储您的熊猫数据帧为您提供了一个持久存储,并提供了一种轻松选择和过滤数据的方法

马库斯·温克勒在 Unsplash 上的照片

SQLite 数据库是 Python 的内置特性,而且非常有用。它不是 SQL 的完整实现,但是它具有个人数据库甚至数据驱动网站后端所需的所有特性。

和熊猫一起用很简单,真的很有用。您可以将数据帧永久存储在一个表中,并在需要时将它们直接读入一个新的数据帧。

但不仅仅是存储方面如此有用。您可以使用简单的 SQL 命令来选择和过滤数据:这样您就不必处理数据帧本身。

我将使用 SQLite 演示一些简单的技术,并使用我最喜欢的伦敦天气数据集演示熊猫。它来自英国气象局的公共领域数据,你可以从我的 Github 账户下载。

这里的所有代码都是用 Jupyter 笔记本写的,但是作为一个独立的 Python 程序也应该运行得很好。

让我们从导入库开始:

import sqlite3 as sql
import pandas as pd
import matplotlib.pyplot as plt

显然,我们需要 SQLite 和 Pandas 库,我们还会得到 matplotlib,因为我们要绘制一些图形。

现在我们来获取数据。在一个 csv 文件中有大约 70 年的温度、降雨量和日照数据。我们是这样下载的:

weather = pd.read_csv('https://github.com/alanjones2/dataviz/raw/master/londonweather.csv')

这是它看起来的样子。记录一年中每个月的数据。气温以摄氏度为单位,降雨量以毫米为单位,“太阳”是一个月的总日照时数。

现在我们要将数据帧保存在 SQLite 数据库中。

首先,我们打开一个到新数据库的连接(如果数据库不存在的话,这将创建一个数据库),然后在数据库中创建一个名为天气的新表。

conn = sql.connect('weather.db')
weather.to_sql('weather', conn)

除非原始数据发生变化,否则我们不需要再次运行这段代码,事实上,我们不应该这样做,因为如果已经存在同名的表,SQLIte 将不允许我们在数据库中创建新表。

让我们假设我们已经运行了上面的代码一次,并且我们有我们的数据库,天气,和表,也被称为天气。我们现在可以启动一个新的笔记本或 Python 程序来完成本教程的其余部分,或者简单地注释掉代码来下载和创建数据库。

所以,我们有一个数据库,里面有我们的天气数据,现在我们想把它读入一个数据帧。下面是我们如何将数据库表加载到数据帧中。

首先,我们像以前一样连接到数据库。然后我们使用 Pandas 的 sql_read 方法读入数据。但是要做到这一点,我们必须发送

对数据库的查询:

SELECT * FROM weather

这是你能做的最简单的 SQL 查询。这意味着从名为 weather 的表中选择所有列并返回数据。下面是代码(查询作为字符串传递)。

conn = sql.connect('weather.db')
weather = pd.read_sql('SELECT * FROM weather', conn)

当然,这只是复制原始数据帧,所以让我们使用 SQL 的强大功能来加载数据的一个子集。

我们将获得相隔 50 年的几年的数据,并比较它们,看看是否有任何明显的差异。

让我们从获取 2010 年的数据开始。

我们将像以前一样使用 read_sql 创建一个名为 y2010 的新数据帧,但是查询略有不同。我们添加一个 WHERE 子句。这只选择关键字 where 后的条件为真的数据。因此,在这种情况下,我们只获得 year 列中的值为“2010”的数据行。

y2010 = pd.read_sql('SELECT * FROM weather WHERE Year == 2010', conn)

您可以看到,唯一返回的数据是 2010 年的。

这是 Tmax 的线图。

现在让我们再来一次,但是是 50 年前的 1960 年

y1960 = pd.read_sql('SELECT * FROM weather WHERE Year == 1960', conn)

现在让我们画出这两年的 Tmax

ax2010 = y2010.plot(y='Tmax')
ax = y1960.plot(y='Tmax',color = 'red', ax=ax2010)
ax.legend(['2010','1960'])

有趣的是,2010 年似乎比 1960 年更热也更冷。天气越来越极端了吗?我们需要做更多的分析来得出这个结论。

也许我们可以从找出最热的年份开始,比如温度超过 25 度的年份。

我们通过使用带有条件的 WHERE 子句来实现这一点, Tmax > 25 ,即选择 Tmax 大于 25 度的行

但是,由于我们只对最高温度感兴趣,我们将只选择我们感兴趣的列。我们通过修改 SQL 查询中的 SELECT 子句来做到这一点。

我们没有选择*(即所有列),而是列出了我们想要返回的列:Year、Month 和 Tmax。

high = pd.read_sql('SELECT Year,Month,Tmax FROM weather WHERE Tmax > 25', conn)

那是按年份顺序的。也许按温度顺序排会更有意思。

我们也可以用 SQL 做到这一点。我们加上 ORDER BY 子句,并给出应规定顺序的列。DESC 的意思是降序(省略它,您将得到默认的升序)。

high = pd.read_sql('SELECT Year,Month,Tmax FROM weather WHERE Tmax > 25 ORDER BY Tmax DESC', conn)

因此,2018 年高居榜首,2006 年紧随其后。但是 1983 年和 1995 年分别排在第三和第四位,所以这里没有明显的模式显示温度随着时间的推移而变热。

有一点我们可以看到,最热的月份是在夏天!(谁会想到呢。)但为了确保万无一失,让我们绘制一个直方图。

high.plot.hist(y='Month', xticks=high['Month'])

是的,最热的月份往往是七月。所以,如果我们在寻找一种趋势,为什么我们不看看几十年来的七月,看看气温是如何变化的。

这是另一个查询:

july = pd.read_sql('SELECT Year,Month,Tmax FROM weather WHERE month == 6', conn)

这给了我们一个所有年份的温度表,但只有当月份等于 6 时,即 7 月。

现在,我们将绘制一个 Tmax 值随时间变化的条形图。

july.plot.bar(x='Year', y='Tmax', figsize=(20,5));

我们可以做一个回归图,看看是否有任何趋势,但坦率地说,看看这个条形图,没有明显的趋势。

因此,通过对伦敦气温数据的这种极其有限的分析,我们无法得出气候变化是否正在影响伦敦人的任何结论(但从个人经验来看,我可以说那里最近感觉相当温暖)。

但是我希望我已经展示了 SQLite 在与 Pandas 一起使用时是一个有用的工具,并且如果您以前没有使用过 SQL,您可以看到如何,即使是我在这里使用的很小一部分,可能会使您的数据分析受益。

一如既往,感谢阅读。如果你想知道我什么时候发表新文章,请考虑在这里注册一个电子邮件提醒。

如果你不是一个媒体订阅者,那就注册吧,这样你就可以每月花 5 美元阅读尽可能多的文章。在这里注册,我将赚取一小笔佣金。

获取代码

你可以在我的 Github 页面上找到这篇文章和其他文章的样本代码。

Python 熊猫数据帧到 Google Sheets for Tableau 公共直播

原文:https://towardsdatascience.com/python-pandas-dataframe-to-google-sheets-for-tableau-desktop-live-cc1f86982bca?source=collection_archive---------27-----------------------

博客的第二部分—

实时画面公共可视化的自动化 ETL

https://public.tableau.com/profile/eklavya.saxena#!/viz home/CoronavirusCOVID-19 cases world wide/新冠肺炎 _Country

T 他的博客是【LIVE Tableau 公共可视化自动化 ETL 的一部分,分为三个部分,即:

  1. 启用 Google Sheets API 并创建凭证
  2. 将 Python 连接到 Google Sheets 并导出数据帧
  3. 使用 Google Sheets 启用 Tableau 公共直播

1.启用 Google Sheets API 并创建凭证

https://console.developers.google.com/

访问您的 Google API 控制台是连接 python 脚本和 google sheets 的第一步。循序渐进地启用 google sheets API 并创建所需的凭证。

1.1 创建一个项目

  1. 点击左上角下拉菜单中的选择一个项目,将会打开一个弹出窗口
  2. 在弹出窗口的右上角,点击'新建项目,这将带您进入一个新窗口
  3. 给你的项目取一个合适的名字(例如:covid-viz-data)。您可以保持'位置** '字段不变,并点击'创建*

1.1 GIF 创建项目

1.2 启用 Google Sheets API 和 Google Drive API

  1. 从左侧窗格中选择''(在'仪表板'下),这将把您重定向到' API 库'窗口,其中有一个搜索 API 和服务的选项
  2. 在字段' 中键入 Google Sheets API '并从结果中选择它,这将重定向到 Google Sheets API 窗口
  3. 点击启用,为您在上一步中创建的项目启用它

类似地,启用 Google Drive API ,因为稍后导入的 python 库可能会使用上述两个 API 的功能。

启用 Google Sheets API 的 1.2 GIF

1.3 创建访问 API 的凭证

您可以在 Google Sheets API 窗口的右侧选择“创建凭证,或者如果您在仪表板上,从步骤 1 开始。

  1. 从左侧窗格中选择“凭证”(在“”下)。这将在右侧向您显示'凭证窗格

  2. 点击顶部的“创建凭证”选项,这将显示一个下拉菜单

  3. 单击下拉菜单中的“帮助我选择选项,这将重定向到标题为“将凭证添加到您的项目”的窗格

  4. 在这个'将凭证添加到您的项目中'窗格中跟随:

    步骤 1: ' 找出您需要哪种凭证 '
    您正在使用哪个 API?— Google Sheets API
    你会从哪里调用这个 API?— Web 服务器 您将访问哪些数据?— 应用数据 您打算将此 API 与 App Engine 或 Compute Engine 一起使用吗?— 不,我现在没有使用它们 ,单击“我需要什么凭证?根据我们输入的建议

    步骤 2:创建服务帐户
    服务帐户名称— (例如:covid-data-update)
    角色— 编辑器(从下拉列表中选择“项目,然后选择“编辑器”)
    服务帐户 ID —自动创建的
    密钥类型—
    这将要求您保存凭证。允许访问您的云资源的 json 文件— 因此安全地存储它

1.3 GIF 到 1.3 创建访问 API 的凭证

1.4 在中与客户电子邮件共享谷歌表单。json 凭证文件

现在我们有了访问 API 的秘密凭证(保存在。json 格式),我们需要确保目标 google sheet 与以该格式生成的客户端电子邮件共享。json 文件。

  1. 从中的“ client_email ”键复制电子邮件地址值。json 文件
  2. 创建一个新的 google 工作表,用于导出数据
  3. 打开表单后,点击右上角的共享
  4. 粘贴复制的电子邮件地址,并授予其“Can e dit ”访问权限

1.4 GIF 与客户端电子邮件共享谷歌表。json 凭证文件

恭喜你!我们已经成功地从 Google API 控制台启用了 Google Sheets API ,并创建了通过 python 脚本访问该 API 的凭证。现在,让我们进入第二部分。

2.将 Python 连接到 Google Sheets 并导出数据帧

https://developers.google.com/sheets/api/quickstart/python

虽然 Google 创建了 Google Sheets API,但是他们当然没有留下来为 Python QuickStart 创建一个精美的指南。我强烈推荐参考它,因为额外的文档/指南提供了使用 Google Sheets 的巨大可能性。

那为什么是这个博客呢?
快速入门要求你安装 3 个库,分别是Google-API-python-clientgoogle-auth-httplib2google-auth-oauthlib 。但是,从大量的 python 库来看,我们有:

pyg Sheets——一个简单、直观的 python 库,通过 google Sheets API v4 访问 Google 电子表格

这一部分将利用 pyghseets 导出数据框架到谷歌表。让我们开始吧:

import sys
!{sys.executable} -m pip install pygsheets

为什么我没有使用!pip install pyghseets?在 Jupyter 中,上面的代码确保您运行的是与当前 Python 内核相关联的 pip 版本。另外,仅供参考,shell 环境和 Python 可执行文件是断开的。点击此处了解更多信息。

import pygsheetsclient = pygsheets.authorize(service_file='/Users/eklav/**credentials.json**')
print("-----------------Authorized--------------------")

安装完成后,下一步当然是导入库。然后,使用[authorize](https://pygsheets.readthedocs.io/en/stable/reference.html#authorization)功能创建一个变量client,用 google 帐户认证 python 脚本(或应用程序)。

sheet = client.open('COVID-19')
print("-----------------Sheet Opened------------------")

现在,使用[open](https://pygsheets.readthedocs.io/en/stable/reference.html#pygsheets.client.Client.open)功能按标题(例如:新冠肺炎’)返回电子表格(在上一部分创建),并将其赋给变量sheet

wks = sheet[0]
print("-----------------First Sheet Accessed----------")

为了访问第一个工作表,将工作表sheet的第0个索引分配给变量wks

wks.set_dataframe(df_COVID,(1,1))
print("-----------------Data Updated------------------")

现在,使用工作表wks.set_dataframe功能将' df_COVID '*和' (1,1) '分别赋值给' df '和' start '参数。
值“ (1,1) ”是指电子表格的 A1 单元格。

要了解 dataframe ' df_COVID 是如何策划的,请参考博客的第一部分—从 GitHub 提取数据并自动运行或调度 Python 脚本

这就把我们带到了这一部分的结尾。我们启用了 API 和凭证,使用它们将 Python 连接到 Google Sheets——您的免费云存储。

3.使用 Google Sheets 启用 Tableau 公共直播

正如在母博客中提到的,最终是时候打破 Tableau Public 不能拥有实时数据的神话了。到目前为止,我们已经有了一个由 Windows 任务调度器自动运行的 Python 脚本,它反过来更新 Google 工作表。这张表将成为我们在 Tableau Public 上发布的仪表盘或可视化数据的来源。

3.1 将 Tableau 连接到 Google Sheet

我将不再详述一个众所周知的步骤——从 Tableau 起始页中选择一个数据源。如果需要,请遵循下面的 GIF:

3.1 GIF 将 Tableau 连接到 Google Sheet

好了,现在你可以根据需要用来自你的 Google Sheets 的实时数据创建可视化了

3.2 在 Tableau Public 上发布工作簿

虽然你有一个与谷歌工作表的实时连接,它必须直接发布工作簿。登录https://public.tableau.com服务器,分享即可。

但是,问题就在这里!将弹出以下错误:

您要发布到的 Tableau 服务器要求对数据源启用提取。使用数据菜单启用以下数据源的提取:

需要数据提取"

现在的问题是— 数据提取???

从 Google Sheets 获取数据的全部意义在于拥有实时连接。这就是我们认为 Tableau Public 只处理摘录的地方。

但是,Tableau 还有更多的服务——不要眨眼,直接连接到“ Extract ”。现在,当您共享时,勾选显示以下内容的复选框并保存:

“保持我的数据与 Google 工作表同步,并嵌入我的 Google 凭据”

点击“保存”按钮后,您将被重新定向到 Tableau Public,您的仪表板已发布。向下滚动并注意到“请求更新按钮。此按钮用于强制更新仪表板,从 Google 工作表中访问最新数据。不然不然我经历的 Tableau 每天自动刷新仪表盘。

答对了。

3.2 在 Tableau Public 上发布工作簿的 GIF

参考

感谢您的阅读!我希望这个博客揭示了 Tableau 公共有趣的一面。继续下去,让你的可视化生活。如果这篇文章是有帮助的,分享它。

请在评论中告诉我:

  1. 如果你觉得这有用或没用,或者
  2. 如果您想了解 Tableau 可视化中使用的不同功能的如何使用

[## eklavyasaxena/新冠肺炎

来自 JHU CSSE GitHub Repo 的 ETL 创建 Tableau 可视化。ETL: Extract 中执行的步骤。GitHub 中的 csv 文件…

github.com](https://github.com/eklavyasaxena/COVID-19) [## Eklavya Saxena -印度|职业简介| LinkedIn

精通数据的分析师和有抱负的数据科学家,拥有 2 年以上的销售或客户行业经验…

www.linkedin.com](https://www.linkedin.com/in/eklavyasaxena/)

Node.js 应用程序中的 Python 和 Pandas

原文:https://towardsdatascience.com/python-pandas-in-node-js-application-47a76ae42a2a?source=collection_archive---------9-----------------------

使用 Python-Pandas 和 node . js-Express 的新冠肺炎时间序列聚合器 API 示例

NodeJS 和 Python 插图作者 Chaeyun Kim

在数据科学领域,我们都知道 Python 是处理数据管理、分析、可视化、ML 等等的最佳工具之一。同样, Node.js 是用于服务器端的 JavaScript 运行时环境,根据其经济效益、快速响应时间等,它是最流行的 web 架构工具之一。从编程语言流行指数看(PYPL): PythonJavaScript 是前 1 & 3 大流行语言。

编程语言流行 2020 年 5 月(截图来自http://pypl.github.io/PYPL.html作者)

从我的经验来看,我看到大多数 Python 爱好者都试图用 Python 写所有东西。大多数 Node.js Volk 试图用 JavaScript 进行数据清理和操作…(对于所有的回调有点痛苦…)互联网上的一些博客试图比较 Node.js 和 Python,发现 Node.js 在 Web 开发方面很棒,Python 在数据科学方面很棒。实际上,我们不需要总是坚持使用同一种编程语言,因为有很多方法可以一起使用它们。在本文中,我将向您展示一个如何从 Node.js web 应用程序中使用 Python 脚本的示例。

示例:

让我们用 Node.js & Pandas 构建新冠肺炎时间序列聚合器 API

在本文中,我将展示一个如何创建一个简单的 API web 应用程序的示例,在该应用程序中,用户可以使用 Node.js 和 Express 框架请求新冠肺炎数据集和时间序列聚合间隔。有趣的是,我们将把 Python 和 Pandas 完成的时间序列聚合也集成到应用程序中。

支持时序聚合的新冠肺炎快速 API 的简单节点(启用)

随后,开发人员可以使用这样的 API 应用程序,通过任何 JavaScript 库在 web 应用程序中轻松呈现图表/地图/仪表板;如 Apexchart.jsHighchart.jsChart.js 。下图显示了对每日新冠肺炎数据集使用简单 Apexchart 的示例。

用 Apexchart.js 展示新冠肺炎确诊病例演示(作者)

下图显示了该应用程序的整体结构:

本例的系统架构(作者)

A 部分:Python 和 Pandas 用于时间序列分析

首先,让我们从 Python 应用程序开始,我将从我的关于用 Python 对新冠肺炎时间序列进行分析的文章中选取一个例子。简而言之,我们将使用一个简单的 Python 脚本来读取和分析从 JHU CSSE 到熊猫数据帧的新冠肺炎数据集。然后,按“国家/地区”级别对数据集进行分组,转置数据帧,将日期/时间列设置为索引列,对确诊新冠肺炎病例最多的国家进行排序,并根据输入的国家编号选择排名靠前的国家。之后,用输入的时间间隔对数据集进行重采样,并返回。json 输出给用户。以下脚本显示了整个脚本:

covid 19 aggregator . py(作者示例脚本)

这个脚本有两个参数;第一个参数(arg1)是确诊新冠肺炎病例最多的国家数量,第二个参数(arg2)是累计时间间隔。例如,如果我们想要获得来自前三个国家的已确认的新冠肺炎病例和每月的汇总数据,那么我们可以使用以下命令运行 Python 脚本:

**$ python covid19aggregator.py 3 'M'**

然后,您将获得以下结果(截至 2020 年 5 月 10 日):

执行带有 3/‘M’个参数covid 19 aggregator . py的示例结果(作者的示例结果)

您可以看到时间索引被写成了时间戳,我们将这样保存它,因为它便于以后在基于 web 的可视化工具中使用。

B 部分:带有 Express 应用程序的 Node.js

在这一部分中,我们将从创建一个简单的 Node.js & Express 应用程序开始。您可以使用以下命令启动项目并安装 express:

**$ npm init
$ npm install express --save**

然后,使用下面的示例脚本为 Node.js web 服务器创建一个server.js文件。如果你是新来的快递,请看这里的文档。在第 1 部分中,我们在端口 3000 上创建了一个简单的 express 应用程序。你可以换到任何你喜欢的港口。在第 2 部分中,我们定义了一个 GET 请求路由到“http://localhost:3000/covid _ 19 _ time series”,并使用child_process生成 Python 子进程,还将 URL 查询参数‘numberOfCountries’‘aggregationInterval’传递给 Python 进程。您可以在这里看到完整的 Node.js 服务器脚本:

NodeJS 服务器 。js 与衍生covid 19 aggregator . pyPython 进程(作者示例脚本)

完成了!现在,这个 Node.js 服务器已经完成,当用户调用以获取 COVID 19 数据时,它会生成 Python 子流程。让我们通过运行一个服务器来测试它:

**$ node server.js** server running on http://localhost:3000

让我们在 web 浏览器上查看结果:
(在这里,您可以传递任意数量的国家/聚合间隔)

[**http://localhost:3000/covid_19_timeseries?numberOfCountries=5&aggregationInterval=M**](http://localhost:3000/covid_19_timeseries?numberOfCountries=5&aggregationInterval=M)

网络浏览器上的示例结果。(作者截图)

所以,大概就是这样。现在,您已经有了一个用 Node.js 和 Python 构建的简单 API 应用程序。请注意,这个示例是为了展示将它们集成在一起的概念,可以在 Node.js 中改进这些脚本以获得更好的 API 路由结构,在 Python 中改进这些脚本以获得更复杂的数据操作工作流。

结论

本文展示了一个示例,说明如何使用 NodeJS 通过 Pandas 生成一个 Python 进程,并将结果直接返回给 API 调用。通过这种方式,我们可以灵活地将所有很酷的数据 Python 脚本与流行的 JavaScript web 框架集成在一起。我希望你喜欢这篇文章,并发现它对你的日常工作或项目有用。如果您有任何问题或意见,请随时给我留言。

关于我&查看我所有的博客内容:链接

安全健康健康!💪

感谢您的阅读。📚

Python 熊猫迭代数据帧

原文:https://towardsdatascience.com/python-pandas-iterating-a-dataframe-eb7ce7db62f8?source=collection_archive---------5-----------------------

了解使用 Python 迭代熊猫数据帧的不同方法

Maicol SantosUnsplash 上拍摄

介绍

作为一名数据科学家,我们有时会遇到低质量的数据。为了取得成功,我们需要能够在任何分析之前有效地管理数据质量问题。谢天谢地,有几个强大的开源库,我们可以利用它们来有效地处理数据,比如 Pandas 。今天我们将看看我们可以循环访问一个数据帧并访问其值的不同方法。迭代数据帧可以被合并到初始探索性数据分析之后的步骤中,以开始清理原始数据。

入门指南

熊猫是什么?

对于那些刚接触数据科学或不熟悉 Pandas 的人来说,Pandas 是一个用 Python 编写的开源库。它提供了易于使用的现成功能来接收和分析关系数据。Pandas 支持多种文件类型的消费,例如 CSV、Excel、JSON、XML、HTML 和 SQL 等等。

安装熊猫

安装 Pandas 最简单的方法是使用 PyPI ,它通过在终端运行命令pip install pandas使用pip从源代码安装 Pandas。具体操作系统的详细安装说明可以在 Pandas 入门页面上找到,或者如果您正在使用 PyCharm 说明可以在学习 Pandas Profiling 中找到。

熊猫数据框

对于大多数人来说,Pandas 将数据收集到两个对象中的一个:

  • 系列:系列是一维 ndarry 对象。
  • 数据帧:数据帧是一个二维数据结构,包含带标签的行和列。

显示系列和数据帧的构造函数的 Python 代码片段。

迭代数据帧

对于本例,我们已经创建了一个带有明确命名的行和列的 DataFrame,以帮助您入门并演示数据结构。通常,我们只命名列,并允许行索引自动生成一个数值范围。

Python 代码片段将生成一个 3 列 5 行的熊猫数据帧。

控制台输出显示了上述 Python 代码片段的结果。

执行完 Python 代码片段后,您应该会收到类似上面的输出。在这里,您可以清楚地看到 Pandas DataFrame 对象是如何使用一系列行和列来构造的。

DataFrame.iterrows()

遍历数据帧的第一种方法是使用 Pandas .iterrows(),它使用索引行对遍历数据帧。

展示如何使用熊猫的 Python 片段。iterrows()内置函数。

控制台输出显示了使用。iterrows()。

在 DataFrame 上调用了.iterrows()之后,我们就可以访问作为行标签的index和代表行本身值的序列row。上面的代码片段利用了Series.values,它为被引用的行返回每列中所有值的 n 数组。

.iterrows()中,row变量是 Series 类型,这意味着我们可以通过数据帧的指定列来访问值。例如,如果我们只对column_a感兴趣,我们可以使用下面的代码片段只返回那些值。

Python 代码片段显示了如何在使用?iterrows()。

上面的代码片段还演示了一种通过row.get('column_name', default_value)而不是row['column_name']来检查行中的列的更安全的方法。如果我们在寻找一个不存在的列,row['column_name']会引发一个KeyError异常。

DataFrame.itertuples()

迭代数据帧的下一个方法是.itertuples(),它返回一个迭代器,包含代表列名和值的名称元组。

显示熊猫语法的 Python 片段。itertuples()内置函数。

显示调用结果的控制台输出。数据帧上的 itertuples()。

这个方法仍然提供了通过语法row.column_name隔离单个列的能力。如果我们只需要返回一个元组,我们可以将name=Noneindex=False传递给.intertuples(),这将从每一行中删除指定的列和索引。

最佳实践

虽然能够使用.iterrows().itertuples()迭代数据帧很方便,但一般来说,建议不要这样做,因为对于较大的数据帧,性能会很慢。通常,当人们想要迭代一个数据帧时,需要添加一个计算列或者重新格式化一个现有的列。Pandas 通过其内置函数.apply()提供这种类型的功能。.apply()函数为更新数据帧提供了更有效的方法。熊猫申请权力用户深入了解熊猫.apply()

摘要

Pandas 提供了几种方法,我们作为数据科学家可以使用这些方法来迭代数据帧,比如.iterrows().itertuples().iterrows().itertuples()都提供了强大的安全方法来访问数据帧行值。虽然许多具有编程背景的新数据科学家可能倾向于熟悉数据帧上的循环,但 Pandas 通过内置的 apply 函数提供了一种更有效的方法。

感谢您花时间阅读我们的故事,我们希望您发现它有价值!

Python 熊猫合并数据帧

原文:https://towardsdatascience.com/python-pandas-merging-dataframes-aebbf898a9ff?source=collection_archive---------50-----------------------

在 Python 中合并熊猫数据帧的快速操作指南

milkovíUnsplash 上拍摄的照片

介绍

作为数据科学家,我们经常会发现我们需要同时分析来自多个数据源的数据。为了成功实现这一点,我们需要能够使用各种方法有效地合并不同的数据源。今天我们将看看如何使用 Pandas 内置的.merge()函数,通过几种不同的连接方法来连接两个数据源。

入门指南

对于那些刚刚接触数据科学或者还没有接触过 Python Pandas 的人,我们建议首先从 Pandas 系列& DataFrame ExplainedPython Pandas 迭代 DataFrame 开始。这两篇文章都将为您提供安装说明和今天文章的背景知识。

熊猫合并

Pandas 内置函数.merge()提供了一个强大的方法,使用数据库风格的连接来连接两个数据帧。

句法

上面的 Python 片段显示了熊猫的语法。merge()函数。

因素

  • right —这将是您要加入的数据框架。
  • how —在此,您可以指定两个数据框的连接方式。缺省值是inner,但是,对于左外连接,您可以通过left,对于右外连接,您可以通过right,对于全外连接,您可以通过outer
  • on —如果两个数据帧都包含一个共享列或一组共享列,那么您可以将它们作为键传递给on进行合并。
  • left_on —在此,您可以指定一列或一列标签,您希望将这些标签加入左侧数据框。当您希望在两个数据框架中连接的列的名称不同时,此参数非常方便。
  • right_on —与left_on相同的条件适用于右侧数据帧。
  • left_index —如果您想使用索引连接左侧数据框,则通过True
  • right_index —如果您想使用索引连接正确的数据帧,则通过True.
  • sort —如果你希望连接的键按字典顺序排序,你可以在这里输入True
  • suffixes —如果两个数据框架共享列标签名,则可以指定要应用于重叠的后缀类型。左侧默认为_x,右侧默认为_y
  • indicator —如果您想标记行的来源,您可以将该参数设置为True。该标志将指示行关键字是只出现在左数据帧中,还是出现在右数据帧中,还是同时出现在两个数据帧中。
  • validate —在这里,您可以查看数据帧是如何连接的,以及键之间的关系。您可以通过下面的1:1来检查左右数据帧中的键是否唯一,1:m来检查合并的键是否只对左数据帧唯一,m:1来检查合并的键是否只对右数据帧唯一。

实际应用

下面我们将通过几个例子来学习如何使用合并功能。下面提供的代码片段将帮助您创建两个数据帧,我们将在故事的剩余部分使用它们。

上面的 Python 片段创建了两个数据帧,您可以使用它们来继续下面的示例。

上面的控制台输出显示了执行 Python 片段创建两个数据帧的结果。

内部连接

内部连接方法是 Pandas merge default。当您传递how='inner'时,返回的数据帧将只包含来自两个数据帧之间共有的连接列的值。

上面的 Python 片段演示了如何使用内部连接来连接两个数据帧。

上图显示了内部连接两个数据帧后的控制台输出。

从上面控制台输出的屏幕截图中,我们可以看到内部连接对两个数据帧的影响。由于值acef不在两个数据帧之间共享,因此它们不会出现在控制台输出中。输出还演示了在处理两个数据帧之间的共享列标签时的默认后缀应用程序。

左连接

Pandas left join 的功能类似于 SQL 中的 left outer join。返回的数据帧将包含来自左侧数据帧的所有值,以及在来自右侧数据帧的合并期间匹配连接键的任何值。

上面的 Python 片段显示了使用左连接合并两个数据帧的语法。

上面的屏幕截图显示了使用左连接合并两个数据帧的控制台输出。

如果右边的数据帧与合并列NaN中的值不匹配,则将在返回的数据帧中插入而不是数字

右连接

熊猫右连接执行与左连接类似的功能,但是连接方法应用于右数据帧。

上面的 Python 代码片段显示了使用 Pandas right join 合并两个数据帧的语法。

上面的屏幕截图显示了使用右连接合并两个数据帧的结果。

如上所述,在左侧数据帧中,右侧不存在的任何键都将插入一个NaN值。

外部连接

Pandas 外部连接合并了两个数据帧,实质上反映了左右外部连接的组合结果。外部连接将从左右两个数据帧返回所有值。当 Pandas 在合并数据帧中找不到值时,将使用NaN来代替。

上面的 Python 片段显示了使用外部连接来连接两个数据帧的语法。

上面的屏幕截图显示了使用外部连接合并两个数据帧的结果。

当使用外部连接合并两个数据帧时,了解新数据帧中的记录来自何处有时会很有用。您可以通过将indicator=True作为参数传递给.merge()函数来查看记录的来源,该函数将创建一个名为_merge的新列。

摘要

要想成为一名成功的数据科学家,您需要经常同时熟练地处理来自多个数据源的数据。我们经常需要组合数据源,有时是为了丰富数据集或在当前数据中合并历史快照。Pandas 使用内置的.merge()函数为连接数据集提供了一个强大的方法。Pandas .merge()函数在连接类型方面提供了灵活性,您可以创建这些类型来实现所需的输出。

感谢您花时间阅读我们的故事,我们希望您发现它有价值!

Python 陷阱:可变默认参数

原文:https://towardsdatascience.com/python-pitfall-mutable-default-arguments-9385e8265422?source=collection_archive---------14-----------------------

一种让几乎所有人都感到不快的语言特征

照片由 uomo liberoUnsplash 上拍摄

许多编程语言允许您编写接受可选参数的函数。Python 就是其中之一。这是一种使函数调用简洁(当参数可以省略时)和灵活(当需要特定的参数值时)的简便方法。但是粗心的人也潜伏着危险。

一个例子

为了便于说明,我们来看一个简单的算法。假设您有一个类似于aaabbaccaaa的字符串,并且您想要计算该字符串中每个字母的个数。您需要一个函数来返回一个字典,该字典的键是字母,值是每个字母在字符串中出现的次数的正整数。

下面是这种思想作为 Python 函数的简单实现。

增强:累积计数

这个功能起作用。这正是我们想要的。但现在让我们添加一个转折。如果有时我们想对一系列字符串进行计数并组合结果呢?我们希望选择多次调用Tally,最终得到一个包含字母计数的字典。

一种方法是将count字典作为函数的另一个参数:

这是一个更灵活的函数,因为它可以处理一系列字符串,而不仅仅是单个字符串。当然,如果我们愿意,我们仍然可以单独处理字符串:

简洁的代码,天真的方式

如果分开计数是我们最经常想要的呢?不必在每个调用中都键入空字典参数,这当然很好。不熟悉 Python,但熟悉其他编程语言中的默认参数的开发人员通常会遵循以下方法:

  • 他们在网上寻找 Python 是否允许默认函数参数。
  • 他们发现答案是肯定的。
  • 他们很快就写出了类似这样的代码:

哦不,它坏了!

这是编写Tally函数的最显而易见的方式,这样你就不需要传入一个显式的空字典。它看起来确实是对的。但这是错误的。有一个细微的瑕疵会咬到你!让我们测试一下,看看会发生什么:

第一行完全按照我们的预期工作。它找到一个a,一个b,一个c。但在那之后,事情变得古怪了。这里到底发生了什么事?

对错误的解释

核心问题是,在 Python 中,默认参数的值只计算一次,当函数被声明为时。默认的参数语法count = {}导致 Python 解释器创建一个空字典,但是每次调用函数时都是相同的字典对象。

为了澄清问题,我们的中断函数的行为与此相同:

为什么 Python 会这样?

这不是 Python 中的 bug。即行为是故意的,不是偶然的。

然而,如果我们偏离事实,进入舆论世界,许多人——我也是其中之一——认为这是 Python 的一个设计缺陷,尽管它有合理的技术原因。这种行为违背了函数式编程的理念。这使得编写一个返回值仅取决于其参数的确定性函数变得更加困难。

更根本的是,它违反了最小惊喜原则。这种行为不是大多数程序员所期望的,这导致了错误。

用一个工具的危险怪癖来发泄自己的挫败感是很自然的。但事实就是如此。这是 Python 的行为,不会改变。改变语言中的这种古怪为时已晚,因为这样做会破坏许多依赖于它的现有程序。作为专业开发人员,理解我们的工具并正确使用它们是我们的责任。

如何解决这个问题

这是否意味着使用默认函数参数太危险了?一点也不。解决这个问题是可能的,这样我们仍然可以编写一个按我们想要的方式运行的Tally函数。这只是避免使用一个可变的默认值的问题。

每次调用函数时,默认情况下创建一个新的可变对象的常见方法是使用不可变的占位符值,如None。该函数查找占位符值,如果找到,就用一个全新的可变类型实例替换它。

这听起来很抽象,所以为了清楚起见,让我们将这个想法应用到现在熟悉的Tally函数中。

现在我们终于有了一个满足我们所有要求的函数。当给定一个字符串参数时,它会计算该字符串中的不同字符。当给定一个字符串参数和一个字典参数时,它将字符串的字母计数添加到给定的字典中。

最后的想法

如果您想要的默认值已经是一个不可变的类型,就没有必要担心这些。但是有很多可变类型需要小心,比如列表、字典、集合和大多数类实例。如果元组包含可变成员,那么它也是有风险的。

即使您的函数没有改变可选参数,如果您的函数向调用者公开可变值,也会出现不希望的副作用。例如,如果函数返回可变值,并且调用代码修改了它的状态,那么对该函数的后续调用将会看到这些修改,即使它们没有被显式传入。更糟糕的是,完全不相关的代码(可能在不同的模块中)可以调用同一个函数,从而污染彼此的内部工作。

我最近被这个问题弄得焦头烂额。我希望这篇文章能让你避免我在 Python 代码中遇到的那种令人困惑的错误。从自己的错误中学习是令人钦佩的,但我想你会同意从别人的错误中学习更令人愉快!

脚注

  1. 关于函数定义的官方 Python 文档是这样说的:默认参数值在函数定义执行时从左到右求值。这意味着当函数被定义时,表达式被计算一次,并且相同的“预先计算的”值被用于每个调用。当缺省参数是一个可变对象(比如一个列表或一个字典)时,理解这一点尤其重要:如果函数修改了对象(例如,通过向列表追加一个项目),缺省值实际上被修改了。这通常不是我们想要的。
  2. 参见中有趣的讨论,这个堆栈溢出线程用 Python 讨论这个设计选择。Python 的符号作用域的工作方式不同于其他语言。另外,Python 函数声明是可执行语句,而不是像其他语言那样的静态声明。这些因素导致了 Python 行为方式的技术原因。我提出“设计缺陷”的指责是出于尊重的理解,即在调用时评估默认表达式会给 Python 的设计者带来更严重的问题。

Python 陷阱——期待意想不到的事情

原文:https://towardsdatascience.com/python-pitfalls-expecting-the-unexpected-2e595dd1306c?source=collection_archive---------17-----------------------

通过避免 Python 代码中的这些常见问题和陷阱,节省您的调试时间

不管你用哪种编程语言编写代码,你可能都遇到过很多奇怪的、看似无法解释的问题,这些问题最终都变成了这种特定语言的愚蠢错误或怪癖。Python 的目标是成为干净简单的语言,但它也有一些让初学者和有经验的软件开发人员感到惊讶的陷阱和怪癖。因此,为了避免对您最喜欢的编程语言中的一些奇怪问题产生不必要的愤怒和沮丧,下面列出了一些常见的 Python 陷阱,您应该不惜一切代价避免这些陷阱。

Meor MohamadUnsplash 上拍摄的照片

可变的默认参数不是一个好主意

为函数设置默认参数非常常见,对于定义可选参数或通常使用相同预定义值的参数非常有用。但是,将默认参数设置为可变值(如listdict)会导致意外行为:

使用可变值作为默认参数的问题是,每次调用函数时,默认参数都没有初始化。相反,最近使用的值将被传入,这在可变类型的情况下是一个问题。为了避免这个问题,你应该总是使用None或者其他不可变的类型,并如上所示对参数进行检查。

尽管这看起来很麻烦,也是一个问题,但这是一种有意的行为,也可以利用来制作缓存函数,这些函数可以使用持久可变的默认参数作为缓存:

与上面的默认参数类似的行为也可以在dict.setdefault(key, value)中看到。在下面的代码中,我们可以看到一些令人惊讶的结果:

尽管我们没有接触上面的data字典,但它已经通过添加默认值val进行了修改。这是因为当键丢失时,传递给setdefault的默认值被直接分配到字典中,而不是从原始值中复制。为了避免这个问题,请确保在使用setdefault时不要重用值。

NaN(非)反身性

处理浮点数和非整数通常会很困难和烦人,但是当你进入非数字无穷大的领域时,这就变得特别奇怪了。因此,让我们通过与这些值进行一些比较来证明这一点:

上面的代码显示了NaN的非自反性。Python 中的NaN即使和自身比较也永远比不上。所以,如果你需要测试NaNinf,那么你应该使用math.isnan()math.isinf()。在处理可能产生NaN的代码时,也要小心任何其他算术运算,因为它会在所有运算中传播,而不会引发异常。

Python 通常很聪明,通常不会从数学函数中返回NaN,例如math.exp(1000.0)将返回OverflowError: math range error,而math.sqrt(-1.0)math.log(0.0)都将返回ValueError: math domain error,但是您可能会遇到使用 NumpyPandas 的情况,如果您这样做了,请记住不要尝试比较NaNs是否相等。

后期绑定闭包

关于 Python 中的作用域和闭包,有一些陷阱、陷阱和惊喜。我认为最常见的是闭包中的后期绑定。让我们从例子开始:

上面的代码显示了循环中函数的定义,然后被添加到一个列表中。随着每次迭代,i变量增加,定义函数中的i变量也增加,对吗?错了。

后期绑定导致所有函数都假定值为 2(来自上一次迭代)。这是因为闭包中定义了所有的函数——全局函数。因此,它们都引用同一个在循环中变异的i

解决这个问题的方法不止一种,但我认为最干净的方法是使用functools.partial:

使用partial我们可以创建新的带有预定义i的可调用对象,强制变量立即绑定从而解决问题。然后,当我们想要实际调用函数时,我们可以提供剩余的原始参数n

重新分配全局变量

使用大量的全局变量通常是不鼓励的,并且被认为是一种不好的做法。然而,使用一些全局变量是有正当理由的——例如定义各种标志,这些标志可用于设置函数的日志级别。

但是如果你决定翻转(重新分配)这个标志呢?嗯,它会引起严重的头痛:

看上面的代码,你可能会认为在执行了some_func()之后,全局flag变量的值会变成True,但事实并非如此。some_func声明新的局部变量flag,将其设置为True,然后在函数体结束后消失。全局变量永远不会被触及。

不过,有一个简单的解决办法。我们需要首先在函数体中声明我们想要引用全局变量,而不是使用局部变量。我们用global <var_name>做这个——在这个例子中是global flag:

你可能遇到的另一个【有趣】变量问题是超出范围变量的修改——幸运的是,这更容易调试和修复。与前面的问题类似,这是由于操作在外部作用域中定义的变量引起的:

这里我们尝试在函数范围内增加变量var,假设它会修改全局变量。但同样,这是错误的。

当你修改变量时,它就变成了这个作用域的局部变量,但是你不能增加之前没有声明的变量(在当前作用域中),所以UnboundLocalError被抛出。

在全局变量的情况下,这也可以使用global <var_name>来解决。这种所谓的作用域错误也可能发生在嵌套函数中,此时您应该使用nonlocal <var_name>来引用最近的外部作用域中的变量:

定义元组的正确方法

几乎每个 Python 开发人员都有一个根深蒂固的误解,即元组是由括号定义的。与像dictset这样的可重复项不同,Python tuple是通过逗号分隔元素来定义的。

源自这种误解的错误通常出现在我们试图用单个元素定义元组时:

在上面的代码片段中,我们可以看到有必要在单数元素后添加,以使 Python 将其识别为 tuple。我们也可以完全省略括号,这在返回多个值的return语句中很常见。

上面的最后一个例子显示了一个类似的陷阱。如果您忘记用逗号分隔元素,Python 将使用隐式串联,使其成为类型字符串的单个值。这种隐式连接可以发生在代码中的任何地方,而不仅仅是在定义 tuple 时,所以如果你的程序有问题,一定要仔细检查你的字符串和 iterables。

索引字节值而不是字节字符串

当处理文件和其中的数据时,我们通常只使用 ASCII 或 UTF-8 字符串。然而,有时您可能不得不读写一些二进制数据,并且您可能会对索引和迭代它们的结果感到惊讶:

当索引到二进制字符串时,我们得到的不是字节字符串,而是整数字节值,换句话说,就是被索引字符的序数值。为了避免这种情况——尤其是在读取二进制文件时——最好总是使用text.decode('utf-8')来获得正确的字符串。但是,如果您想将原始数据保存为二进制字符串,那么您可以使用chr(c)将单个字符转换为字符串表示。

使用取反变量进行索引

切片和切块是 Python 最方便的特性之一,包括指定负索引的能力,但是如果不小心,可能会得到意想不到的结果:

如果我们用除了-0之外的任何负值(变量)对一个序列进行切片,我们将得到预期的值,但是如果我们碰巧使用[-0:]进行切片,我们将得到整个序列的副本,因为它等同于[:]

为什么它一个也不返回!?

我把我的【最爱】留到了最后。很容易忘记函数是返回新值还是就地修改原来的。特别是当一般有两种类型的方法时——列出修改参数的方法,返回原地修改参数None字符串方法。**

我犯了太多次这样的错误。很容易忘记许多字符串或列表方法之一的行为,这可能会导致数小时的调试。所以,如果你在应该是整个字符串或列表的地方收到了None,那么仔细检查以确保你正确地使用了上面显示的所有方法。

结论

这是不可避免的,你会遇到这些或其他类似的陷阱和陷阱,这将导致很多愤怒和沮丧。通常情况下,解决这些问题的最好方法是暂时退后一步。去散步。去冲杯咖啡。或者至少深呼吸一下。大多数情况下,解决这样一个问题所需要的就是把它留一会儿,以后再回来。

如果这没有帮助,也许是时候进行一些橡皮鸭调试或引入另一双眼睛(坐在你旁边的同事)。通常,当你开始向别人解释问题时,你会立刻意识到问题到底出在哪里。

当您最终找到错误并设法解决它时,花一点时间想想您可以做些什么来更快地找到它。下一次你遇到类似的问题时,你也许能更快地解决它。

**本文原帖martinheinz . dev

* [## Python 调试终极指南

让我们探索使用 Python 日志记录、回溯、装饰器等等进行调试的艺术…

towardsdatascience.com](/ultimate-guide-to-python-debugging-854dea731e1b) [## 编写更加地道和 Pythonic 化的代码

使你的 Python 代码可读、有效、简洁和可靠的习惯用法和惯例。

towardsdatascience.com](/writing-more-idiomatic-and-pythonic-code-c22e900eaf83) [## Python 上下文管理器的魔力

使用和创建令人敬畏的 Python 上下文管理器的方法,这将使你的代码更具可读性、可靠性和…

towardsdatascience.com](/the-magic-of-python-context-managers-adb92ace1dd0)*

Python Power Tip:枚举类型

原文:https://towardsdatascience.com/python-power-tip-enumerated-types-9a1e606250a4?source=collection_archive---------27-----------------------

PYTHON 编程

表示有限选项集的正确方式

照片由路易斯·汉瑟@shotsoflouisUnsplash 拍摄

通常,程序员希望在他们的代码中表示一些东西,这些东西的值必须属于预先确定的有限的值集合。例子包括:

  • 一周中的每一天:星期一,星期二,…,星期天。
  • 图像文件格式的类型:JPEG,PNG,GIF,…
  • 纸牌游戏中的花色:梅花、方块、红心、黑桃。
  • 有限状态机的状态。

不令人满意的替代品

为了解决这样的情况,许多编程语言支持枚举类型。Python 直到 2014 年 3 月发布 3.4 版才支持枚举类型。在那之前,Python 程序员不得不求助于一些不太理想的策略。

常见的解决方法是用唯一的整数值定义一些全局变量,如下所示:

然后剩下的代码可以根据需要使用CLUBDIAMONDHEARTSPADE来表示一副牌。

这种方法存在一些问题:

  • 这些全局变量是可变的。必须确保没有代码给它们赋予不同的值。
  • 没有类型检查。很容易将其他整数值与一套牌混淆,从而导致错误。

Python 最后添加了枚举类型

Python 的这一缺陷导致了各种第三方包的产生。在 2005 年有一个被拒绝的提议将枚举类型添加到 Python 标准库中。然后,在 2013 年 1 月,语言开发人员之间的一次电子邮件对话再次引发了对标准支持的考虑。结果是 PEP 435 ,一个向标准库添加新enum模块的提议。Python 的创造者吉多·范·罗苏姆于 2013 年 5 月 10 日批准了 PEP 435。第二年enum模块首次出现在 Python 3.4 中。

定义典型的枚举类型

对于只需要一些可选值的简单情况,您可以遵循以下模式:

这就创建了一个枚举类型Suit,它定义了四种花色的符号,称为成员。可选的装饰器@unique增加了一个健全性检查,确保所有成员都有惟一的值。如果您不小心添加了多个具有相同值的符号,那么在执行类声明时会出现一个ValueError异常。例如,以下代码将失败:

运行此代码会产生以下行为:

Traceback (most recent call last):
  File "cards2.py", line 2, in <module>
    class Suit(Enum):
  File "/usr/lib/python3.5/enum.py", line 573, in unique
    (enumeration, alias_details))
ValueError: duplicate values found in <enum 'Suit'>: Diamond -> Club

此时,您可以很快发现问题所在,即DiamondClub都具有相同的值:1。

使用枚举类型

Suit这样的枚举类型的成员是常量。在修复了Suit中的唯一性问题之后,这里有一些你可以用 Python 解释器尝试的例子。首先,如果您评估其中一个成员,您会看到它的表示:

>>> **s = Suit.Spade**
>>> **s**
<Suit.Spade: 4>

每个枚举成员还有一个name属性,该属性产生字符串形式的名称:

>>> **s.name**
'Spade'

每个成员还有一个value属性,它返回您给它的任何值:

>>> **s.value**
4

namevalue属性是只读的。这解决了我们上面提到的可变性问题:

>>> **s.value = 7**
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/types.py", line 141, in __set__
    raise AttributeError("can't set attribute")
AttributeError: can't set attribute>>> **s.name = 'Joker'**
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/types.py", line 141, in __set__
    raise AttributeError("can't set attribute")
AttributeError: can't set attribute>>> **Suit.Heart.value = 9**
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/types.py", line 141, in __set__
    raise AttributeError("can't set attribute")
AttributeError: can't set attribute

枚举成员可以直接相互比较是否相等:

>>> **s == Suit.Spade**
True>>> **s == Suit.Heart**
False>>> **s != Suit.Heart**
True

这允许您编写代码来处理替代情况,如下所示:

枚举成员充当字典键:

>>> **color = { Suit.Heart: 'red', Suit.Diamond: 'red',**
... **Suit.Spade: 'black', Suit.Club: 'black' }**>>> **color[Suit.Club]**
'black'

类型转换

如果在字符串中有枚举成员的名称,可以使用带括号的类型名称来获取相应的枚举成员。

>>> **text = 'Heart'**
>>> **Suit[text]**
<Suit.Heart: 3>

类型名还充当一个函数,当给定一个初始值作为参数时,该函数返回相应的成员。

>>> **Suit(3)**
<Suit.Heart: 3>

枚举类型是可枚举的

仅仅从它们的名字来看,枚举类型应该提供枚举它们包含的成员的能力是有意义的。事实也的确如此。类型名充当其成员的枚举数:

>>> **for x in Suit:**
...     **print(x)**
... 
Suit.Club
Suit.Diamond
Suit.Heart
Suit.Spade>>> **list(Suit)**
[<Suit.Club: 1>, <Suit.Diamond: 2>, <Suit.Heart: 3>, <Suit.Spade: 4>]

温和类型检查

我上面提到的一个问题是,可能会混淆不同种类的枚举值。让我们添加另一个枚举类型,看看当我们试图比较它们时会发生什么。

尽管Suit.ClubAnimal.Dog具有相同的关联值 1,但它们并不相等:

>>> **Suit.Club == Animal.Dog**
False

这是有道理的,因为SuitAnimal是不同的类型,一般来说不同的类型比较起来是不相等的:

>>> **Suit.Club == 1**
False>>> **Suit.Club == 'one'**
False

这有助于您避免编写代码混淆动物与卡片套装!

整数枚举

上面演示的Enum基类通常是创建枚举类型最有用的方法。但是,有时您希望枚举成员的行为类似于整数常量。在这种情况下,您可能不希望抽象类型成为表示特定整数常量的符号集合。也许您有一个外部 API,它将图像文件的格式报告为 1=PNG、2=JPEG 或 3=GIF。

在这种情况下,Python enum模块提供了另一个叫做IntEnum的基类。下面是如何定义一个不那么挑剔的枚举类型,其中成员的行为类似于整数常量:

现在成员ImageFormat.JPEG仍然拥有自己的枚举成员身份:

>>> **ImageFormat.JPEG**
<ImageFormat.JPEG: 2>

然而,当与整数 2 比较时,它匹配:

>>> **ImageFormat.JPEG == 2**
True

你甚至可以用它做数学,不像一个Enum的成员:

>>> **ImageFormat.JPEG + 1**
3>>> **Suit.Club + 1**
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'Suit' and 'int'

其他有用的Enum功能仍然有效,比如使用名称或值枚举和获取成员:

>>> **list(ImageFormat)**
[<ImageFormat.PNG: 1>, <ImageFormat.JPEG: 2>, <ImageFormat.GIF: 3>]>>> **ImageFormat(3)**
<ImageFormat.GIF: 3>>>> **ImageFormat['PNG']**
<ImageFormat.PNG: 1>

还有很多要学的

我们已经在这里介绍了 Python 枚举类型的基础知识,这足以让您入门。现在,您可以在代码中很好地使用枚举类型了。

然而,还有很多细节和细微差别。我鼓励你阅读下面链接的官方建议和文档页面。这两页都是深入理解这一重要语言特性的好读物。

参考

  1. PEP 435:将 Enum 类型添加到 Python 标准库:这是导致将enum模块添加到 Python 3.4+标准库的提议。
  2. Python 官方文档为 [enum](https://docs.python.org/3/library/enum.html) 模块。

Python:过程化编程还是面向对象编程?

原文:https://towardsdatascience.com/python-procedural-or-object-oriented-programming-42c66a008676?source=collection_archive---------2-----------------------

Python:是过程化编程还是面向对象编程?戴维·兰格尔在 Unsplash 上的照片

数据科学和机器学习

过程化和面向对象之间有点争议,我们为什么要关心它?

谁不知道 Python?
大多用于数据科学和机器学习。
让我们多讨论一下吧!

当你第一次学习一个程序时,你似乎在使用一种叫做过程化编程的技术。程序性程序通常是一系列指令,从一行的顶部开始一个接一个地执行。另一方面,面向对象的程序是围绕 well 对象构建的。你可以把物体想象成现实世界中存在的东西。例如,如果你要建立一个鞋店,商店本身就是一个对象。商店中的商品,例如靴子和凉鞋,也可以是对象。收银机会是一个对象,甚至一个售货员也会是一个对象。

与过程式编程相比,面向对象编程有几个优点,过程式编程是您最先学习的编程风格。

  • 面向对象编程使您能够开发大型的、模块化的程序,这些程序可以随时扩展。
  • 面向对象的程序对最终用户隐藏了实现。

面向对象的程序将关注每个对象的具体特征以及每个对象能做什么。

一个对象有两个基本部分,特征和动作。例如,销售人员的几个特征包括姓名、地址、电话号码和时薪,以及销售人员能做什么。这可能涉及出售一件物品或从仓库中取走物品。作为另一个例子,鞋子的特征可以是颜色、尺寸、样式和价格。鞋子可以做什么动作?鞋子是一个没有生命的物体,但是它可以,比如说,改变它的价格。

**In terms of English grammar:**A characteristic would be a noun. 
An action would be a verb.Real-world example: a dog. Some of the characteristics could be:
* weight
* colour
* breed
* height -> These are all nouns.What actions would a dog take? 
* bark
* run
* bite
* eat -> These are all verbs.

一个对象有特性和动作。特征有特定的名称。它们被称为属性,动作被称为方法。在鞋子的例子中,颜色、尺码、款式和价格被称为属性。改变价格的行为是一种方法。还有另外两个术语,分别是对象和类。

一个对象可以是一只特定的鞋子,例如,一只美国尺码为 7.5 的棕色鞋子,以及鞋子示例中价格为 110 美元的运动鞋款式。这只棕色鞋子可能会改变它的价格。另一个对象可能是一双美国尺码为 4.5 的白色鞋子和一双售价为 80 美元的人字拖鞋子。这只白鞋也可以改变它的价格。

你注意到棕色鞋子和白色鞋子有什么特别吗?它们都有相同的属性。换句话说,它们都有颜色、尺寸、样式和价格。他们也有同样的方法。就好像它们来自一个蓝图,一个包含所有属性和方法的普通鞋子。对象的这种通用版本称为类。

你只需要对这个蓝图进行一次分类,然后你就可以一次又一次地从这个类中创建特定的对象。换句话说,你可以使用鞋子的蓝图,来制作你想要的任意多的鞋子,任何尺寸、形状、颜色、样式和价格。这些是面向对象编程中的基本术语。

**Object-Oriented Programming (OOP) Vocabulary****Class**
a blueprint which is consisting of methods and attributes.**Object**
an instance of a class. It can help to think of objects as something in the real world like a yellow pencil, a small dog, a yellow shoe, etc. However, objects can be more abstract.**Attribute**
a descriptor or characteristic. Examples would be colour, length, size, etc. These attributes can take on specific values like blue, 3 inches, large, etc.**Method**
an action that a class or object could take.

语法

如果您以前没有使用过类,语法可能会很复杂。

图一。鞋类

在图 1 中,写的是一个鞋类。该类具有颜色、大小、样式和价格属性。它还有一个改变价格的方法,以及一个输出折扣价的方法。在 shoe 类中,一些代码展示了如何实例化 Shoe 对象的例子,这样你就可以看到如何在程序中使用一个类。记住一个类代表一个蓝图。因此,我们正在设置普通鞋的颜色、尺码、款式和价格。

**Two things about this might seem a bit odd:*** __init__ ---> Python built-in function
* self -------> variable

Python 使用**__init__**创建一个特定的鞋子对象。另一方面,**self**变量在开始时可能很难理解。**self**保存颜色、大小等属性,使这些属性在整个 Shoe 类中可用。**self**本质上是一个保存所有属性和属性值的字典——检查 change price 方法,看看**self**如何工作。

我们可以将**self**作为第一个方法输入来访问价格。**self**中存储了价格,以及颜色、大小和样式等其他属性。如果你想访问属性,T7 总是你的方法的第一个输入。

还要注意,变更价格和折扣方法类似于一般的 Python 函数。例如,Python 函数不需要返回任何东西,所以像在 change price 方法中一样,它不返回任何东西。它只改变价格属性的值。然而,贴现方法确实返回了一些东西,它返回的是贴现价格。

**Additional: Function vs Method**A function and method seem very similar; both of them use the same keyword. They also have inputs and return outputs. The contrast is that a ***method is inside a class***, whereas a ***function is outside of a class.***

深入“自我”变量

如果定义两个对象,Python 如何区分两个对象?这就是**self**发挥作用的地方。如果在**shoe_one**上调用**change_price**方法,Python 怎么知道改变**shoe_one**的价格而不是**shoe_two**的价格?

def change_price(self, new_price): 
    self.price = new_priceshoe_one = Shoe('brown', '7.5', 'sneaker', 110) 
shoe_two = Shoe('white', '4.5', 'flip-flop', 80)shoe_one.change_price(125)

**self**告诉 Python 在计算机内存的什么地方寻找**shoe_one** 对象,然后 Python 改变**shoe_one**对象的价格。当你调用**change_price**方法时,**shoe_one.change_price(125)****self**被隐式传入。

**self**这个词只是一个约定。实际上你可以使用任何其他的名字,只要你始终如一;然而,你应该总是使用**self**而不是其他的词,否则你可能会让人混淆。

关于面向对象编程的一些注意事项

现在,我们将编写一个使用 shoe 类代码的单独的 Python 脚本。在同一个文件夹中,您需要创建另一个名为 project.py 的文件。在这个文件中,我们想要使用 shoe 类。首先,您需要通过键入**from shoe import Shoe**来导入 shoe 类。小写的 shoe 指的是 shoe.py 文件,大写的 shoe 指的是这个文件内部定义的类。

shoe.py 文件

project.py 文件

你可以指定你想要的文件和类。它们不必是相同的。我们这样做只是为了方便。现在,在project . py中可以使用鞋类了。如果你注意到了,代码现在是模块化的。您将编写一些使用 shoe 类的代码。

鞋类有一个方法来改变鞋的价格。在的 project.py 文件中可以看到第 9 行的**shoe_two.change_price(90)**。在 Python 中,您还可以使用以下语法更改属性的值:**shoe_one.color = ‘blue’****shoe_one.size = 5.0****shoe_one.price = 78**。与编写访问和显示属性的方法相比,直接访问属性有一些缺点。

*In terms of object-oriented programming, 
Python’s rules are a bit looser than in other programming languages. In some languages like C++, you can explicitly state whether an object should be permitted to change or access an attribute value directly. Python does not have this option.* 

为什么用方法改变值比直接改变值更好?

从长远来看,通过一个方法改变值会给你更多的灵活性。但是,如果计量单位被替换,例如,商店最初是以美元服务的,现在必须以欧元工作。如果你像在第 14 行那样直接改变了一个属性,如果突然你不得不使用欧元,你将不得不手动修改它。无论您在哪里直接访问价格属性,都必须这样做。

另一方面,如果您想使用一个像 change price 方法这样的方法,那么您所要做的就是进入 shoe 类,将原来的方法更改一次。我们要乘以,比如说,0.81,来把一切从美元转换成欧元。如果您返回到 project.py ,一个类似于数字 9 的行,您不必手动将价格从美元更改为欧元,因为转换会在鞋类中为您完成。

遗产

本文还将讨论一个面向对象的主题,继承。我们认为使用一个真实世界的对象,比如前面的鞋子例子,继承会更容易理解。鞋子有四个属性,颜色、尺码、款式和价格。鞋子也有两种方法:一种是改变价格的方法,另一种是计算折扣价的方法。

随着商店的扩张,它可能会储存其他类型的鞋子,如高跟鞋、踝靴和拖鞋。这些鞋子与鞋子对象有一些共同的属性和方法。它们可能都有颜色、尺寸、样式和价格,它们都可以使用函数来改变价格和计算折扣。

当每双新鞋有如此多的共同点时,为什么要为它们编写单独的类呢?或者,您可以编写外观鞋类,然后高跟鞋、踝靴和骡子类可以继承鞋类的属性和方法。

这看起来像一个家谱,鞋子是父母,高跟鞋,踝靴和拖鞋是孩子。一个好处是,当你添加更多像芭蕾舞鞋这样的鞋类时,你可以很容易地添加一个继承自鞋类的新类。如果您想添加一个新的属性,如材料,来表示鞋是由合成材料、橡胶还是泡沫制成的呢?现在,你要做的就是,给鞋子类添加一个材质属性,所有子类自动继承新属性。编写和维护代码变得更加高效。

结论

Python 被认为是面向对象的编程语言,而不是过程化编程语言。

它是通过查看像 Scikit-learn熊猫NumPy 这样的 Python 包来识别的。这些都是用面向对象编程构建的 Python 包。例如,Scikit-learn 是一个用面向对象编程构建的相对全面和复杂的包。这个软件包随着最新的功能和新的算法的出现而不断发展。

当你用 Scikit-learn 训练一个机器学习算法时,你不需要知道任何关于算法如何工作或者它们是如何编码的。你可以直接专注于建模。

到目前为止,我们已经了解了 Python 中面向对象编程语言的核心:

  • 类别和对象
  • 属性和方法
  • 遗产

了解了这些话题,就足够你开始写面向对象的软件了。然而,这些只是面向对象编程的基础。您可以通过访问下面的高级主题了解更多信息。另外,本文的源代码可以在我的 GitHub⁴ 上找到。

***Other Interesting Articles**#1 [Function Arguments: Default, Keyword, and Arbitrary](/function-arguments-default-keyword-and-arbitrary-9588b5eaaef3)#2 [Scope of Variable and LEGB Rule](/scope-of-variable-and-legb-rule-4d44d4576df5)#3 [Writing Your Own Functions](/writing-your-own-functions-40d381bd679)#4 [Data Science with Python: How to Use NumPy Library](/data-science-with-python-how-to-use-numpy-library-5885aa83be6b)#5 [Do you have the Software Engineer and Data Scientist skills?](/do-you-have-the-software-engineer-and-data-scientist-skills-probably-not-7e8fb069e067)*

关于作者

Wie Kiang 是一名研究人员,负责收集、组织和分析意见和数据,以解决问题、探索问题和预测趋势。

他几乎在机器学习和深度学习的每个领域工作。他正在一系列领域进行实验和研究,包括卷积神经网络、自然语言处理和递归神经网络。

**连接上LinkedIn

***References**#1 [Scikit-learn](https://github.com/scikit-learn/scikit-learn)
#2 [pandas](https://pandas.pydata.org/)
#3 [NumPy](http://www.numpy.org/)
#4 [Source code on GitHub](https://github.com/wiekiang/python-oop)**Advanced Python Object-Oriented Programming Topics*** [class methods, instance methods, and static methods](https://realpython.com/instance-class-and-static-methods-demystified/)
* [class attributes vs instance attributes](https://www.python-course.eu/python3_class_and_instance_attributes.php)
* [multiple inheritance, mixins](https://easyaspython.com/mixins-for-fun-and-profit-cb9962760556)
* [Python decorators](https://realpython.com/primer-on-python-decorators/)*

让我的代码高效的 Python 编程概念!

原文:https://towardsdatascience.com/python-programming-concepts-that-made-my-code-efficient-68f92f8a39d0?source=collection_archive---------6-----------------------

沙哈达特·拉赫曼在 Unsplash 上拍摄的照片

使用这些神奇的命令来增强您的 Python 类!

Python 是广泛使用和采用的语言之一,尤其是在机器学习领域。毫无疑问,Python 是最通用的语言。它不仅可以用来处理后端数据,还可以用来做前端 UI。Python 拥有可以施展魔法的工具。然而,他们中许多人的目标总是实现目标,而不考虑最佳实践和效率。

为了实现这个目标,我们最终编写了 n 个将被调用并完成工作的函数。其中一些相互关联的功能可以使用一个来定义。幸运的是,Python 是面向对象编程(OOP),可以通过创建对象来解决问题。因为 Python 是 OOP,使用可复用的代码,避免冗余是最大的优势。

写 Python 代码时的口头禅

班级

从真正使其面向对象的最重要的组件开始,定义 cclass。c lass 基本上就是一个创建对象的模板。想一个披萨类,会告诉食材,种类,大小等等。一个简单的类应该是这样的:

上面代码的输出

init

init 是初始化方法,我们一调用这个类,它就会运行。这里,类一初始化,type_ variable 就被赋值为“veggie”。

上面代码的输出

假设我们创建了一个打印所请求的比萨饼的方法。这被称为实例方法,因为它们在实例对象 obj 上被调用。最佳实践是在该方法下定义一个变量,这样就可以在类内的任何地方访问它。Python 并不要求应该在类中的什么位置定义实例属性。

__ 呼叫 _ _

call 一调用方法就运行。一旦对象被初始化,它就采取行动。 call 在一个实例需要经常改变状态的时候很有用。

上面代码的输出

我们可以看到 shape 的默认值是‘圆形’。然而,我可以在初始化后通过向对象传递一个值来改变形状。尝试传递空括号并检查输出!

repr

repr 主要用于查看赋给我们变量的值。它可以定义如下:

上面代码的输出

尽管 repr 被认为是对象的“正式”字符串表示,但它主要用于调试,主要由开发人员使用。

str

str 与上面的 repr 颇为相似。 str 可以被覆盖,并允许更多的定制,除非像 repr 不能。

上面代码的输出

如上图,除非像 repr 一样,需要将对象传递给 print 函数来显示变量。 strrepr 相反,被认为是对象的“非正式”字符串表示。它主要用于为普通用户创建输出。

__ 词典 _ _

Python 有一个名为 dict 的内部字典,保存所有的内部变量。这是检查变量内部细节的简单方法。

上面代码的输出

也可以使用 dict 属性直接更改变量,如下所示:

上面代码的输出

__ 插槽 _ _

slots 和上图的 dict 很像。这是最好的特性之一,通常不被 Python 社区使用。如果数据被传递给 init 并且主要用于存储数据, slots 可以帮助优化类的性能。下面是如何使用它:

再深入一点细节, dict 浪费了很多 RAM。这是告诉 Python 不要使用 dict 而只使用一组固定属性的好方法。对于繁重的 RAM 工作,有些人已经看到通过使用 slots 减少了 40–50%的 RAM 使用[2]。

静态方法:

我们简要地看到了如何创建方法来完成特定的任务。有些方法,不一定需要修改或传递任何类参数,就可以使用。他们成为类的一部分而不是类的对象是有意义的。换句话说,他们对状态一无所知。这种方法被称为静态方法。下面是一个小例子:

上面代码的输出

正如我们上面看到的,我们可以直接使用静态方法,甚至不用初始化类。我们使用@staticmethod 定义这样的方法。我们主要用来创建效用函数。

类方法:

类方法不同于静态方法。这里,类方法可以访问或修改的状态。当调用方法时,我们将 cls 作为指向类而不是对象实例的参数传递。

上面代码的输出

正如我们在上面看到的,一个人可以单独使用这个方法,但是它需要它所属的类所期望的所有参数。根据输入的数字,大小被确定为“中等”。我们使用@classmethod 定义它们。

结论:

这些是我在一段时间里学到的一些重要的方面。如果想真正写出更好的 Python 代码,理解并实现这些“最佳实践”是很重要的。一开始可能很难理解,但是你越是编码和尝试使用它们,你就会越清楚地理解它们的重要性。最佳实践有助于代码库的长期可维护性。集成良好设计原则的良好基础不仅会使未来的开发更容易,还会帮助其他用户/团队成员使用相同的代码进行重用或改进。

参考资料:

  1. www.programiz.com

2。https://book.pythontips.com/en/latest/__slots__magic.html

如果你认为我遗漏了什么概念,应该补充,请随时评论!欢迎评论!

想成为 中等会员 享受无限制阅读文章的乐趣,请注册成为会员。Medium 将与我分享一部分给使用以上链接注册的成员!谢了。

面向金融的 Python 股票价格趋势分析

原文:https://towardsdatascience.com/python-python-for-finance-stock-price-trend-analysis-9111afc29259?source=collection_archive---------7-----------------------

构建一个强大的 Python 工具来执行股票价格趋势分析

在本文中,我们将构建一个非常强大的 Python 工具来执行股票价格趋势分析。一旦脚本准备就绪,Python 将为我们生成下图,显示不同股票随时间的价格趋势。

用于金融股票价格分析的 Python

这个用于金融分析的很酷的Python脚本将股票列表作为输入,然后它将:

  • 下载每家所需公司近年来的每日股票价格
  • 将所有股票价格合并到一个单一的熊猫数据框架中。
  • 以基准日期(即我们获得数据的第一天)的百分比显示结果。
  • 使用 Matplotlib 绘制每家公司的股价走势图

设置 Python for Finance 脚本

为了开始构建我们的股价趋势分析脚本,我们需要导入几个包。

首先,我们将向一个免费的财务 API 发出 http 请求,在那里我们将获得股票每日价格。然后,我们将使用 Pandas 合并 API 返回的财务数据,并将它们合并到一个 Pandas 数据框架中。最后,我们将使用 matplotlib 将我们的数据转换成图形。

在导入所有必需的包之后,我们将有一个我们想要检索价格的每家公司的股票 报价器列表。作为一个想法,你也可以使用 Python 获得标准普尔 500 指数中所有公司的股票列表,并将其作为你分析的基础,而不是手动输入股票代码。你可以在我的另一篇文章中找到答案。

import requests
import pandas as pd
import matplotlib.pyplot as plt

#Enter the ticker of the companies that you want to analyse
companies = ['AAPL','FB','GOOG','F','TSLA']#empty list to add each of the companies
listofdf = []

现在我们有了初始设置,我们可以进入有趣的部分了。我们的最初目标是发送一个 http 请求到 API 端点来下载每日股票价格

#API end point request
requests.get(f"https://financialmodelingprep.com/api/v3/historical-price-full/aapl?serietype=line")

#outcome
{
"symbol": "AAPL",
"historical": [
{
"date": "1989-09-19",
"close": 1.54
},
{
"date": "1989-09-20",
"close": 1.59
},
{
"date": "1989-09-21",
"close": 1.6
},

正如你在上面的 url 中看到的,我们传递了 aapl 作为参数(即在上面的例子中是 aapl 是苹果的股票代码)。该参数向 API 指示我们正在请求哪只股票的股价数据。因此,通过将 url 参数 appl 更改为任何其他公司股票,我们将获得其他公司的价格。

通过查看响应,我们看到列表中的每个元素都是一个字典,包含一天的股票价格。

for item in companies:
    histprices = requests.get(f"https://financialmodelingprep.com/api/v3/historical-price-full/{item}?serietype=line")
#convert response to json
    histprices = histprices.json()

#Parse the API response and select only last 600 days of prices
    histprices = histprices['historical'][-600:]

#Convert from dict to pandas datafram
    histpricesdf = pd.DataFrame.from_dict(histprices)

#rename column from close to the name of the company
    histpricesdf = histpricesdf.rename({'close': item}, axis=1)

#append all dfs to list
    listofdf.append(histpricesdf)

For 循环将让我们遍历公司列表中的每个公司。这样,在每次循环迭代中,我们将为列表中包含的每只股票发出一个新的 http 请求。

注意,我们将单词 item 作为 url 的参数传递,该单词表示股票代码,并将随着每次循环迭代而改变。

然后,我们对熊猫数据帧进行切片,只保留最近的 600 天。最后,我们可以使用 pd。data frame . from _ dict()to将我们的字典与股票价格和日期转换成一个熊猫数据框架。

现在我们有了一个名为 listofdf 的列表。列表中的每个元素都包含每只股票的熊猫数据帧。然而,将我们所有的股票放在不同的熊猫数据框架中对我们的分析没有太大的帮助。因此,我们将使用 Pandas 类方法 pd.concat合并为一个。

#set index of each DataFrame by common column before concatinatinghtem
dfs = [df.set_index('date') for df in listofdf]

histpriceconcat = pd.concat(dfs,axis=1)

太好了,现在我们将所有股票价格合并到一个熊猫数据框架中:

在开始绘制每只股票的价格趋势之前的最后一步,我们将将数据框中的每一行除以第一行。这将允许跨股票比较,因为所有股票价格将显示为一段时间内的百分比差异。

面向金融的 Python 股票价格

低于 1 的值表示与基准日(即 2017-10-04)相比,股价有所下跌。大于 1 的值表示价格上涨。

奥斯汀·迪斯特尔Unsplash 上拍摄的照片

绘制股票价格趋势

我们的脚本几乎准备好了,唯一悬而未决的部分是 Python 显示股票价格随时间的趋势。我们可以使用 matplotlib 轻松实现这一点。

首先,我们将循环遍历每个串联的熊猫数据帧,以便绘制每个列。然后,我们可以通过添加标题旋转棒并显示图例来稍微改变一下图表的布局:

for i, col in enumerate(histpriceconcat.columns):
    histpriceconcat[col].plot()

plt.title('Price Evolution Comparison')

plt.xticks(rotation=70)
plt.legend(histpriceconcat.columns)

#Saving the graph into a JPG file
plt.savefig('foo1.png', bbox_inches='tight')

用于金融股票价格分析的 Python

包扎

就这样,我们构建了一个很好的 Python 脚本来执行股票价格趋势分析。由于价格显示为第一个数据点的百分比,该图对于比较不同公司的价格趋势特别有用。例如,我们可以看到 特斯拉 在过去几周经历了大幅增长,而苹果股价自 2017 年以来一直在稳步上涨。

随意改变绘图天数和公司数量。为了您的方便,请参阅下面的整个脚本。

好好享受吧!

import requests import pandas as pd import matplotlib.pyplot as plt companies = ['AAPL','FB','GOOG','F','TSLA'] listofdf = [] for item in companies: histprices = requests.get(f"https://financialmodelingprep.com/api/v3/historical-price-full/{item}?serietype=line") histprices = histprices.json() #Parse the API response and select only last 600 days of prices histprices = histprices['historical'][-600:] #Convert from dict to pandas datafram histpricesdf = pd.DataFrame.from_dict(histprices) #rename column histpricesdf = histpricesdf.rename({'close': item}, axis=1) #append all dfs to list listofdf.append(histpricesdf) #set index of each DataFrame by common column before concatinatinghtem dfs = [df.set_index('date') for df in listofdf] histpriceconcat = pd.concat(dfs,axis=1) #divide all dataframe by first line of data to enable comparison histpriceconcat = histpriceconcat/histpriceconcat.iloc[0] for i, col in enumerate(histpriceconcat.columns): histpriceconcat[col].plot() plt.title('Price Evolution Comparison') plt.xticks(rotation=70) plt.legend(histpriceconcat.columns) plt.savefig('foo1.png', bbox_inches='tight')

原载于 2020 年 2 月 25 日 https://codingandfun.com**T21

import requests
import pandas as pd
import matplotlib.pyplot as plt

companies = ['AAPL','FB','GOOG','F','TSLA']
listofdf = []
for item in companies:
    histprices = requests.get(f"https://financialmodelingprep.com/api/v3/historical-price-full/{item}?serietype=line")
    histprices = histprices.json()

#Parse the API response and select only last 600 days of prices
    histprices = histprices['historical'][-600:]

#Convert from dict to pandas datafram

    histpricesdf = pd.DataFrame.from_dict(histprices)

#rename column
    histpricesdf = histpricesdf.rename({'close': item}, axis=1)

#append all dfs to list
    listofdf.append(histpricesdf)

#set index of each DataFrame by common column before concatinatinghtem
dfs = [df.set_index('date') for df in listofdf]

histpriceconcat = pd.concat(dfs,axis=1)

#divide all dataframe by first line of data to enable comparison
histpriceconcat = histpriceconcat/histpriceconcat.iloc[0]

for i, col in enumerate(histpriceconcat.columns):
    histpriceconcat[col].plot()

plt.title('Price Evolution Comparison')

plt.xticks(rotation=70)
plt.legend(histpriceconcat.columns)
plt.savefig('foo1.png', bbox_inches='tight')

在 Python 中使用 API。

原文:https://towardsdatascience.com/python-requests-api-70a555fecc97?source=collection_archive---------19-----------------------

高级概念包括面向对象程序设计、缓存

约书亚·阿拉贡Unsplash 拍摄

随着微服务的出现,有很多 API 可以与之交互,无论是用于编排系统还是提取数据。使用 Python 处理专用的 API 工作负载是合适的,因为它具有多用途的特性。

在本文中,我将与您分享 3 个代码片段,它们将帮助您更好地管理依赖于 API 的工作流。我将使用 J 子占位符假 API 进行演示。

1.使用线程和异步实现并发的 Python API

当您希望用一个变化的参数对同一个资源进行多次调用时,您必须转向并发方法。事实上,编写顺序代码会产生低效的代码:您的代码将花费大部分时间等待服务器的响应。

要解决这个问题,有两种方法要么我们使用线程,要么从 python 3.5 开始我们可以使用异步。让我们看看这两种方法的代码是什么样子的,以便分别检索注释。让我们从线程方法开始。

线程方法来源:作者

我用一个dataclass来封装初始化整个过程的逻辑。线程是工作线程,每个线程并发地调用一个 URL。他们从队列中提取 URL,队列是一种支持并发的数据结构。当他们收到答案时,他们把它放到另一个队列中。最后,当所有的工人完成后,我们将队列转换成一个列表,并返回它。

现在让我们看看异步版本。

异步方法来源:作者

在这个版本中,我们不需要处理并发和多线程,因为没有并发线程产生。事实上,异步代码是基于事件循环和协程的,概括地说,我们不是等待 IO 代码解决,而是执行另一段代码,并在解决后返回到 IO 代码。

然而,为了能够等待代码和委托控制,我们必须使用异步函数,这意味着范式转换,并使用新的库。

因为,正如你所看到的,异步版本的缺点是不能使用通常的库,例如请求。事实上,使用支持异步的库是必要的。

另一方面,线程的缺点是必须考虑用专用数据结构管理并发线程。

2.使用重试修饰器重试 Python 代码失败

当使用 API 时,存在节流的情况并不少见。拥有一个允许您在函数失败时重试的实用程序可能会很有趣。为了实现这个实用程序,我使用了一个对很多情况都非常有用的 python 特性:decorators。

有状态重试装饰器源代码:作者

这是一个没有函数形式的装饰者,而函数形式是传统的呈现方式。这是一个类。当需要在内存中保存一个状态时,以类的形式实现的 Decorators 是很有趣的。这里我们需要在内存中保存尝试的次数。

因此,这个装饰器允许我们指定被装饰的函数必须重试的次数,也允许我们指定每次重试之间的等待时间。

3.缓存 Python HTTP 请求的结果

当您必须对某个 API 进行大量调用时,例如每天有一个限制,并且您的脚本在接近结束时由于失误而失败,您会丢失对该 API 的调用结果。

在这种情况下,实现一个缓存来保存我们的结果可能会很有趣,因为我们下次启动脚本时,只有未缓存的请求才会被执行。下面是实现本地缓存的代码示例。

简单的本地缓存实现来源:作者

这个缓存是作为一个类实现的。本地缓存只不过是一个 dict,我们用 URL 作为关键字来保存数据。然后,这个缓存以序列化 pickle 文件的形式保存在本地。在脚本的第二次执行期间,将加载缓存并从中提取结果。

然而,尽管这种缓存是合适的,但它不允许使用线程。这将需要实现另一个缓存,并使用像 REDIS 这样更健壮的东西。

因此,您可以像上面那样创建一个接口,它将定义所有缓存的框架。现在,您可以创建一个新的缓存实现,而无需更改整个脚本。

要做的另一个改进是管理缓存的有效性,实际上这里缓存并不管理它,您必须手动使缓存无效,在这个简单的例子中没有这样做。

结论

在本文中,我们看到了如何使用高级 python 特性和软件工程概念来改进与 API 交互的脚本。希望这对你有帮助。

Python Rest API 示例

原文:https://towardsdatascience.com/python-rest-api-example-10c802e8ff24?source=collection_archive---------33-----------------------

使用 Flask 分享你的想法,Flask 是数据科学家最流行的框架

扎拉克汗Unsplash 上拍摄的照片

让我们假设我们非常擅长创建机器学习模型,我们可以创建许多不同的有趣的项目。下一步是什么?我们如何与他人分享我们的知识?答案是做一个 API。

根据维基百科,应用编程接口 ( API )是客户端和服务器之间的接口通信协议,旨在简化客户端软件的构建。听起来很复杂,但事实并非如此。

在本教程中,我们将把这个算法转换成一个 API。

让我们看看代码。

import PIL
from PIL import Image
import requests
from io import BytesIO
import webcolors
import pandas as pd

import webcolors

def closest_colour(requested_colour):
    min_colours = {}
    for key, name in webcolors. CSS3_HEX_TO_NAMES.items():
        r_c, g_c, b_c = webcolors.hex_to_rgb(key)
        rd = (r_c - requested_colour[0]) ** 2
        gd = (g_c - requested_colour[1]) ** 2
        bd = (b_c - requested_colour[2]) ** 2
        min_colours[(rd + gd + bd)] = name
    return min_colours[min(min_colours.keys())]

def top_colors(url, n=10):
    # read images from URL
    response = requests.get(url)
    img = Image.open(BytesIO(response.content))

    # convert the image to rgb
    image = img.convert('RGB')

    # resize the image to 100 x 100
    image = image.resize((100,100))

    detected_colors =[]
    for x in range(image.width):
        for y in range(image.height):
            detected_colors.append(closest_colour(image.getpixel((x,y))))
    Series_Colors = pd.Series(detected_colors)
    output=Series_Colors.value_counts()/len(Series_Colors)
    return(output.head(n).to_dict())

所以“ top color ”函数所做的是给定一个图像的 URL,它可以返回前 10 种主色。点击此处了解更多信息。

我们必须在工作目录中用上面的代码创建一个 colors.py 文件,这样我们就可以将函数导入到我们的 flask 代码中。

我们的 API,的输出不能是熊猫数据帧。所以我们会把它转换成 JSON。一个简单的方法是将数据帧作为字典返回,然后在我们的 flask 代码中,使用 flask 的 Jsonify 函数,我们可以将其转换为 JSON。这就是我们使用。 top_colors 函数中的 to_dict()方法。

Python Rest API Flask 脚本

现在我们有了我们的函数,下一步是创建我们的 Flask 代码。在我们的工作目录中,我们必须用以下代码创建一个 main.py 文件:

from flask import Flask, jsonify, request

app=Flask(__name__)

#we are importing our function from the colors.py file
from colors import top_colors

[@app](http://twitter.com/app).route("/",methods=['GET','POST'])
def index():
    if request.method=='GET':
#getting the url argument       
        url = request.args.get('url')
        result=top_colors(str(url))
#the jsonify function is converting the dictionary to JSON
        return jsonify(result)
    else:
        return jsonify({'Error':"This is a GET API method"})

if __name__ == '__main__':
    app.run(debug=True,host='0.0.0.0', port=9007)

您不必理解整个脚本,只需将它作为您的 API 项目的基础。

首先我们必须从 colors.py 文件中导入我们的函数 top_colors 。使用url = request . args . get(' URL ')我们得到参数 "url" 的值,在我们的例子中是一个图像的 URL。

然后,我们将这个值传递给我们的函数,并使用 jsonify 库将它转换成一个 JSON 返回结果,正如我们上面所说的。

if 语句是为那些调用 API 作为 POST 方法的人准备的,这样它就可以返回一个警告。最后,端口由您决定,我们使用的是 9007

最后,我们可以运行 main.py 文件在本地进行测试。只需在您的终端中运行以下命令:

 python main.py

输出将是这样的:

* Serving Flask app "main" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 220-714-143
 * Running on http://0.0.0.0:9007/ (Press CTRL+C to quit)

这意味着我们的 API 运行在使用 9007 端口的本地主机上。

现在我们可以用浏览器来测试它。要在 API 的 URL 中添加我们的变量(图片 URL),我们必须把它添加在末尾,如下所示?变量=。在我们的示例中,我们的 API 的 URL 如下:

http://localhost:9007/ ?URL =[[图片的 URL]]

例如,我们想从 Unsplash 中获取以下图像的主色:

Á·萨·斯泰纳斯多蒂尔Unsplash 上拍摄的照片

https://images . unsplash . com/photo-1615479865224-b 07 bb 46 a 5 f 56?ixid = mxwxmja 3 fdb 8 mhxwag 90 by 1 wywdlfhx 8 fgvufdb 8 fhw % 3D&ixlib = r b-1 . 2 . 1&auto = format&fit = crop&w = 1000&q = 80

我们在浏览器中点击了以下 URL

[http://localhost:9007/?url=](http://localhost:9007/?url=https://image.shutterstock.com/z/stock-photo-at-o-clock-at-the-top-of-the-mountains-sunrise-1602307492.jpg:)[https://images.unsplash.com/photo-1615479865224-b07bb46a5f56?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80](https://images.unsplash.com/photo-1615479865224-b07bb46a5f56?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80)

然后,我们将得到以下输出:

{'black': 0.2843,
 'gainsboro': 0.2812,
 'darkslategray': 0.1889,
 'lavender': 0.0668,
 'lightsteelblue': 0.0448,
 'lightgray': 0.0405,
 'darkgray': 0.0189,
 'darkolivegreen': 0.0172,
 'dimgray': 0.0144,
 'lightslategray': 0.0129}

成功了,我们得到了那个图像的主色!下一步是在服务器上部署它。

结论

构建 API 是数据科学家必须掌握的知识。迟早你会被要求为你的模型创建一个 API 来与开发者或项目的其他人分享,所以开始尝试吧!

以后我会写更多初学者友好的帖子。在媒体上关注我访问我的博客了解他们。

我欢迎提问、反馈和建设性的批评,你可以通过推特(Twitter)或社交网站(Instagram)联系我。

原载于 2020 年 1 月 29 日 https://predictivehacks.com**

Python 风险管理:蒙特卡罗模拟

原文:https://towardsdatascience.com/python-risk-management-monte-carlo-simulations-7d41c891cb5?source=collection_archive---------7-----------------------

看到更多可能性的介绍

特别感谢 Daria Sannikova

在这篇文章中,我们将回顾蒙特卡罗模拟,它可以用来提供对未来事件建模的见解。这篇文章的全部思想来自两个因素的结合。第一个是我正在进行的期权交易实验,旅程可以在这里找到。第二是另一篇关于 Kelly Criterion 的 Python 风险管理文章非常受欢迎,所以我想扩展一下这个话题,这篇文章的原文可以在这里找到。事不宜迟,让我们开始讨论资产定价的蒙特卡罗模拟吧!

蒙特卡罗模拟概述

教授蒙特卡罗模拟的一个常见方法是思考任何形式的机会,因此有了老丨虎丨机的形象。在任何给定时间,基于一个动作的下一个时间步中可能发生多个事件。现在,我相信先学习简单的例子来理解复杂的例子,所以让我们来考虑扔一个公平的六面骰子。我们都知道骰子从 1 到 6 有 6 种可能的机会。但是,为了通过实验计算出多少,我们必须滚动几次骰子并记录结果。有了蒙特卡罗模拟,我们可以在模拟中进行任意数量的试验。

在更专业的定义中,蒙特卡洛取自概率分布,以提供风险的多元模型或呈现多个假设事件[1]。蒙特卡洛的基本公式可以归结为:

基本上,该配方由 3 个主要成分组成。首先,是我们所关注的资产在一段时间内的数据。在我们的文章中,它将是加密货币 Tezos 和股票代码 AMD。下一部分是漂移,这是资产在过去移动的方向。第三个分量是从分布中抽取的随机分量。在我们的例子中,我们将使用正态分布来模拟资产波动。波动性通常被视为一只股票在通常情况下的疯狂运动,看起来有点随机。

投资者/交易者如何应用蒙特卡罗

如前所述,蒙特卡罗是一个很好的方法来规划一个有多种可能结果的问题。在金融领域,尤其是金融市场,一项资产在未来可能会有多个不同的价格水平。除了资产定价,蒙特卡罗模拟还可以应用于预测财务项目,如现金流[2]。

蒙特卡洛的加密货币——Tezos

Tezos 是另一种应用类似 Etherium [3]的智能合约的加密货币。我只是对它感到好奇,因为它有一个有趣的特性。至少在我持有的比特币基地 Tezos 股票中,它实际上为持有它支付了大约 5%的回报(Tezos 奖励),这类似于股票的股息收益率——如下图:

在完成了比特币基地的介绍和一些 Tezos 奖励后,我的 Tezos 钱包。

只是提醒一下,我在比特币基地了解到 Tezos 是免费的,注册这个附属链接你可以得到 10 美元。要获得 Tezos 的收入,您必须向下滚动您的仪表板,应该会看到一个收入页面。只要完成教程,你应该会看到奖励。加密 EOS 的一个例子可以在这个附属链接中找到。关于 Tezos 蒙特卡洛模拟的例子,每日数据取自 investing.com:

#Import Libraries
import numpy as np  
import pandas as pd  
import pandas_datareader as wb  
import matplotlib.pyplot as plt  
from scipy.stats import norm
%matplotlib inline

#Settings for Monte Carlo asset data, how long, and how many forecasts 
ticker = 'XTZ_USD' # ticker
t_intervals = 30 # time steps forecasted into future
iterations = 25 # amount of simulations#Acquiring data
data = pd.read_csv('XTZ_USD Huobi Historical Data.csv',index_col=0,usecols=['Date', 'Price'])
data = data.rename(columns={"Price": ticker})#Preparing log returns from data
log_returns = np.log(1 + data.pct_change())#Plot of asset historical closing price
data.plot(figsize=(10, 6));

2019 年 8 月至 2020 年 1 月 Tezos 对美元的收盘价。

#Plot of log returns
log_returns.plot(figsize = (10, 6))

记录 Tezos 对美元的正常回报。

#Setting up drift and random component in relation to asset data
u = log_returns.mean()
var = log_returns.var()
drift = u - (0.5 * var)
stdev = log_returns.std()daily_returns = np.exp(drift.values + stdev.values * norm.ppf(np.random.rand(t_intervals, iterations)))#Takes last data point as startpoint point for simulation
S0 = data.iloc[-1]
price_list = np.zeros_like(daily_returns)
price_list[0] = S0#Applies Monte Carlo simulation in asset
for t in range(1, t_intervals):
    price_list[t] = price_list[t - 1] * daily_returns[t]

#Plot simulations
plt.figure(figsize=(10,6))
plt.plot(price_list);

25 个 Tezos 回报的蒙特卡罗模拟,最长 30 天。

需要注意的一点是这些模拟中的巨大波动性。从今天的 1.50 美元的价格来看,Tezos 可能会从 1.00 美元波动到 2.75 美元!从这些少量的模拟中,我可以看出为什么有些人喜欢在比特币和类似的密码上冒险,因为它们有略微有利的上行潜力。

AMD 上的蒙特卡洛

我刚刚决定做 AMD,由于我的其他职位交易 AMD 期权发现这里。现在,让我们来看看高级微器件蒙特卡罗模拟。

#Import Libraries
import numpy as np  
import pandas as pd  
import pandas_datareader as wb  
import matplotlib.pyplot as plt  
from scipy.stats import norm
%matplotlib inline

#Settings for Monte Carlo asset data, how long, and how many forecasts 
ticker = 'AMD' # stock ticker
t_intervals = 30 # time steps forecasted into future
iterations = 25 # amount of simulations#Acquiring data
data = pd.DataFrame()
data[ticker] = wb.DataReader(ticker, data_source='yahoo', start='2018-1-1')['Adj Close']#Preparing log returns from data
log_returns = np.log(1 + data.pct_change())#Plot of asset historical closing price
data.plot(figsize=(10, 6));

AMD 2018-2020 年收盘价。

#Plot of log returns
log_returns.plot(figsize = (10, 6))

记录 AMD 从 2018 年到 2020 年的正常回报。

从上面的收盘价来看,对数回报看起来相当不错。现在开始设置漂移和随机成分。

#Setting up drift and random component in relatoin to asset data
u = log_returns.mean()
var = log_returns.var()
drift = u - (0.5 * var)
stdev = log_returns.std()daily_returns = np.exp(drift.values + stdev.values * norm.ppf(np.random.rand(t_intervals, iterations)))#Takes last data point as startpoint point for simulation
S0 = data.iloc[-1]
price_list = np.zeros_like(daily_returns)
price_list[0] = S0#Applies Monte Carlo simulation in asset
for t in range(1, t_intervals):
    price_list[t] = price_list[t - 1] * daily_returns[t]

#Plot simulations
plt.figure(figsize=(10,6))
plt.plot(price_list);

未来 30 天 AMD 的 25 次蒙特卡洛模拟

从蒙特卡洛模拟来看,AMD 的整体趋势是上升的,这是一个好迹象,因为我在挑战时持有看涨的头寸!

结论

蒙特卡洛模拟允许投资者和交易者将投资可能性转化为决策。蒙特卡洛的优势在于它能够将不同可能事件的质量范围考虑在内。同样,这也是它最值得注意的缺点,即它有时无法准确衡量极端事件。例如,在大熊危机期间,多次蒙特卡洛模拟失败。因此,这个模型和其他模型一样,受到所应用的数据和设置的限制。针对这一弱点的一个可能的解决方案是对模拟的随机分量采用非正态概率分布。

— — — — — — — — — — — — — — — — — — — — — — — — — —

参考文献

[1]斯坦默斯,R. (2020 年 1 月 3 日)。如何使用蒙特卡罗分析来估计风险?检索自https://www . investopedia . com/articles/financial-theory/08/Monte-Carlo-variable-model . ASP

[2]阿加瓦尔,K. (2019,11 月 18 日)。蒙特卡洛模拟能为你的投资组合带来什么?检索自https://www . investopedia . com/articles/investing/112514/Monte-Carlo-simulation-basics . ASP

[3]比特币基地。(2019).赚 Tezos。从 https://www.coinbase.com/earn/tezos取回

— — — — — — — — — — — — — — — — — — — — — — — — — —

要进入比特币基地,点击这个附属链接,这样我们都可以得到 10 美元。

这篇文章是由于 Options $100k Challenge 而创作的。

免责声明:本文陈述的所有内容均为我个人观点,不代表任何雇主。投资有很大的风险,所有投资决定都要咨询你的投资顾问。我可能会积极交易本文中提到的资产。这篇文章包含附属链接。

Python (Scikit-Learn):逻辑回归分类

原文:https://towardsdatascience.com/python-scikit-learn-logistic-regression-classification-eb9c8de8938d?source=collection_archive---------18-----------------------

通过使用 Python 中的 scikit-learn 包,了解如何将逻辑回归应用于二元分类

照片由 Pietro Jeng 在 Unsplash 上拍摄

使用预测技术区分分类数据的过程称为分类。最广泛使用的分类技术之一是逻辑回归。关于逻辑回归的理论基础,请看我之前的文章

在本文中,我们将利用 Python 编程语言中可用的 scikit-learn (sklearn) 包,将逻辑回归应用于一个二元分类问题。

泰坦尼克号数据集

我们将使用泰坦尼克号数据集(可在 Kaggle 上获得),目标是预测泰坦尼克号上的幸存者。也就是说,基于数据集中包含的特征(解释变量),我们希望预测某个特定的人是否在泰坦尼克号沉船事故中幸存。

加载数据

我们从导入所需的包和加载 titanic 数据集开始。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn import metrics
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

titanic = pd.read_csv(".../Titanic/train.csv")

titanic.head()

在这里,我们可以看到数据集中包含的不同变量。让我们简要描述一下每个变量:

  • PassengerId :乘客的 ID;
  • 幸存:目标变量;该人是在海难中幸存(1)还是没有在海难中幸存(0);
  • Pclass :乘客在船上所处的等级(1、2 或 3);
  • 姓名:乘客姓名;
  • 性别:乘客的性别;
  • 年龄:乘客的年龄;
  • SibSp :船上兄弟姐妹和配偶人数;
  • Parch :船上父母/子女人数;
  • 车票:车票号码;
  • 票价:车票的票价;
  • 舱室:舱室编号;
  • 登船:登船港(C =瑟堡,Q =皇后镇,S =南汉普顿)。

预处理

当应用任何预测算法时,我们可以永远不要在没有对数据进行任何预处理的情况下立即使用它。这一步极其重要,绝不能忽视。对于该数据集,我们执行以下预处理步骤:

1。删除那些似乎不会给我们的模型增加任何价值的功能

titanic.drop(['PassengerId', 'Name', 'Ticket', 'Cabin'], axis=1, inplace=True)

这里,我们从数据集中删除了 PassengerId、姓名、机票和客舱特性。其原因是,这些不能为我们的模型提供任何预测能力。

2。为登船口创建分类模型

ports = pd.get_dummies(titanic.Embarked, prefix='Embarked')
ports.head()

我们从分类装载特征创建了三个二元特征,因为模型不能处理原始分类变量中的字符串名称。

titanic = titanic.join(ports)
titanic.drop(['Embarked'], axis=1, inplace=True)

3。将性别名称转换为二进制

titanic.Sex = titanic.Sex.map({'male': 0, 'female': 1})

通过映射将“男性”和“女性”名称转换为二进制(0 和 1)。

4。替换丢失的值

titanic[pd.isnull(titanic).any(axis=1)]

请注意,所有缺失值(nan)都出现在年龄要素中。为了解决这些缺失值,让我们用数据中的平均年龄来填充缺失值。

titanic.Age.fillna(titanic.Age.mean(), inplace=True)

训练和测试分割

既然我们已经预处理了数据,我们可以提取 X 中的解释变量和 y 中的目标变量:

y = titanic.Survived.copy()
X = titanic.drop(['Survived'], axis=1)

接下来,我们将数据分成训练集和测试集。训练集用于训练逻辑回归模型。该模型从训练集中包括的特征中学习。测试集用于验证逻辑回归模型的性能。对于测试集中的每个观察值,我们预测该人是否幸存,并将预测值与真实值进行比较。

我们拆分数据,使训练集包含 75%的数据,测试集包含 25%的数据。我们使用 scikit-learn 包的train_test_split模块。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=123)

逻辑回归模型

通过使用 scikit-learn 包中的LogisticRegression模块,我们可以使用 X_train 中包含的特性将逻辑回归模型拟合到训练数据。

model = LogisticRegression()
model.fit(X_train, y_train)

接下来,现在我们已经根据训练数据训练了逻辑回归模型,我们能够使用该模型来预测测试集中包括的人是否在海难中幸存:

y_pred = pd.Series(model.predict(X_test))y_test = y_test.reset_index(drop=True)
z = pd.concat([y_test, y_pred], axis=1)
z.columns = ['True', 'Prediction']
z.head()

这里,我们看到,对于测试集的前五个观察值,逻辑回归模型正确预测了 5 个中的 4 个。

为了评估整个测试集,我们可以使用 scikit-learn 包中的metrics模块。

print("Accuracy:", metrics.accuracy_score(y_test, y_pred))
print("Precision:", metrics.precision_score(y_test, y_pred))
print("Recall:", metrics.recall_score(y_test, y_pred))

输出:

Accuracy: 0.8026905829596412
Precision: 0.7631578947368421
Recall: 0.6904761904761905

也就是说,逻辑回归模型导致 80.3%的准确性。这么简单的车型绝对不差!

当然,可以通过例如进行进一步的预处理、特征选择和特征提取来进一步提高模型性能。然而,这个模型形成了一个坚实的基线。

可视化模型结果的一个好方法是利用混淆矩阵。这里,我们使用matplotlibseaborn来创建一个漂亮的混淆矩阵图。

cnf_matrix = metrics.confusion_matrix(y_test, y_pred)

labels = [0, 1]
fig, ax = plt.subplots()
tick_marks = np.arange(len(labels))
plt.xticks(tick_marks, labels)
plt.yticks(tick_marks, labels)
# create heatmap
sns.heatmap(pd.DataFrame(cnf_matrix), annot=True, cmap="YlGnBu", fmt='g')
ax.xaxis.set_label_position("top")
plt.title('Confusion matrix', y=1.1)
plt.ylabel('True')
plt.xlabel('Predicted')

在混淆矩阵中,我们看到 121 名海难幸存者被正确预测为未幸存,18 名海难幸存者被错误预测为海难幸存者,26 名海难幸存者被错误预测为海难幸存者,最后,58 名海难幸存者被正确预测。

逻辑回归的利与弊

优点:

  • 不需要很高的计算能力;
  • 易于实现;
  • 简单易懂。

缺点:

  • 容易过度拟合;
  • 无法解决非线性问题;
  • 无法处理大量的分类特征。

感谢阅读!

希望在阅读完本文后,您现在能够通过使用 Python 中的 scikit-learn 包来自己使用逻辑回归技术。祝你在自己的项目中使用它好运!

Python SQLite 教程-终极指南

原文:https://towardsdatascience.com/python-sqlite-tutorial-the-ultimate-guide-fdcb8d7a4f30?source=collection_archive---------11-----------------------

入门所需的一切!

让我们了解一下开始使用 Python 中的 SQLite3 所需要的一切!资料来源:Nik Piepenbreier

SQL 和 Python 已经迅速成为任何从事严肃数据分析的人的必备技能!本 Python SQLite 教程是您在 Python 中使用 SQLite 的唯一指南。在本帖中,我们将介绍:

  • 正在加载库
  • 创建并连接到您的数据库
  • 创建数据库表
  • 添加数据
  • 查询数据
  • 删除数据
  • 还有更多!

SQLite3(我们称之为 SQLite)是标准 Python 3 包的一部分,所以您不需要安装任何东西。如果你没有运行 Python 3,请点击链接开始。

如果你想开始学习 SQL,可以看看我的完整的初级 SQL 教程,其中包括免费下载的 PDF 和其他赠品。

你会创造什么

学习完本教程后,您将使用 Python 在 SQLite 中创建了一个数据库。具体来说,这篇文章将指导您完成创建数据库的所有步骤,该数据库涵盖了下表,包括所有关系:

我们将创建的数据库的概述。资料来源:Nik Piepenbreier

SQLite for Python 中可用的数据类型

SQLite for Python 提供的数据类型比其他 SQL 实现少。这可能有点限制。然而,正如您将看到的,SQLite 使许多其他事情变得更容易。让我们快速看一下可用的数据类型:

  • 空值 —包括一个空值
  • 整数 —包括一个整数
  • 实数 —包括一个浮点(十进制)值
  • 正文。—包括文本
  • 斑点。—包括完全作为输入存储的二进制大对象

从这个列表中,您可能会注意到一些缺失的数据类型,如日期。不幸的是,在使用 SQLite 时,您只能使用这些数据类型。

Python 中的 SQLite 入门

准备好了吗?我们开始吧!资料来源:Nik Piepenbreier

让我们从加载库开始本教程。我们可以通过使用以下命令来实现这一点:

import sqlite3

让我们开始实际创建我们的数据库。

用 Python 创建 SQLite 数据库

在 Python SQLite 教程的这一部分,我们将探索使用 SQLite 在 Python 中创建数据库的不同方法。为此,我们将创建一个代表数据库的 连接 对象。这个对象是使用 SQLite 的 connect()函数创建的。

让我们首先创建一个. db 文件,因为这是实际维护 SQLite 数据库的一种非常标准的方式。我们将使用名为 conn 的变量来表示连接。我们将创建一个名为 orders.db 的文件。

conn = sqlite3.connect('orders.db')

通过这行代码,我们创建了一个新的连接对象,以及一个名为 orders.db 的新文件,该文件位于您正在工作的目录中。如果您想指定一个特定的目录,您可以写:

conn = sqlite3.connect(r'PATH-TO-YOUR-DIRECTORY/orders.db')

如果文件已经存在,那么连接功能将简单地连接到该文件。

注意:注意我们在包含这个路径的字符串前包含了字母“r”。这让 Python 知道我们正在处理一个原始字符串,这意味着“/”不会用于转义字符。你可以通过查看此链接了解更多关于原始字符串的信息。

connect 函数创建一个到 SQLite 数据库的连接,并返回一个对象来表示它。

内存数据库

使用 Python 中的 SQLite 生成数据库的另一种方法是在内存中创建数据库。这是生成可用于测试目的的数据库的好方法,因为它们只存在于 RAM 中。

conn = sqlite3.connect(:memory:)

然而,出于本教程的目的,对于您将遇到的大多数用例,您将使用我们前面描述的方法。

创建光标对象

现在我们已经创建了一个数据库连接对象,我们的下一个任务是创建一个 光标 对象。简单地说,游标对象允许我们对数据库执行 SQL 查询。我们将创建一个变量 cur 来保存光标对象:

cur = conn.cursor()

游标对于 Python 中的 SQLite3 至关重要。资料来源:Nik Piepenbreier

现在我们有了一个 cursor 对象,我们可以使用它以下面的方式运行 SQL 查询:

cur.execute("YOUR-SQL-QUERY-HERE;")

注意,我们用引号将 SQL 查询括起来,这很重要。不管我们使用单引号、双引号还是三引号。对于较长的查询,通常最好使用三重引号,因为它们允许我们编写多行查询。

在 SQLite for Python 中创建我们的表

在 Python SQLite 教程的这一点上,让我们使用 Python 中的 SQLite 创建我们的第一个表!现在我们有了一个连接对象( conn )和一个光标对象( cur ),我们可以创建我们的第一个表了。按照我们之前展示的数据库模式:

快速提醒一下我们的数据库是什么样子的。资料来源:Nik Piepenbreier

我们将从用户表开始。

cur.execute("""CREATE TABLE IF NOT EXISTS users(
   userid INT PRIMARY KEY,
   fname TEXT,
   lname TEXT,
   gender TEXT);
""")
conn.commit()

在上面的代码中,我们做了很多事情:

  1. 使用游标对象上的 execute 函数执行 SQL 查询
  2. 使用 SQL 生成一个名为用户的表
  3. 如果不存在,那么将在重新连接到数据库时帮助我们。该查询将允许我们检查该表是否存在,如果存在,则没有任何改变。
  4. 我们创建四列:用户 id名字名字性别用户标识被指定为主键。
  5. 我们通过在连接对象上使用提交函数来提交更改。

准备好桌子了吗?资料来源:Nik Piepenbreier

要创建我们的另一个表,我们可以遵循类似的模式并编写以下命令:

cur.execute("""CREATE TABLE IF NOT EXISTS orders(
   orderid INT PRIMARY KEY,
   date TEXT,
   userid TEXT,
   total TEXT);
""")
conn.commit()

执行这两个脚本后,您的数据库将有两个表。我们现在准备开始添加数据!

在 Python 中使用 SQLite 添加数据

让我们看看如何用 Python 中的 SQLite 向我们刚刚创建的数据库添加数据。与表生成查询类似,添加数据的查询使用 cursor 对象来执行查询。

cur.execute("""INSERT INTO users(userid, fname, lname, gender) 
   VALUES('00001', 'Nik', 'Piepenbreier', 'male');""")conn.commit()

通常,当我们在 Python 中工作时,我们会有保存值的变量。例如,我们可能有一个包含用户信息的元组,可能如下所示:

user = ('00002', 'Lois', 'Lane', 'Female')

如果我们想将这些数据加载到数据库中,我们将使用不同的约定:

cur.execute("INSERT INTO users VALUES(?, ?, ?, ?);", user)
conn.commit()

我们在这里做的是用问号替换所有的值,并添加一个包含我们希望添加的值的附加参数。

这里需要注意的是,SQLite 期望值是元组格式的。但是,变量可以包含列表,只要列表项是元组。例如,我们可以使用变量添加更多用户:

more_users = [('00003', 'Peter', 'Parker', 'Male'), ('00004', 'Bruce', 'Wayne', 'male')]

在这种情况下,我们不想使用 execute 函数,而是希望使用 executemany 函数:

cur.executemany("INSERT INTO users VALUES(?, ?, ?, ?);", more_users)conn.commit()

如果我们在 cursor 对象上使用了 execute 函数,该函数会假设我们将两个条目(两个元组)直接传入表中,而不是两组,每组四个条目!幸运的是,在这种情况下,这个函数可能会失败,但是要小心使用哪个函数!

SQLite 和防止注入攻击

顺便说一下,使用(?, ?,…)我们上面提到的方法也有助于抵御 SQL 注入攻击。因此,建议使用这种方法,而不是前面提到的方法。也更容易打出来,所以是双赢!

一些加载更多数据的脚本

如果您正在学习 Python SQLite 教程,让我们加载更多的数据,使下面的部分更有意义。下面是一些脚本,您可以复制并粘贴这些脚本,将一些示例数据插入到这两个表中:

如果您正在跟进,也加载这些数据文件!资料来源:Nik Piepenbreier

您可以使用以下查询来加载此数据:

cur.executemany("INSERT INTO users VALUES(?, ?, ?, ?);", customers)
cur.executemany("INSERT INTO orders VALUES(?, ?, ?, ?);", orders)
conn.commit()

使用 Python 在 SQLite 中选择数据

接下来,在这个 Python SQLite 教程中,我们将看看如何在 Python 中使用 SQLite 选择数据!我们将遵循与上面执行查询类似的结构,但是我们也将向其中添加另一个元素。

有许多方法可以返回数据。资料来源:Nik Piepenbreier

通过 Python 在 SQLite 中使用 fetchone()

让我们从使用 fetchone()函数开始。我们创建了一个变量 one_result 来只提取结果

cur.execute("SELECT * FROM users;")
one_result = cur.fetchone()
print(one_result)

这将返回:

[(1, 'Nik', 'Piepenbreier', 'male')]

通过 Python 在 SQLite 中使用 fetchmany()

假设我们想要返回不止一个结果,我们可以使用 fetchmany()函数。让我们运行一个不同的脚本来生成 3 个结果:

cur.execute("SELECT * FROM users;")
three_results = cur.fetchmany(3)
print(three_results)

这将返回以下内容:

[(1, 'Nik', 'Piepenbreier', 'male'), (2, 'Lois', 'Lane', 'Female'), (3, 'Peter', 'Parker', 'Male')]

通过 Python 在 SQLite 中使用 fetchall()

类似地,我们可以使用 fetchall()函数返回所有结果。如果我们运行以下命令,将返回所有结果:

cur.execute("SELECT * FROM users;")
all_results = cur.fetchall()
print(all_results)

用 Python 删除 SQLite 中的数据

让我们也学习一下如何删除数据!资料来源:Nik Piepenbreier

现在,我们来看看如何在 Python 中使用 SQLite 删除数据。我们可以使用与上面类似的结构来实现这一点。假设我们想要删除姓“Parker”的任何用户,我们可以写:

cur.execute("DELETE FROM users WHERE lname='Parker';")
conn.commit()

当我们运行下面的查询时:

cur.execute("select * from users where lname='Parker'")
print(cur.fetchall())

这将打印出一个空列表,确认记录已被删除。

在 Python 中用 SQLite 连接表

最后,让我们看看如何用更复杂的查询连接数据。假设我们想要生成一个查询,其中包含每个订单上每个客户的名字和姓氏。

为了实现这一点,我们编写以下代码:

cur.execute("""SELECT *, users.fname, users.lname FROM orders
    LEFT JOIN users ON users.userid=orders.userid;""")
print(cur.fetchall())

类似地,您可以应用一些其他的 SQL 技巧。关于 SQL 的完整介绍,点击这里查看我的完整初学者指南

结论:Python SQLite 教程

在这篇 Python SQLite 教程中,我们探索了开始使用 Python 中的 SQLite 所需要知道的一切。我们从如何加载库开始,探索了如何创建数据库和表,如何添加数据,如何查询表,以及如何删除数据。

非常感谢您抽出时间!你真的真的很棒!资料来源:Nik Piepenbreier

posted @ 2024-10-14 11:52  绝不原创的飞龙  阅读(3)  评论(0编辑  收藏  举报