TowardsDataScience 博客中文翻译 2021(三百五十八)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

如何聚类数据!

原文:https://towardsdatascience.com/how-to-cluster-data-65d37c98ce55?source=collection_archive---------32-----------------------

使用无监督机器学习和 K-均值聚类的指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:我

在从事数据科学项目时,数据科学家经常会遇到含有未标记数据点的数据集。因此,很难获得可用于对数据行为建模的有洞察力的知识。为了从无意义的数据中找出意义,部署了无监督的机器学习技术来标记数据点,并提供不同类别之间的清晰对比。

一种非凡的无监督机器学习技术被称为聚类。聚类是将未标记的数据分组到类中的一种很好的机制。它通过检查整个数据集来寻找数据点变量之间的相似性。注意到某些相似性后,可以将数据集分成多个组,组成员拥有相似的属性。 K 均值聚类是本文将要探讨的聚类类型。

K-Means 通过 scikit-learn 进行聚类

样本聚类

Scikit-learn 是一个机器学习库,可以通过 Python 获得。它可以用来建立机器学习算法,以做出准确的预测。K-means 聚类模型是使用下面的代码通过 scikit-learn 导入的。

**from** **sklearn.cluster** **import** KMeans

需要一个数据集来利用 K 均值聚类模型。因此,goodreads 书籍评级的数据集从 Kaggle 下载并上传到 Jupyter Notebook。然后,提取数值变量,如平均评分、页数、评分计数和文本评论计数。使用这四个变量,可以在数据集上拟合 K 均值聚类。

下一步是计算出将数据集合理分组的最佳聚类(组)数量。通过尝试不同数量的簇,有可能计算出它们的惯性。K 均值聚类的惯性是对聚类的一致性和独特性的度量。通过绘制惯性对聚类数的图表,在图表上创建肘状结构的点处选择最优的聚类数。这样做是因为增加超过肘点的簇的数量不会大量改变惯性值,并且最终会创建不必要的额外簇/组。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

聚类的最佳数量将是 4,因为这是创建图形肘部的位置

因此,选择四个组作为组的数量。然后,将其拟合到 goodreads 图书数据集上,以便将标签归属于数据点。

kmeans_book = KMeans(n_clusters = 4)
kmeans_book.fit_predict(books_df)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

goodreads ’ book 数据集的前五行在 K-Means 聚类适合数据集后进行标记

通过选择四个聚类,创建了理想地代表每个聚类的四个中心。然后,测量每个数据点与中心的距离,并根据其最近的聚类中心标记数据点。下面可以看到四个聚类中心。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据集中的四个聚类中心

作为预处理形式的聚类

K-means 聚类也可以用作构建机器学习算法时的预处理方法。这可以通过创建一个管道来实现,在该管道中,对独立变量应用 K 均值聚类,以测量每个数据点到聚类中心的距离。然后,可以应用分类器,根据数据点到聚类中心的距离来标记数据。

K-means 聚类作为预处理器的一个用例可以在红酒质量的分类中找到。首先,将数据集分成训练和测试数据集,并使用两个聚类的 K-means 聚类和决策树分类器创建管道。

**from** **sklearn.model_selection** **import** train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state = 10, train_size = 0.8)pipeline = Pipeline([("kmeans", KMeans(n_clusters = 2)), ("dec", DecisionTreeClassifier())])

上面显示的管道代码可以适用于训练数据,并用于对测试数据的独立变量进行预测。

pipeline.fit(x_train, y_train)
y_pred = pipeline.predict(x_test)

在下图中可以看到聚类中心。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

管道的聚集中心

管道的准确度分数约为 0.74。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

管道的准确度分数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

葡萄酒质量检测数据的前五行。包含数据点预测质量的列被附加到表格中。

结论

聚类为数据科学家提供了一种从无意义的数据集中提取有用信息的方法。通过对数据集进行聚类,可以对其进行标记,这些标记可用于模拟数据点的行为或创建可视化图表,以有效区分数据集上的不同点。在未标记数据集带来的混乱中,K-means 聚类是一种建立这些数据集结构的好方法。

本文使用的代码的链接可以在这里 查看

非常感谢您的阅读!

如何在 Python 中使用 TF-IDF 和图划分对相似句子进行聚类

原文:https://towardsdatascience.com/how-to-cluster-similar-sentences-using-tf-idf-and-graph-partitioning-in-python-5fb70627a4e0?source=collection_archive---------2-----------------------

哪些数据科学文章更能吸引读者(第二部分)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Hanson LuUnsplash 上的照片

在这一系列文章中,我们分析了数据科学出版物的历史档案,以了解哪些主题更受读者欢迎。之前我们讨论过如何获取将用于进一步分析的数据

在本文中,我们将介绍如何清理我们之前收集的文本数据,使用网络图对相似的主题进行分组,并在这些集群中建立模式。

数据汇总

让我们提醒自己数据是什么样子的。它是从三个数据源[field:’ Source ‘]—Analytics vid hya[’ avd ']、 TDS [‘tds’]和获得的文章的组合。

我们收集了出版物档案中每篇文章的标题、副标题、掌声和回应。

import pandas as pd# Reading the data obtained using code [here](https://medium.com/analytics-vidhya/what-data-science-articles-attract-more-attention-part-1-efe8faf209d0).
avd = pd.read_csv('analytics_vidhya_data.csv')
tds = pd.read_csv('medium_articles.csv')
tai = pd.read_csv('towards_ai_data.csv')avd['source'] = 'avd'
tds['source'] = 'tds'
tai['source'] = 'tai'# Create single data set, join title and subtitle
single_matrix = pd.concat([avd, tds, tai])
single_matrix['title_subtitle'] = [' '.join([str(i),str(j)]) for i, j in zip(single_matrix['Title'].fillna(''), single_matrix['Subtitle'].fillna(''))]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

文章数据集

我们在数据集中添加了一个名为“title_subtitle”的附加列,它是列*“Title”“Subtitle”*的连接,我们将主要使用这个列,以便更好地查看文章所属的主题。非常有趣的是,39%的文章没有副标题,只有很小一部分没有标题。

让我们快速看一下每个数据源的掌声和响应分布。我们从方框图开始,我们使用 Python 中的 seaborn 库来创建我们的图。

# We will use seaborn to create all plots
import seaborn as sns
import matplotlib.pyplot as pltfig, axes = plt.subplots(1, 2, figsize=(8, 5))
# Claps
sns.boxplot(ax=axes[0], x="source", y="Claps", data=single_matrix)# Responses
sns.boxplot(ax=axes[1], x="source", y="Responses", data=single_matrix)

我们可以看到,走向数据科学不仅有更多的活动,而且有相当多的离群值,个别文章获得了读者的大量吸引力。当然,每个来源的活动取决于出版物的规模,对于较大的出版物,我们观察到更多的作者和读者。

当涉及到回应时,我们观察到的活动远少于所有来源的鼓掌,尽管这种行为并不十分意外。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

按来源划分的掌声和回应的箱线图

接下来,我们移除异常值并可视化场的分布,以获得更清晰的图像。

# Code to create distribution subplots
fig, axes = plt.subplots(2, 1, figsize=(8, 8))# Claps
sns.distplot(avd['Claps'][avd['Claps']<10000], hist=True, rug=False, ax=axes[0])
sns.distplot(tds['Claps'][tds['Claps']<10000], hist=True, rug=False, ax=axes[0])
sns.distplot(tai['Claps'][tai['Claps']<10000], hist=True, rug=False, ax=axes[0])# Responses
sns.distplot(avd['Responses'], hist=True, rug=False, ax=axes[1])
sns.distplot(tds['Responses'], hist=True, rug=False, ax=axes[1])
sns.distplot(tai['Responses'], hist=True, rug=False, ax=axes[1])

我们可以看到两种分布都向左倾斜,这意味着大多数文章得到的掌声很少,甚至更少的回应。然而,这并不奇怪,因为文章的成功取决于许多因素,如高质量的写作,相关的主题等等。取得良好的平衡不是一件简单的事情!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

按来源划分的掌声和响应分布

如何清理文本数据?

在处理文本时,清理数据是一个重要的步骤(如果不是最重要的部分的话)。在处理这类任务时,有标准的做法可以遵循。我们将采取以下步骤来处理标题和字幕:

  • 删除标点符号和其他符号
  • 删除停用词和数字
  • 词汇

我们将混合使用正则表达式和 nltk 库来 删除标点符号、符号、停用词和数字

import re
single_matrix['title_subtitle'] = [re.findall(r'\w+', i.lower()) for i in single_matrix['title_subtitle'].fillna('NONE')]

上面的代码匹配一个或多个单词字符,事实上 r’\w+’r '[a-zA-Z0–9 _]+'相同。同样,在应用 re.findall()i.lower() 命令时,他们方便地将句子拆分成单词,并转换成小写。这将在接下来的步骤中非常有用。因此,句子‘在 qlikview 中报告|临时报告’变成了【报告,在,Qlikview,临时,临时,报告】。

接下来,我们将使用 nltk 库上传一个停用词词典,这样我们就可以将它们从句子中删除。此外,我们将单词“使用”和“部分”添加到列表中,因为它们在数据集中被过度使用。为了删除我们用于循环迭代每个句子的停用词,在这样做的时候,我们也确保从句子中删除数字。

# The code to upload list of stop words and remove them from sentencesimport nltk
nltk.download('stopwords') 
from nltk.corpus import stopwordsstopwords_eng = stopwords.words('english')  
stopwords_eng += ['use', 'using', 'used', 'part']new_titles_sub = []
for title_sub in single_matrix['new_title_subtitle']:
    new_title_sub = []
    for w_title in title_sub:
        if w_title not in stopwords_eng and not w_title.isdigit():
            new_title_sub.append(w_title)

    new_titles_sub.append(new_title_sub) 

single_matrix['new_title_subtitle'] = new_titles_sub

最后,我们要把句子中的单词去掉。考虑到上下文,词条解释将单词转换为其有意义的词根形式。频繁的词干提取是一种计算速度更快的替代方法,但是不够精确。我们再次使用 nltk 来表示单词

nltk.download('wordnet')
nltk.download('words')
from nltk.stem import WordNetLemmatizer
wordnet_lemmatizer = WordNetLemmatizer()new_titles_sub = []
for title_sub in single_matrix['title_subtitle']:
    new_title_sub = []
    for w_title in title_sub:
        new_title_sub.append(wordnet_lemmatizer.lemmatize(w_title, pos="v"))
    new_titles_sub.append(new_title_sub) 

single_matrix['new_title_subtitle'] = new_titles_sub
single_matrix['new_title_subtitle'] = [' '.join(i) for i in single_matrix['new_title_subtitle']]

让我们看看所有转换后的句子是什么样的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如何使用 TF-IDF 对文本数据进行矢量化?

TF-IDF 代表术语频率-逆文档频率,它是*某个特定文档集中某个关键字与某个文档相关程度的数值度量。*它常用于文本分析,一些例子包括内容排名和信息检索。这里的是一篇非常有用的论文,更详细地讨论了这种方法。

顾名思义,该度量由两部分组成,一部分是查找单词在文档中出现的频率(TF),另一部分是单词在语料库中唯一性的程度(IDF)。让我们来看看简化版的公式及其组成部分:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看到,更频繁出现的单词将导致更低的 TF-IDF 分数,而对于罕见的单词,分数将更高。这种权重调整非常重要,因为过度使用的单词不会有额外的意义。

理解计算的最简单的方法是举例,在我们的数据集中,单个标题是一个文档,所有标题形成一个语料库(文档集)。考虑标题*‘使用变量 qlikview 创建强大的数据故事’中的*‘create’一词,文档有 7 个词,‘create’只出现一次,所以 TF(create) = 1/7 。其中一个数据源中的文章总数为 12963 ,单词‘create’出现在 268 标题中,因此IDF(create)= log(12963/268)= 3.88。因此, TF-IDF =0.143.88 = 0.55* 就是单词*‘create’*的得分。

既然我们知道了如何计算文档中每个单词的分数,我们就可以对带有文章标题和副标题的数据集进行矢量化处理。为此我们将使用 Python 中的 sklearn 库,特别是tfidf 矢量化 r 函数。

注意:tfidf 矢量化 r 使用的公式与上面指定的略有不同,它将 IDF 加 1。这样做是为了确保每个文档中出现的单词不会被忽略。

from sklearn.feature_extraction.text import TfidfVectorizertf = TfidfVectorizer(analyzer='word', ngram_range=(1, 3), min_df=0)tfidf_matrices = []
data_sets = []
for source in ['avd', 'tai', 'tds']:
    source_data = single_matrix[single_matrix['source'] == source].drop_duplicates()
    data_sets.append(source_data['new_title_subtitle'])
    tfidf_matrices.append(tf.fit_transform(
source_data['new_title_subtitle']))

我们引入了遍历数据源的 for 循环,这样做是为了缩短计算时间。当查看所有句子对之间的距离并将它们分成组时,也需要这样做。输出是稀疏矩阵,其中行是文档,列是语料库中唯一的单词。

现在我们已经有了矢量化的标题和副标题,我们可以计算所有句子之间的成对距离。我们将在代表句子的向量对之间使用余弦相似度。该度量考虑两个向量之间的角度,通常用于文本分析。对所选相似性度量的一些很好的解释可以在这里找到,本文不仅提供了清晰的定义,还讨论了基于上下文的使用。

我们使用 sklearn 库来计算成对余弦相似度,再一次根据源进行分割。

from sklearn.metrics.pairwise import linear_kernel
matrix_with_cos_sim = []
for m in tfidf_matrices:
    matrix_with_cos_sim.append(linear_kernel(m, m))

每个数据源的输出是一个 numpy 数组(NxN ),所有句子之间具有成对的相似性,其中 N 是单个数据源的标题/副标题的数量。

如何利用网络图将相似的句子分组?

我们的目标是找到包含类似数据科学主题的文章的聚类,为此,我们将从构建一个加权图开始,其中节点是文章,边是它们的余弦相似性。然后,我们能够通过应用图划分来创建聚类,目的是在不强加大量社区的情况下找到有意义的子图(也称为社区)。

我们将使用 Python 库 networkx社区来构建和划分图表。在我们继续构建图表之前,我们将只为语料库中的每个文档选择前 15 个相似的标题,这个数字是根据称为模块性的度量来选择的,模块性给出了划分有多好的指示。这种方法不仅锐化了图形,而且有助于提高计算速度。

import numpy as np
from tqdm import tnrange
top_n_sentences = []
for cs, t in zip(matrix_with_cos_sim, data_sets):
    no_dups = np.array(t)
    i = 0
    top_frame = []
    for c, z in zip(cs, tnrange(len(cs))):
        # Create vector of titles
        start_name = pd.Series([no_dups[i]]*15) 
        # Index of top 15 similar titles
        ix_top_n = np.argsort(-c)[0:15]
        cos_sim = pd.Series(c[ix_top_n])
        names = pd.Series(no_dups[ix_top_n])
        i +=1
        top_frame.append(pd.DataFrame([start_name, names, cos_sim]).transpose())

    top_frame = pd.concat(top_frame)
    top_frame.columns = ['title1', 'title2', 'cos_sim']
    # Remove the similarities for the same sentences
    top_frame['is_same'] = [bool(i==j) for i, j in zip(top_frame['title1'], top_frame['title2'])]
    top_frame = top_frame[top_frame['is_same'] != True]

    top_n_sentences.append(top_frame)

该脚本为数据集中的每个标题生成具有前 15 个相似标题的数据框(按源划分),它将用作构建图表的输入。让我们看看其中一个源的数据框示例

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们将继续构建和划分图表,我们将对拥有第二大数量文章的源(Analytics Vidhya)进行构建和划分。这些代码片段可以应用于本文涵盖的所有源代码。

# We start by defining the structure of the graphtop_frame = top_n_sentences[2] #TDS articlesedges = list(zip(top_frame['title1'], top_frame['title2']))
weighted_edges = list(zip(top_frame['title1'], top_frame['title2'], top_frame['cos_sim']))
nodes = list(set(top_frame['title1']).union(set(top_frame['title2'])))

我们现在可以使用上面定义的结构使用 networkx 来构建图形

import networkx as nx
G = nx.Graph()
G.add_nodes_from(nodes)
G.add_edges_from(edges)
G.add_weighted_edges_from(weighted_edges)

接下来,我们使用社区库对图进行分区,在模块导入之前,确保安装 python-louvain 库以避免错误。

# !pip install python-louvainimport community
partition = community.best_partition(G)
modularity = community.modularity(partition, G)

前面我们提到了模块性,这是衡量分区好坏的标准,本例中的值是 0.7 。通常,大于 0.6 的值被认为是足够好的分区。

# Takes some time for larger graphs
import matplotlib.pyplot as plt
pos = nx.spring_layout(G, dim=2)
community_id = [partition[node] for node in G.nodes()]
fig = plt.figure(figsize=(10,10))
nx.draw(G, pos, edge_color = ['silver']*len(G.edges()), cmap=plt.cm.tab20,
        node_color=community_id, node_size=150)

上面的代码生成了我们刚刚发现的图形和社区,虽然这个图看起来很忙,但我们仍然能够看到通过这种方法发现了相当多的集群。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

标题和副标题被划分到社区中

在我们更详细地研究集群之前,我们将把我们之前创建的分区变量转换成更易读的格式。

title, cluster = [], []
for i in partition.items():
    title.append(i[0])
    cluster.append(i[1])

frame_clust = pd.DataFrame([pd.Series(title), pd.Series(cluster)]).transpose()
frame_clust.columns = ['Title', 'Cluster']

上面代码的输出是数据帧,其中包含所有标题和副标题以及它们所属的社区,通过对图进行划分,可以识别出 45 个集群。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

标题和副标题被划分到社区中

现在我们已经获得了集群,我们可以为每个集群创建汇总统计数据,以了解其中是否有任何集群有更多的活动。我们将有分区的数据集与有掌声和回应的数据集合并,然后我们将计算每个组的最小值、最大值、平均值、中值和文章数。尽管主要关注中值,因为我们之前看到数据偏向较小的值,并且存在异常值。

avd = single_matrix[single_matrix['source'] ==           'avd'].drop_duplicates()frame_clust = frame_clust.merge(tds[['Title', 'new_title_subtitle', 'Claps', 'Responses']], how='left', left_on='Title', right_on='new_title_subtitle')grouped_mat = frame_clust.groupby('Cluster').agg(
{'Claps': ['max', 'mean', 'sum', 'median'],
 'Responses': ['max', 'mean', 'sum', 'median'], 
 'Title_x': 'count'}).reset_index()grouped_mat.columns = ['cluster', 'claps_max', 'claps_mean',  'claps_sum', 'claps_median','responses_max', 'responses_mean', 'responses_sum', 'responses_median', 'title_count']grouped_mat = grouped_mat.sort_values(by = ['claps_median', 'title_count'])

出于代表性目的,我们将只关注读者活跃度最低的三个社区和读者活跃度最高的三个社区。我们首先考虑数据集,然后我们将可视化单词云,以确定每个小组的共同主题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

读者活跃度最低和最高的社区

上表显示,这些群组并不是很大,让我们看看每个群组中有哪些共同的主题,我们将使用 wordcloud 库。

from wordcloud import WordCloud
fig, ax = plt.subplots(1, 3, figsize=(12.5,6.5))clusters = [19, 39, 38] #lowest activity groups
# clusters = [43, 28, 7] #highest activity groupsfor cluster, col in zip(clusters, [0, 1, 2]):
    corpus = ' '.join(frame_clust['new_title_subtitle'].  [frame_clust['Cluster'] == cluster])
    ax[col].imshow(WordCloud(width = 800,
                             height = 800,
                             background_color ='white', 
                             min_font_size = 10).generate(corpus))
    ax[col].axis("off")plt.show()

我们首先看一下活跃度最低的社区,看起来第 19 类的文章大多属于一个作者,这可以解释活跃度较低的原因。另外两个集群由多个作者撰写的更多文章组成。有趣的是,我们可以观察到诸如“python 中的面向对象编程”和“欺诈检测”这样的主题引起了读者最少的兴趣。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

读者活动较少的群集

转到最活跃的集群,引起读者更多兴趣的突出主题是自然语言处理、神经网络、激活函数和支持向量机。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

读者活跃度较高的集群

总结

虽然我们能够在低和高读者活动组中建立共同的主题,但我们仍然观察到没有很多掌声和回应的文章,以及在每个组中有高活动的文章。当试图建立读者感兴趣的一般模式以及文章饱和度较高的主题时,这种分析会很方便。然而,选择一个相关的主题并不能保证文章的成功,因为许多其他重要因素有助于吸引读者。

强化学习的值迭代算法如何编码

原文:https://towardsdatascience.com/how-to-code-the-value-iteration-algorithm-for-reinforcement-learning-8fb806e117d1?source=collection_archive---------0-----------------------

利用强化学习求解 MDP

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源

在本文中,我将向您展示如何实现价值迭代算法来解决马尔可夫决策过程(MDP)。当你进入强化学习和人工智能时,这是你应该学习的第一个算法。

强化学习是机器学习的一个领域,它专注于让代理学习如何在特定环境中表现/行动。MDP 仅仅意味着问题的框架,环境本身。

什么构成了 MDP?

MDP 由 5 个元素组成。

  1. 一套状态。这表示代理在环境中的所有可能位置。
  2. 一套动作。这表示代理在任何给定状态下可以采取的所有操作。
  3. 转移概率。这表示代理尝试的操作成功(或失败)的概率。
  4. 奖励,是到达特定状态的数值。
  5. 折扣系数γ ,与即时奖励相比,这意味着减少未来奖励的价值。

MDP 中代理的目标是找到最优策略,即在任何给定状态下采取的最优行动的集合。

一个例子

理解这一切的最简单的方法是用一个例子。

假设我们有一只熊(代理人)想要得到蜂蜜(正奖励),同时避开它周围的蜜蜂(负奖励)。在每个单元(或状态),熊可以采取行动。例如,从他的实际位置,他可以向下或向右。最后,我们有转移概率。有时候,熊会打算做一些事情,但它会做其他事情(例如,向下而不是向左)。靠近蜜蜂会变得更加“危险”,因为失足可能意味着负面的回报。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:自制图片

现在,为了找到获得蜂蜜的最佳方式,熊将在环境中行走。他可能会走进蜜蜂,被蛰,并学会避免这种状态。最终,随着时间的推移,他会弄清楚如何在任何给定的状态下表现,以获得蜂蜜而没有后果!聪明的熊!

但是熊将如何学习呢?数值迭代算法是解决这一问题最常用的算法之一。让我们开始吧。

值迭代算法

该算法试图找到处于任何给定状态的值 V(st)。它使用贝尔曼方程。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:https://artint.info/html/ArtInt_227.html

别担心,这真的没那么复杂。所有这一切意味着,考虑到转移概率,处于一个状态的价值等于该状态的直接回报®加上每个相邻状态的贴现回报(St+1)的最大值。因此,我们在这个算法中只先行一步。

这是一种迭代算法,其中状态值不断更新,直到收敛,即当值停止变化时。

最终,最优策略是隐含的,因为它将是为每个状态提供最佳价值的行动。

用 Python 实现算法

现在让我们进入有趣的部分!

下面是第一部分,代表了 MDP 的初始设置/创建(状态、动作、奖励等)。).

SMALL_ENOUGH变量是用来决定在哪个点上停止算法是合适的。Noise代表随机行动而非有意行动的概率。

在第 13–16 行,我们创建了状态。在第 19–28 行,我们为各州创建了所有奖励。有蜂蜜的州为+1,有蜜蜂的州为-1,其他州为 0。

然后,我们创建一个字典,包含任何状态的所有可能的动作。每个状态有 2 到 4 个可能的动作(向下、向上、向左或向右)。

最后,我们为每个状态定义一个初始随机策略以及一个值字典,包含每个状态的初始奖励。这最后一个字典将在算法期间被更新。

下面是值迭代算法。

从第 8 行和第 14 行可以看出,我们遍历了每个状态和每个状态中的每个动作。

在第 25–33 行,我们选择了一个随机的动作,在 10%的时间里,它会被执行,而不是预期的动作。这增加了问题的不确定性,使其成为非确定性的。通常,在值迭代中,您可能有不止一个可能的随机动作(考虑所有相邻的状态)或者甚至更高的噪声。然而,在这里,为了保持简单并确保算法快速运行,我只选择了一个可能的随机动作,每个状态发生的概率相对较小。

在第 38 行,我们计算在一个状态中采取一个动作的值。

在第 40-41 行,我们保存了与最佳值相关联的动作,这将给出我们的最优策略。

最后,在第 48 行,如果迭代期间在所有状态中观察到的最大改进被认为太小,则算法停止。

结果呢

这个超级小的例子在 44649 次迭代中收敛。

以下是与每个州相关的值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们看到,越接近最终回报,处于这种状态的价值就越高。

我们还看到,处于状态(2,1)的值(0.259)比更远的状态(2,0)的值(0.338)小。这是因为当接近负回报时,熊可能会失足撞到蜜蜂。因此,在这种情况下,最好远离这些州,即使这意味着也远离蜂蜜!

从这些值中,我们可以得出最优策略。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

显然,我使用的例子非常简单,因此只需查看环境就可以很容易地找出最佳策略。然而,环境变得越大,我们人类就越难找出每个国家的最佳行动方案。对于电脑来说,不是。

之前不知道该做什么的熊,现在已经学会了如何在躲避蜜蜂的同时获取蜂蜜。对他有好处!

下面的存储库包含了这个项目使用的所有代码:https://github . com/francoistamant/reinforcement-learning-MDP

非常感谢你的阅读,我希望你学到了一些东西,如果你有任何问题,请随时联系我!

成为会员:【https://francoisstamant.medium.com/membership】T2

当你只知道 Jupyter 笔记本时如何编码

原文:https://towardsdatascience.com/how-to-code-when-all-you-know-are-jupyter-notebooks-78cf8d4f32e0?source=collection_archive---------12-----------------------

从笔记本转换到 Python 文件的初学者指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

克里斯里德在 Unsplash 上的照片

当我开始我的第一份机器学习工作时,我之前所有的编码都是在 Jupyter 笔记本上完成的。然而,我开始工作的公司没有使用它们,所以我有点害怕不知道没有它们如何编码,而是必须使用 Python 文件。也许你发现自己处于和我当时相似的位置,开始学习如何使用文件和脚本,但不知道如何开始。唉,这是我的教程,当你只知道 Jupyter 笔记本时,如何编码。

Jupyter Notebook 是一个方便的小东西:你可以编写代码,合并细胞,分割细胞,运行单个细胞——无论它们在笔记本中的什么位置——并直接在执行的细胞下方看到输出。然而,就像生活中的一切一样,笔记本也有它们的问题:它们可能会很乱,以非线性顺序执行单元格的能力使得再现性很难,并且很难将笔记本中的代码投入生产。Python 文件不会带来这些问题,一旦你学会了使用它们,它们实际上会使编码变得更加容易。

那么什么是 Python 文件呢?它是 Python 函数和语句的集合,要么直接执行,要么从其他地方导入。这个代码集合可以像带有. py 后缀的文本文件一样简单,用文本编辑器打开。然而,更常见(也更实用)的是使用 IDE 来处理文件,比如 PyCharmVisual Code Studio 。(为了熟悉 PyCharm 的基础知识,我在这里推荐这个简短的教程。它向您展示了如何启动项目、创建文件以及运行这些文件。关于 Visual Code Studio 的简短介绍,点击这里。)

开发代码

在我的第一份工作开始时,在 PyCharm 中执行脚本对我来说并不神秘。相反,我不确定如何使用简单的脚本而不是笔记本来开发 T21 代码。

编码是一个迭代的过程。你写几行代码,看看行不行,再写更多的代码,等等。在 Jupyter 笔记本中,这个过程非常简单,因为它允许您执行每一行来查看它是否工作。当使用脚本时,事情有点不同,因为您不能只执行一行。你或多或少必须从头到尾运行你的整个脚本。

当从 Jupyter 笔记本切换到 Python 脚本时,对我来说效果很好的是下面的方法:我写了一段代码(一到三行左右),然后运行脚本看看它是否工作。在整个代码中使用 Print 语句通常是检查代码是否真的在做您想要它做的事情的好方法。像这样:

在这个例子中,我编写了一个函数,用零值填充图像,这样图像就得到想要的形状。当我运行代码并且没有抛出错误时,我继续写一些代码行并再次检查我的代码是否运行没有任何错误:

如果是这样,我想写的函数就完成了,我删除打印语句和调用函数的行——瞧,它就完成了:

结合笔记本和脚本

老实说,我仍然经常使用 Jupyter 笔记本——它们太方便了,可以把我的可视化和数据分析都放在一个地方。在将代码转换成 Python 文件之前,我经常使用它们来开发代码。正如我上面提到的,笔记本非常适合运行单独的代码行来查看它们是否工作,这非常有帮助,尤其是当你还不是一个有经验的程序员的时候。

所以我经常做的是在笔记本上开发代码——一行一行,用打印语句来查看代码是否在做我想让它做的事情——直到我有了一个可以变成函数的代码块。然后我把这个函数放到一个 Python 文件中。如果我愿意,我可以将它从那里再次导入到我的笔记本中,以便在那里使用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在笔记本上逐行开发代码…

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

把它变成一种功能…

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将它复制粘贴到 Python 文件中…

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

…导入并执行笔记本中的功能

我希望您现在感觉不那么茫然了,并准备开始自己尝试 Python 文件。显然,我没有涵盖与 Python 文件相关的所有内容。因此,如果您想知道如何不从 ide 内部而是从命令行运行 Python 文件,我可以在这里推荐本文。如果你想了解更多关于导入模块的知识,你可以在这里阅读。玩得开心!

实现您自己的 Python 预提交挂钩

原文:https://towardsdatascience.com/how-to-code-your-own-python-pre-commit-hooks-with-bash-171298c6ee05?source=collection_archive---------21-----------------------

创建自己的预提交钩子作为 bash 脚本,用于静态分析和与 Git repo 的持续集成。

作者:爱德华·克鲁格道格拉斯·富兰克林

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

约翰·沃尔特·班茨在 Unsplash 上拍摄的照片

这里是这个项目的模板。我们使用诗歌进行包装管理。本文着重于编写定制的预提交钩子。

https://github.com/edkrueger/poetry-template

有关 Python 预提交钩子的更多介绍性信息,请查看本文。

什么是预提交挂钩?

预提交钩子是 Git 钩子的子集。Git-hooks 是每当 Git 存储库中发生特定操作时自动运行的脚本——比如提交或推送。“预提交挂钩”在提交发生之前运行。

预提交挂钩通常用于确保代码在发布前被正确地链接和格式化。这些钩子也用于持续集成、构建过程、依赖性管理和测试。然而,使用预提交钩子进行测试在 DevOps 领域是有争议的,不在我们的讨论范围之内。

通过简单的 bash 代码,您可以为特定需求创建自己的定制钩子——例如,持续集成到已部署的应用程序。

预提交 Python 包

令人困惑的是,还有一个叫pre-commit的 Python 包。预提交是一个用于预提交挂钩的管理工具。它在每次提交之前管理安装和执行挂钩。

我们需要安装pre-commit作为开发需求。例如,对于诗歌,你会跑;

poetry add pre-commit --dev

自定义挂钩

下面是我们的定制钩子的 bash 代码,create-requirements.这个 bash 脚本被设计来保持requirements.txt与诗歌的锁文件poetry.lock.同步

这很有用,因为如果我们保持需求是最新的,我们可以使用这个文件进行部署,避免任何定制的构建包。

例如,我们可以通过确保我们对虚拟环境依赖关系树所做的任何更改都反映在我们的requirements.txt文件中来保持 Heroku 应用程序的部署。

这很有用的另一个原因是,通过避免在容器中安装虚拟环境,您可以创建更轻、更简单的 docker 构建。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 Iza Gawrych 在 Unsplash 上拍摄

如果我们有一个与我们的requirements.txt不同步的虚拟环境,这个预提交钩子将捕获它,提供一个适当的错误消息,并创建正确的requirements.txt

write _ requirements.sh

让我们仔细看看我们的代码,看看 bash 和 exit 状态是如何与包pre-commit一起使用来阻止提交完成的。

在第 1 行,我们可以看到 bash 变量NEW_REQUIREMENTS存储了我们使用的包管理器poetry生成的需求。

第 3–9 行检查是否存在名为requirements.txt的文件,该文件提供了该结果的最终输出。如果文件不存在,我们使用退出状态 1 表示失败**,预提交停止提交。**

对于 bash shell 来说,以零(0)退出状态退出的命令已经成功。非零(1–255)退出状态表示失败。

bash 脚本将完成并最终生成一个新的requirements.txt文件,因为在检查第 11 行时NEW_REQUIREMENTS不等于空白的REQUIREMENTS

在第 11 行,我们将当前的requirements.txt文件存储为REQUIREMENTS。然后是第 13–15 行,检查旧版本REQUIREMENTS,是否与我们当前虚拟环境的NEW_REQUIREMENTS.相同。如果这些文件相同,我们不需要更新任何内容,并使用退出状态 0 来表示成功。如果create-requirements是我们的最后一个钩子,这允许预提交运行下一个钩子或者完成提交过程。

但是,如果REQUIREMENTSNEW_REQUIREMENTS不相同,我们需要重写我们的requirements.txt。这是在第 18 行完成的,我们从 poem 的虚拟环境中创建了一个新的requirements.txt文件。注意,在我们重写这个文件之后,我们使用退出状态 1,这样我们的脚本失败了,我们的提交也失败了。

这个失败允许我们运行git add requirements.txt来提交。我们的下一个git commit将重新运行我们的钩子,这一次通过所有的检查,因为新的requirements.txt对我们的虚拟环境是最新的。

该流程确保我们在本地运行应用的虚拟环境与我们在远程运行应用的虚拟环境保持一致。

确保我们的定制挂钩正常工作

在这里,我们运行一些检查来查看 bash 脚本是如何工作的。

首次测试

假设我们的回购中没有requirements.txt文件,我们尝试提交。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们的自定义挂钩失败

根据我们的 bash 代码,我们应该得到一个失败和requirements.txt does not exist错误消息。然后在目录中生成一个requirements.txt。我们可以通过运行git status.看到这一点

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

git 状态

请注意,我们现在有一个未被跟踪的requirements.txt.在实践中,人们现在会:

  • 运行git add requirement.txt
  • 运行git commit -m "add requirements.txt"

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们的定制钩子传递

现在我们的提交已经完成,可以推送给 git 了。

如果您不想提交这个检查,运行git reset HEAD~ 来恢复提交。

第二次测试

假设我们对虚拟环境的依赖关系进行了更改。我们可以用下面的代码运行预提交钩子。

 poetry run pre-commit run --all-files

这将给出与运行相同的终端输出:

git commit -m “modified requirements.txt”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然而,第一行只运行我们的预提交钩子,而第二行运行我们的钩子来准备提交。

请注意新的错误消息requirements.txt is not up to date!

同样,我们现在有一个由 bash 脚本的第 18 行生成的未跟踪的requirements.txt 。实际上,现在人们会:

  • 运行git add requirement.txt
  • 运行git commit -m "update requirements.txt"

预提交挂钩的目的是确保在对 Git repo 进行更改之前,某些事情会发生或不会发生。在我们的例子中,这个预提交钩子确保我们的requirements.txt文件存在,并且与我们当前的诗歌虚拟环境保持一致。所有这些都是在我们将任何代码推送到 git 并最终投入生产之前完成的。

结论

我们的定制钩子create-requirements,确保我们在本地使用的环境与我们在远程创建的环境一致。这可以通过 bash 代码、退出状态和pre-commit来实现。非零的退出状态会导致 bash 脚本发出一个错误。因此,这些错误可以用来阻止不符合我们标准的提交。

如何收集 Reddit 数据集

原文:https://towardsdatascience.com/how-to-collect-a-reddit-dataset-c369de539114?source=collection_archive---------4-----------------------

在 Python 中使用 PSAW 和 PRAW

Reddit 是一个社交媒体平台,由子论坛或子编辑组成,每个子论坛专注于一个给定的主题。一些公共子数据可能是有趣数据的深井,随时可供探索!然而,即使想到如何收集这些数据,尤其是大量的数据,也是令人望而生畏的。

在这篇文章中,我们将使用 Python 开发一个工具,从任何(公共)子编辑中收集公共可用的 Reddit 帖子,包括他们的评论帖子,按发布年份组织。

我们将详细介绍必要的设置记录功能,完整的主算法和逐块的**,最后是收集数据的示例收集和探索的想法。**

设置

我们的工具将基于 PSAWPRAW 。PSAW 的用法相当简单。然而,为了使用 PRAW (Reddit 的 API),您需要设置您的授权令牌,以便 Reddit 知道您的应用程序。您可以按照这个指南快速获得您的令牌,并替换下面代码中的相关信息,具体来说,就是您的客户端 ID 和密码,以及您的 reddit 用户名和密码。

import praw
from psaw import PushshiftAPI# to use PSAW
api = PushshiftAPI()# to use PRAW
reddit = praw.Reddit(
    client_id = "YOUR_CLIENT_ID_HERE",
    client_secret = "YOUR_CLIENT_SECRET_HERE",
    username = "YOUR_USERNAME_HERE",
    password = "YOUR_PASSWORD_HERE",
    user_agent = "my agent"
)

我们还必须定义子编辑列表(可以只有一个!)和年份范围,即从哪一年开始和哪一年结束将检索帖子。在这种情况下,我们将从 2020 年初到 2021 年底(到今天为止)发布的r/shortscarystorys subreddit中提取帖子。最后,我们必须设置存储数据的目录。

subreddits = ['shortscarystories']
start_year = 2020
end_year = 2021# directory on which to store the data
basecorpus = './my-dataset/'

日志记录功能

日志功能让您深入了解正在运行的进程。当这个过程很长,你想知道它是如何进行的时候,这些尤其重要。在我们的例子中,我们将简单地编写一个函数,将算法刚刚采取的动作,以及采取该动作需要多长时间打印到屏幕上。如果我们最终提取了很多很多的数据,并希望确保程序不只是停留在某个地方,这将是非常有见地的。这个函数可以很容易地修改为记录到一个文件,而不是打印到屏幕上:这就是为什么我把它封装到一个函数中,而不是把打印直接内置到算法中。

import timedef log_action(action):
    print(action)
    return

主算法

主要思想非常简单:在<start_year>和<end_year>之间的每一年,创建一个目录,并且为中的每个子编辑创建一个目录来存储该子编辑在这一年中的帖子。</end_year></start_year>

这是完整的代码,然后我们将一次一个块地检查它。

详述算法

**###第 1 块# ## **

简单地说,对于从<start_year>到<end_year>之间的每一年,创建一个目录并定义开始和结束时间戳(从当年开始直到下一年开始)。这些时间戳作为输入提供给 PSAW 请求,指定从中检索数据的时间窗口。</end_year></start_year>

###第二块# ## #第十四块】

对于中的每一个子编辑,开始为日志记录计算提取时间,在当年的目录中创建相应的目录,并定义 CSV 文件的路径,在该文件中存储相应的要提取的帖子。

###第 3 块# ## #第 19 块】

定义存储每个帖子的 Python 字典(存储在内存中,稍后写入之前定义的 CSV 文件路径)。我们对存储帖子的 ID、URL、标题、分数、评论数、创建时间戳和帖子的实际正文(selftext)感兴趣。可以提取其他指标——使用本指南找出您确切需要的指标。

**###块 4 # ## # **

PSAW 允许我们创建一个迭代器来遍历一组特定的文章(也称为提交)。我们用之前设置的参数来指定这个集合:开始和结束时间戳、特定的子编辑以及要检索的帖子数量。在这个例子中,我将其限制在 100 篇帖子,但是 Python 关键字 None 可以用于在指定的时间框架内浏览所有帖子。此外,PSAW 没有给我们每篇文章想要的所有信息,所以我们只使用它来检索文章的 ID ,然后在 PRAW 使用该 ID 来获取剩余的信息

**# # # 5 # # ## **

对于我们在前面的块中定义的迭代器中的每个 post(或 submission ),获取它的 ID 并使用它从 PRAW 获取完整的 post 数据,并将它附加到我们在块 3 中定义的 Python 字典中。

###块 6 ###

每个帖子都有一个相关的评论线程,我们也希望收集这些评论线程,以便将来进行可能的分析。我们希望将这篇文章的整个评论存储在一个单独的 CSV 文件中,我们现在为该文件定义适当的文件路径。我们还定义了 Python 字典来存储这篇文章的评论线程,特别是每个评论的 ID、父 ID、链接 ID,最重要的是它的正文。

###块 7 # ## #块 19】

现在,对于当前帖子的扁平化评论线程中的每个评论(它最初是一个树结构,我们显式地将其扁平化,但总是可以基于评论父 ID 检索原始树结构),我们检索适当的数据并存储在我们在前面的块中定义的 Python 字典中。一旦我们检查了当前帖子的所有评论并存储在字典中,我们就可以将它保存到 CSV 文件中(该路径是我们在前面的块中定义的)。我们使用 Pandas 轻松地转换成正确的格式并写入文件。

# # # 8 # # ## # 23】

最后,一旦我们遍历了迭代器中的所有 post(即,在块 4 中定义的指定时间范围内)并存储在字典中,我们可以将它保存到 CSV 文件中(我们在块 2 中定义了该路径)。同样,我们使用 Pandas 轻松地转换成正确的格式并写入文件。

记录输出

这是上面代码中示例的日志记录输出:

[Year] 2020
	[Subreddit] shortscarystories
		[Info] Found submissions: 100
		[Info] Elapsed time:  26.14s
[Year] 2021
	[Subreddit] shortscarystories
		[Info] Found submissions: 100
		[Info] Elapsed time:  27.96s

收集的数据示例

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

前 3 篇收集自 2020 年 r/shortscarystories 的帖子(2020-shortscarystories-submissions . CSV)。图片作者。

需要注意的一个重要方面是,Reddit 的原始数据并不完美。有些帖子的内容可能已经被删除,但帖子仍然存在,在“随意杀人”条目中可以看到,帖子的正文是“[已删除]”。不是盲目地收集所有数据,而是可以改变块 5 以忽略文本主体为“[已删除]”、“[已移除]”或空的所有帖子。这也可以在稍后的数据预处理阶段执行。

收集和探索的想法

最后,我在这里留下我写这篇文章时的一些想法,这些想法可以产生有趣的挑战和结果。

  1. 利用最近来自 https://www.reddit.com/r/recipes/的帖子,人们可以收集一个食谱图片、配料和说明的数据集。有了这些数据,人们可以开发出这样的系统:基于成分列表的配方建议器、基于成分列表的配方创建器、基于配方图像的配方指令合成器等等。
  2. 利用来自https://www.reddit.com/r/shortscarystories/帖子的数据,开发如下系统:给定标题作为提示的恐怖短篇故事生成器,基于故事标题和文本的评分/评论预测,用于观众统计预测,等等。
  3. 使用来自https://www.reddit.com/r/AskReddit/帖子的数据(帖子是一个问题,评论是可能的答案),开发一个 oracle 系统,它对每一个可以想象到的问题都有一个答案。

如何使用 Python 从加拿大统计局收集数据

原文:https://towardsdatascience.com/how-to-collect-data-from-statistics-canada-using-python-db8a81ce6475?source=collection_archive---------16-----------------------

实践教程

加拿大统计局 API 和 python 库的分步教程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Alex ShutinUnsplash 上拍摄的照片

加拿大统计局提供广泛的数据供公众使用,包括加拿大经济、社会和环境的数据。除了手动浏览网页访问数据,加拿大统计局还提供 Web 数据服务,即 API 访问他们的数据库。更好的是,有一个 python 库 stats_can 包装了 API 命令,允许用户编写简单的代码来自动读取数据。本文将提供如何实现这一点的一步一步的教程。

识别所需数据项及其vectorID

进入加拿大统计局子页面数据,输入关键词,例如 GDP,点击搜索图标。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在返回的结果中找到所需的项目。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

GDP 页面上,点击Add/Remove data

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

点击标签页Customize layout

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

向下滚动并勾选选项Display Vector identifier and coordinate,然后点击按钮Apply

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,该表将被重组,您会发现一个新列Vector,这里我们将选择所有行业的 GDP,因此目标vectorIDv65201210。这将在稍后的 Python 代码中使用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在 Python 中安装 stats_can

该库可以与 conda 或 pip 一起安装:

conda install -c conda-forge stats_can

或者:

pip install stats-can

收集数据

我们将使用函数[stats_can.sc.vector_to_df](https://stats-can.readthedocs.io/en/latest/stats_can.html#stats_can.sc.vectors_to_df)从加拿大统计局读取数据。该函数的语法如下:

df = stats_can.sc.vectors_to_df(vectors, periods = n, start_release_date = None, end_release_date = None)

它返回具有 n 个周期数据或发布日期范围的向量的数据框架。该函数包装了两个 API 命令,分别是get_bulk_vector_data_by_rangeget_data_from_vectors_and_latest_n_periods ,用于将 JSONs 的结果列表转换为数据帧。

例如,对于 GDP 的矢量数据v65201210,您可以运行以下代码来收集过去 6 个月的 GDP:

import stats_candf = stats_can.sc.vectors_to_df('v65201210', periods = 6)

您可以重命名索引和列,使表格看起来更漂亮:

df.columns = ['GDP']
df.index.names = ['Date']

返回的表如下所示:

Date        GDP        
2020-05-01  1726385.0
2020-06-01  1833032.0
2020-07-01  1879281.0
2020-08-01  1896592.0
2020-09-01  1912085.0
2020-10-01  1920056.0

收集和可视化多个经济指数的示例

在最近的项目中,我收集了多个生态指数,如 GDP、CPI、失业率等。建立多变量回归模型,用于预测金融交易数量。

首先,我计算出我计划使用的所有 eco 指数的向量,包括 GDP、CPI、TSX、失业率和汇率(美元兑加元),并将它们放入字典中:

eco_vec_map = {'CPI':'v41690973',
               'Exchange_Rate_USD':'v111666275',
               'GDP':'v65201210',
               'Unemployment_Rate':'v91506256',
               'TSX':'v122620'}

其次,我将字典中的值转换为一个列表并运行函数,输入 periods = 36(即最近 3 年),函数自动识别向量列表并返回多列表:

vectors = list(eco_vec_map.values())
df = stats_can.sc.vectors_to_df(vectors, periods = 36)

然后,我用它们的 eco 索引名重命名了这些列,注意这里使用了一个映射技巧,这样您就不必担心列的顺序了:

inv_map = {v: k for k, v in eco_vec_map.items()}
df.columns = df.columns.to_series().map(inv_map)
df.index.names = ['Date']

返回的表如下所示:

Date        TSX       CPI    GDP       Unemployment_Rate  Exchange_Rate_USD
2017-09-01  NaN       NaN    1905358.0 NaN                NaN
2017-10-01  16025.59  130.9  1907384.0 NaN                NaN
2017-11-01  16067.48  131.3  1917258.0 5.4                1.2769
2017-12-01  16209.13  130.8  1922552.0 5.3                1.2771
...
2020-08-01  16514.44  137.0  1904249.0 11.0               1.3222
2020-09-01  16121.38  136.9  NaN       8.4                1.3228
2020-10-01  NaN       NaN    NaN       8.1                1.3215

最后,我可视化了表中的所有列:

df.plot(subplots = True, figsize = (14,8), layout = (3,2));

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结果显示,除 CPI 外,其他生态指数在 2020 年 3-4 月间经历了大幅下降或上升,这很可能是受疫情的影响。

摘要

本文详细介绍了如何使用加拿大统计局的 Python 库收集数据。主要步骤是:

  • 识别目标数据项的vectorIDs
  • 安装stats_can库,调用函数stats_can.sc.vectors_to_df采集数据并保存为 DataFrame 表。

我很难在网上找到好的教程,所以我写了这篇文章,希望能帮助别人。如有任何问题或建议,请随时通过 Linkedin 联系我。我很乐意连接:)

参考资料:

[1]网络数据服务用户指南,加拿大统计局。https://www . stat can . GC . ca/eng/developers/WDS/user-guide # a12-3

[2]用于读取加拿大统计局数据的 python 库。
https://stats-can.readthedocs.io/en/latest/index.html#

如何使用 Python & Tesseract 从图像中收集文本信息

原文:https://towardsdatascience.com/how-to-collect-text-information-from-images-with-python-tesseract-7073785b1d77?source=collection_archive---------5-----------------------

一个从公寓平面图中自动收集房间尺寸的脚本…或者至少它尝试了

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

如果你有分析思维,并且曾经进行过虚拟找房之旅,你可能会遇到我个人一直觉得令人恼火的问题:你几乎永远无法通过房产大小进行搜索,更不用说通过单个房间的大小了。然而,这种信息经常以平面布置图的形式出现。只是大量的缩放和手动输入来收集数据…

嗯,我认为这将是一个练习图像识别技能和创建一个脚本的绝佳机会,该脚本可以将图像转换成一个漂亮而干净的数据表。毕竟,随着每个过于雄心勃勃的项目开始:

能有多难?

事实证明,相当困难。我其实并不确定这是一个可以 100%准确解决的问题。我认为我充分探索了各种可能性,并取得了良好的进展,但请注意这个项目不会完全成功。即使经过重大的调整和微调,一个特别棘手或质量差的图像可能会使算法出错。

然而,我认为对于像我一样抱着天真的期望开始类似项目的人来说,这是一个宝贵的教训。

摘要

最后,我们希望将平面图转换成显示房间和房间大小的表格。我们正在使用米,但调整代码应该很简单,这样它也可以识别英尺的度量。

我们将使用的 pytesseract ,它是谷歌的 Tesseract OCR 的 Python 包装器。

该项目的代码在我的 GitHub 上。

  • 如果你只是想自己尝试一下,你将需要floor plan _ reader脚本。您将需要安装软件包和 Tesseract,另外您可能需要调整它在脚本中的位置。 Jupyter 笔记本显示了如何使用代码。祝你好运!
  • 如果您想继续学习,请继续下一节,在这里我们将设置环境。

环境

宇宙魔方

首先,我们需要宇宙魔方包本身,即使我们不直接使用它。安装过程并不简单,你也可以在官方的 GitHub 页面找到更多信息,但是我发现这个摘要更有用。

在 Mac 上,安装自制软件非常简单:

brew install tesseract

您还需要 Tesseract 的位置,我跟踪了这个堆栈溢出线程,我的安装位置是:

/usr/local/bin/tesseract

(当然,不同系统的位置不同。)

Python 包

我们需要两个“非标准”包:枕头宇宙魔方:

pip install Pillowpip install pytesseract

Pillow 是一个处理图像的包,是一个名为 PIL 的旧包的分支,我们将使用它的图像对象:

from PIL import Image

(是的,这个库在项目内部仍然被称为 PIL,这并不意味着我们使用了过时的 PIL 包。)

对于宇宙魔方,我们需要连接到它的位置:

import pytesseract
pytesseract.pytesseract.tesseract_cmd = r'/usr/local/bin/tesseract'

从错误中学习

我将向你介绍我在开始使用 pytesseract 时犯的四个业余错误。如果你更喜欢"这是目的地,而不是旅程。“种人,跳过这一点,我们在下一节开始看实际代码。

文件路径与图像

如果您从 pytesseract 开始,您尝试的第一件事可能是image_to_string函数。顾名思义,它确实如此。

您可以将图像或文件路径作为参数传递。然而,根据我的经验,首先处理图像总是更好。用枕头,用它打开图片,传递图像对象。考虑这个平面布置图示例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们直接用 pytesseract 打开:

pytesseract.image_to_string(‘plans/floorplan_02.png’)

这是我们得到的结果:

'KITCHENIDINER — MASTER BEDROOM\ngo" xis" Tatra hou" xara\nPi\n\n3.14m x 2.95m\n\nSITTING ROOM\n12\'1" x 15\'7"\n3.69m x 4.74m\n\nBEDROOM 2\n8\'1" x 12\'0"\n2.47m x 3.66m\nBEDROOM 3\n71" x 85"\n2.17m x 2.56m\n\n \n\x0c'

而如果我们先用枕头打开:

pytesseract.image_to_string(Image.open('plans/floorplan_02.png'))

这是我们得到的结果:

'KITCHEN/DINER\n15°7" x 11\'8"\n4.74m x 3.55m\n\nSITTING ROOM\n12\'1" x 15\'7"\n3.69m x 4.74m\n\n \n\n \n\n \n\n \n\n \n\n \n\nMASTER BEDROOM\n10\'4" x 9\'8"\n3.14m x 2.95m\n\nBEDROOM 2\n8\'1" x 12\'0"\n2.47m x 3.66m\n\nBEDROOM 3\n71" x 85"\n2.17m x 2.56m\n\n \n\x0c'

是的,你的眼睛没有欺骗你,那是一个完整的额外线!那以后会派上用场的。

第一课 。:在将任何东西传递给 pytesseract 之前,始终使用 Pillow 之类的图像处理包。将图像对象作为参数传递,而不是文件路径。

调整大小很重要

下一个令人惊讶的是关于调整大小。考虑下面的图像(模糊,是的,这将是重点。):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果您只是将它作为一个枕头图像读入,并将其传递给 image_to_string,您会得到以下结果:

' \n    \n   \n\nUTILITY ROOM\n\n  \n  \n  \n\n  \n \n\n  \n\n       \n   \n    \n\n  
...

但是,如果您首先调整图像的大小,比如说将其宽度和高度调整为原来的 5 倍:

image = image.resize((image.size[0] * 5, image.size[1] * 5))

结果是:

'UTILITY ROOM\nR\' i\nSe 2.51m x 2.44m\n3.88m x ?2.57m\nSITTING ROOM
...

我没有复制整个结果,重点是,如果没有重新缩放,杂物间下的较小文本不会被读入。

你可以在这里了解更多关于枕头的图像处理。我个人没有调整图像亮度或对比度的运气。只有重新调整似乎工作得很好。我不知道为什么会这样。

第二课 。:利用 Pillow 的图像处理功能。如果您调整图像的大小,调整亮度或对比度,Tesseract 会以不同的方式读入您的图像。然而,变化并不总是积极的!例如,您可能会注意到,缩放超过某个阈值会降低精度。

裁剪也很重要…

…当我们这样做的时候,你对图像所做的任何其他事情都很重要!

我实际上对你耍了点小花招,如果你真的读了上面的图片,杂物间的第一面2.51,将被读为2.91。原因?我从原始图片中截取了主要信息。没有缩放,或以任何方式调整,只是排除了一些空白区域。没有裁剪,数字可以正确读取。

正是在这个时候,我第一次开始考虑接受失败…

第三课 。:实际上任何事情都可以改变结果。您永远无法确定字符是否被正确地读入,即使它们是用漂亮、一致的字体书写的,并且在您的人眼看来似乎没问题。宇宙魔方的算法并不适用于所有情况。

一张整洁有序的表格胜过一大堆杂乱的文字

在很长一段时间里,我试图用image_to_string方法来强迫项目工作。如果你看一下上面的一些例子,你可能会发现我没有发现的问题。

问题是image_to_string将逐行从左到右、从上到下扫描文档。(它如何确定 \n 的位置,谁也说不准。)我非常确定我可以让下面的逻辑工作:

loop over the string
search for matches of pre-defined room names from a set
if there is a match: 
    put the room name in a dictionary
    delete the corresponding room from the set and the string
    look for the next bit that looks like the two sides
    when found, save the sides in the dictionary
    delete the sides from the stringrepeat the process with the shortened room name set and main string, until there is no new room found

这个想法是,房间可以彼此靠近,但第一个房间名称后从左到右和从上到下的第一个数字必须是与所讨论的房间相对应的数字…是的,我知道,但我要说的是,这招出奇的有效。

然后我终于遇到了我的克星:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我不知道为什么我以前没有想到这种可能性,但是把米放在两条不同的线上完全打乱了我以前的方法。更不用说我还没有遇到过的任何其他平面图结构。

我认为仅仅通过阅读image_to_string产生的连续文本是无法确定哪个尺寸属于哪个房间的。然而,通过使用image_to_data方法(加上一些额外的调整,我们将在下一节中看到),我们得到了一个漂亮且有组织的表:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第四课 。:除非你有一个微不足道的问题,否则你会想用 *image_to_data* 而不是 *image_to_string* 。只要确保将 *output_type* 参数设置为“ data.frame ”就可以得到熊猫数据帧,而不是更乱更大的文本块。

浏览代码

在这一部分,我将带大家浏览代码。请注意,我不会完全照搬脚本,我们只讨论要点。

打开图像

首先,我们需要一个方法来打开图像本身,这是我最终使用的方法:

def **process_image**(filepath, resize_factor = 1):   image = Image.open(filepath)
  image = image.resize(
    (image.size[0] * resize_factor, image.size[1] * resize_factor))   return image

我花了很多时间试图找出一个最佳的resize_factor。有人会认为这与图片的像素大小有关,但显然,事实并非如此。我最终把责任抽离出来,变成了一场争论。我猜你可以对不同的resize_factors重复这个过程,看看你是否得到相同的结果。

用宇宙魔方读入图像

这在技术上是整个代码的图像识别部分。如前所述,我们希望使用image_to_data。这就是如何将它转换成一个美观易读的表格:

def **convert_floorplan_pic_to_df**(filepath, resize_factor = 1): image = process_image(filepath, resize_factor) df = pytesseract.image_to_data(image, output_type='data.frame')
  df = df[df['conf'] != -1] 
  df['text'] = df['text'].apply(lambda x: x.strip())
  df = df[df['text']!=""]
  df['text'] = df['text'].apply(lambda x: x.upper()) return df

向上滚动一点,看看这个数据帧应该是什么样子。

我们将使用其中大约一半的列。列conf显示了模型在其解决方案中的确定性,-1 是这些奇怪的额外行,不知道它们为什么在那里,但我们肯定不需要它们。还有很多读入的空白,我们也不需要。

识别文本部分

我们已经有了一个图像上带有文本的数据框架,但是我们还远远没有完成,在它可用之前还有大量的处理工作。

我们利用另外两个函数,将图像转换成包含文本信息的数据帧:

def **process_floorplan**(
    filepath, rooms_set = default_rooms_set, resize_factor = 1): df = convert_floorplan_pic_to_df(filepath, resize_factor)

我们想一行一行地检查这个数据帧,并决定这个字符串是房间名称、大小还是其他什么。

房间将从一组房间名称字符串中识别出来,默认情况下看起来像这样:

default_rooms_set = {"DINING ROOM", "KITCHEN", "LIVING ROOM",
   ...
}

另一方面,使用正则表达式来识别大小。我们基本上要考虑每个浮点数,这很容易做到:

room_side_regex = r'[0-9]+[.][0-9]+'

如果我们看一下df对象,我们会立即发现一个问题:一些房间名可能会被分成多行。(从今以后,我们假设我们从不希望搜索由两个以上部分组成的房间名。)

我解决这个问题的方法是创建另一个名为text_2row的文本列,它是两行文本的串联。

shifted_text_col = list(df['text'].iloc[1:])
shifted_text_col.append("")
df['text_2row'] = df['text'] + " " + shifted_text_col

现在我们可以循环了。这里不打算复制代码,再次请参考我的 GitHub 。逻辑如下:

for each row in the DataFrame: 
  if the text_2rows matches one of the rooms
    the current row gets a room id
    go to next in loop, skip an extra line
  if not match so far
    if text column matches one of the rooms
      current row gets a room id
      go to next in loop
  if no match so far
    if text column matches the size regex
      current row gets a room_side id
      go to next in loop
  if still no match
    current row gets no id
    go to next in loop

在大小匹配中有一个假设:如果行中有多个浮点数,我们总是取第一个浮点数。所以如果这个列表的长度大于 0:

regex_list = re.findall(room_side_regex,df[‘text’].iloc[i])

我们取第一个元素:

df['side_number'].iloc[i] = float(regex_list[0])

经过一些清理后,我将数据帧分成两个较小的数据帧。两者都包含被确定为roomroom_side的行的lefttopvalue列。这是我们的房间:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们有一个类似的边表,数字在value列。

搭配带侧边的房间

我们已经从文本中获得了所有需要的信息,我们现在只需要匹配它们。

有许多不同的方法可以解决这个问题。注意,当我们用image_to_data创建原始 DataFrame 时,pytesseract 会放入一些有用的信息。例如,我们有一个block列,它将文本排列成簇。

我最终使用了lefttop列,它们应该是包含文本的框的位置,从图像的左上角开始计算。我们将计算这些左上角的欧几里德距离,并为每个房间选择两个最接近的数字。这种方法有一些缺点,我们将很快回到它。

我们将使用scipy中的distance_matrix方法:

from scipy.spatial import distance_matrixdist = distance_matrix(
  df_rooms[['left', 'top']], 
  df_sides[['left', 'top']])

然后这只是一个为每个房间选择两个最近点的练习。我们依赖于numpyargpartition方法,同样,代码在我的 GitHub 中。

最终确定

经过一些格式化之后,我们终于得到了我们的最终产品:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

成功了吗?

我想,算是吧。如果你看一下上面的表格,我认为只有一个小小的错误。加上学习没有找到…

当然,这只是一个例子。最大的挑战是读取以前看不到的格式的平面图。我相信,如果你关注某个机构的平面图,并对图像处理进行微调,它可以在更大范围内变得可靠。

我确实学到了很多关于图像文本处理的知识。大部分是关于它的局限性,但是嘿,那仍然算数!我希望你通过阅读这篇文章也学到了一些新的东西。

可能的改进

我有一些想法可以让这个过程变得更好:

  • 专注于某些房间类型,不要像我一样试图处理所有房间。问题是很难确定一个房间在平面图上是否有尺寸。我想象一个杂物间会在没有精确尺寸的情况下被展示。
  • 我放弃了调整贴图的对比度和亮度的想法,结果似乎不可靠,但也许值得花时间来研究这如何改变 pytesseract 的结果。
  • 房间到侧面的匹配有点简单。这里可以有额外的检查,例如,我们可以检查某些元素是否大致在彼此之下,这将表明更密切的关系。

https://matepocs.medium.com/membership

如何给熊猫数据框上色

原文:https://towardsdatascience.com/how-to-color-a-pandas-dataframe-41ee45db04f6?source=collection_archive---------12-----------------------

一个关于如何在熊猫数据帧上设置颜色的简短教程。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

罗伯特·卡茨基在 Unsplash 上的照片

andas 无需介绍,因为它已经成为 Python 中事实上的数据分析工具。作为一名数据科学家,我每天都使用熊猫,它总能以更好的方式实现我的目标,让我感到惊讶。

我最近学到的另一个有用的特性是如何给熊猫的数据帧上色。

这里有几个你可能会感兴趣的链接:

- [Complete your Python analyses 10x faster with Mito](https://trymito.io/) [Product]- [Free skill tests for Data Scientists & ML Engineers](https://aigents.co/skills) [Test]- [All New Self-Driving Car Engineer Nanodegree](https://imp.i115008.net/c/2402645/1116216/11298)[Course]

你愿意阅读更多这样的文章吗?如果是这样,你可以点击上面的任何链接来支持我。其中一些是附属链接,但你不需要购买任何东西。

让我们添加颜色

让我们用随机数创建一个熊猫数据帧:

import numpy as np
import pandas as pddf = pd.DataFrame(np.random.randint(0, 100, size=(15, 4)), columns=list("ABCD"))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

带有随机数的熊猫数据框(图片由作者制作)

给单元格着色(按频率)非常简单:

df.style.background_gradient(cmap="Blues")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

带有随机数的彩色熊猫数据框(图片由作者制作)

颜色是基于列的

如果我们把 B 列增加 1000,就不会干扰其他列的颜色。

df["B"] *= 1000

如下图所示,A、C、D 列的最大值保留了它们的颜色。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

带有随机数的彩色熊猫数据框(图片由作者制作)

更改颜色映射

您可以设置 matplotlib 中支持的任何色彩映射表。如果您的目标是可视化频率,请小心选择顺序色图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来自 matplotlib 的连续颜色图(图片由作者制作)

非顺序色彩映射表是可视化频率的一个不好的例子(所以请确保使用顺序色彩映射表):

df.style.background_gradient(cmap="Spectral")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可视化频率的一个不好的例子是用一个无序的颜色图(作者制作的图像)

在你走之前

Twitter 上关注我,在那里我定期发布关于数据科学和机器学习的消息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由Courtney hedgeUnsplash 拍摄

如何在 R 中组合动画剧情

原文:https://towardsdatascience.com/how-to-combine-animated-plots-in-r-734c6c952315?source=collection_archive---------22-----------------------

利用 gganimate 和 magick 的强大功能为您的观众组合动画情节

在本教程中,我将概述在 r 中创建动画多面图的必要步骤。虽然很少,但组合动画图可以是展示相同数据的不同元素的强大方法(如下所示)。

在这个例子中,我使用了来自国际举重联合会的举重数据。出于本教程的目的,我们将看看不同性别托举的差异。一个多面的动画情节是一个很好的选择,因为我们想观察这些差异的大小以及这些差异是如何随着时间的推移而演变的。

我们将创建这个 GIF:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

环境设置

这些是我们开始工作所需的包。在我的例子中,我使用了一个为风格目的而开发的自定义主题。请随意运行theme_set(theme_minimal())而不是使用我的主题!

加载和清理数据

我已经帮你清理了很多数据。如果你想跟着做,这是过程(或者,直接跳过!).

在这里,我们将做一些小清洁,然后将三个电梯改造成一列:

就我的想象而言,我只关心每年最重的举升次数:

我们将为最终输出创建的第一个可视化图形是一个哑铃图。好奇那是什么,或者如何在 R 中制作?看看我关于这个话题的另一篇文章

为了构造一个哑铃图,我们需要在同一行中同时进行雄性和雌性观察。为此,我们使用了spread函数。

现在,让我们为每种性别构建一个数据框架:

加入他们:

不跟随,或者想检查你的进展?以下是我们的数据最终的样子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

视觉化!

最后,我们可以构建可视化。

首先,我们可以使用ggalt创建一个静态可视化(同样,我的博客文章涵盖了这个步骤的细节)。

如果你只对两者的组合感兴趣,你可以快进到单个情节的创作。你会在这篇文章的结尾发现这一点!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,我们使用 Thomas Pedersen 精彩的 gganimate 软件包制作动画。这是一个相对容易的步骤,因为gganimate只需要两行额外的代码:transition_statesease_aes。然后,我们把它传入animate函数!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是在我们的例子中,我们希望包含另一个 GIF:一个随时间变化的差异折线图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,我们将使用magick来组合它们(感谢这篇文章)。在这里你可以找到进行组合所必需的代码(不管你的动画情节是什么样的,这应该是可行的!).

这里发生了什么事?本质上,我们利用magick的力量来:

  1. **(第 2-3 行)**从每个 GIF 中读入所有的单个图像 ( image_read)(毕竟,GIF 只是一系列图像!).
  2. **(第 5 行)**对于第一帧,将两幅图像堆叠在彼此之上(image_append),因此图 1 在图 2 之上。
  3. **(第 6–9 行)**对于其余的帧(在我的例子中,是下一个 249 帧,因为我的 GIF 有 250 帧),复制这个并将其与第一帧合并(这是for循环)。

这里,我们指定stack = TRUE以便一个图在另一个图的之上**。如果您想将它们并排放置,请指定stack = FALSE。**

总的来说,该流程会产生我们的最终结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在此视图中,我们可以看到相对和绝对差异的大小(上图),我们可以看到这些差异如何随时间变化(下图)。动画组合图表的力量!

感谢阅读。有问题吗?给 me@connorrothschild.com 发电子邮件或者在推特上给我发信息。

如何在 Pandas 中组合数据——你应该知道的 5 个功能

原文:https://towardsdatascience.com/how-to-combine-data-in-pandas-5-functions-you-should-know-651ac71a94d6?source=collection_archive---------8-----------------------

了解它们的不同之处,并正确使用它们

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Hendrik Cornelissen 在 Unsplash 上拍摄的照片

当我们使用 Pandas 处理数据时,一个常见的任务是组合来自不同来源的数据。在本文中,我将回顾您可以用于数据合并的 5 个 Pandas 函数,如下所列。如果你想看的话,每个函数都有到官方文档的链接。

* [concat](https://pandas.pydata.org/docs/reference/api/pandas.concat.html)
* [join](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.join.html#pandas.DataFrame.join)
* [merge](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.merge.html#pandas.DataFrame.merge)
* [combine](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.combine.html)
* [append](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.append.html#pandas.DataFrame.append)

对于当前教程,让我们使用两个简单的DataFrame对象,如下所示。请注意,为了更好地说明相应的功能,我将在适当的地方做一些小小的修改。

用于说明的数据帧

1.串联

concat函数以串联命名,它允许您水平或垂直地并排组合数据。

当您组合具有相同列的数据时(或者实际上它们中的大多数是相同的),您可以通过将axis指定为 0 来调用concat,这实际上也是默认值。

>>> pd.concat([df0, df1.rename(columns={"c": "a", "d": "b"})], axis=0)
   a  b
0  1  4
1  2  5
2  3  6
0  2  5
1  3  6
2  4  7

当您将数据与指示相同实体的行(即,相同有序主题的研究数据)和不同数据的列组合时,您可以将它们并排连接。

>>> pd.concat([df0, df1], axis=1)
   a  b  c  d
0  1  4  2  5
1  2  5  3  6
2  3  6  4  7

默认情况下,当您水平组合数据时(即沿着列),Pandas 会尝试使用索引。当它们不相同时,您会看到 nan 来填充不重叠的部分,如下所示。

>>> df2 = df1.copy()
>>> df2.index = [1, 2, 3]
>>> pd.concat([df0, df2], axis=1)
     a    b    c    d
0  1.0  4.0  NaN  NaN
1  2.0  5.0  2.0  5.0
2  3.0  6.0  3.0  6.0
3  NaN  NaN  4.0  7.0

如果这不是期望的行为,并且您希望通过忽略索引来使它们完全对齐,则应该在连接之前重置索引:

>>> pd.concat([df0.reset_index(drop=True), df2.reset_index(drop=True)], axis=1)
   a  b  c  d
0  1  4  2  5
1  2  5  3  6
2  3  6  4  7

请注意,df0的重置索引是可选的,因为它的索引恰好是从 0 开始的,这将与df2的重置索引相匹配。

2.加入

concat相比,join专门使用索引连接DataFrame对象之间的列。

>>> df0.join(df1)
   a  b  c  d
0  1  4  2  5
1  2  5  3  6
2  3  6  4  7

当索引不同时,默认情况下,连接保持左边的行DataFrame。从右边DataFrame开始,左边DataFrame中没有匹配索引的行被删除,如下所示:

>>> df0.join(df2)
   a  b    c    d
0  1  4  NaN  NaN
1  2  5  2.0  5.0
2  3  6  3.0  6.0

但是,可以通过设置 how 参数来更改此行为。可用选项有:左、右、外和内,它们的行为如下所示。

**# "right" uses df2’s index**
>>> df0.join(df2, how="right")
     a    b  c  d
1  2.0  5.0  2  5
2  3.0  6.0  3  6
3  NaN  NaN  4  7**# "outer" uses the union**
>>> df0.join(df2, how="outer")
     a    b    c    d
0  1.0  4.0  NaN  NaN
1  2.0  5.0  2.0  5.0
2  3.0  6.0  3.0  6.0
3  NaN  NaN  4.0  7.0**# "inner" uses the intersection**
>>> df0.join(df2, how="inner")
   a  b  c  d
1  2  5  2  5
2  3  6  3  6

3.合并

如果你有这样的经验,那么merge函数很像是在数据库中加入动作。相比 join,merge 更通用,可以对列和索引执行合并操作。因为我们已经介绍了使用基于索引的合并的join,所以我们将更加关注基于列的合并。让我们看一个简单的例子。

>>> df0.merge(df1.rename(columns={"c": "a"}), on="a", how="inner")
   a  b  d
0  2  5  5
1  3  6  6

on参数定义了两个DataFrame对象将在哪些列上合并。请注意,您可以将单个列指定为字符串,也可以在一个列表中指定多个列。这些列必须出现在两个DataFrame对象中。更一般地,您可以分别从左边的DataFrame和右边的DataFrame指定合并列,如下所示。

>>> df0.merge(df1, left_on="a", right_on="c")
   a  b  c  d
0  2  5  2  5
1  3  6  3  6

除了单独的列ac之外,这与之前的合并结果基本相同。

有许多其他的可选参数可以用来进行合并。我想在这里强调两点。

  • how:定义要执行的合并类型。支持的类型包括左、右、内(默认)、外和交叉。一切都应该很简单,除了最后一个十字,它从两个帧创建笛卡尔乘积,如下所示。
>>> df0.merge(df1, how="cross")
   a  b  c  d
0  1  4  2  5
1  1  4  3  6
2  1  4  4  7
3  2  5  2  5
4  2  5  3  6
5  2  5  4  7
6  3  6  2  5
7  3  6  3  6
8  3  6  4  7
  • 后缀:当两个 DataFrame 对象具有除了要合并之外的相同列时,此参数设置应该如何使用后缀将这些列重命名为。默认情况下,左右数据框的后缀为“_x”“_y”,您可以自定义后缀。这里有一个例子。
>>> df0.merge(df1.rename(columns={"c": "a", "d": "b"}), on="a", how="outer", suffixes=("_l", "_r"))
   a  b_l  b_r
0  1  4.0  NaN
1  2  5.0  5.0
2  3  6.0  6.0
3  4  NaN  7.0

4.结合

combine函数执行两个DataFrame对象之间的列式合并,与之前的函数有很大不同。combine的特别之处在于它带了一个函数参数。该函数采用两个Series,每个对应于每个数据帧中的合并列,并返回一个Series,作为相同列的元素操作的最终值。听起来很困惑?让我们看看下面代码片段中的一个例子。

组合数据

taking_larger_square功能作用于df0df1 中的a列和df0df1中的b列。在两个a和两个b列之间,taking_larger_square从较大的列中取值的平方。在这种情况下,df1的列ab将被视为正方形,这将产生如上面的代码片段所示的最终值。重命名后的df1如下图所示,供您参考。

>>> df1.rename(columns={"c": "a", "d": "b"})
   a  b
0  2  5
1  3  6
2  4  7

虽然这里没有涉及,但是还有另一个密切相关的函数combine_first,它只是使用第一个帧的非空值来合并两个帧。

5.附加

到目前为止,我们讨论的大多数操作都是针对按列组合数据的。行方式操作怎么样?append 函数专门用于将行追加到现有的DataFrame对象,创建一个新的对象。我们先来看一个例子。

>>> df0.append(df1.rename(columns={"c": "a", "d": "b"}))
   a  b
0  1  4
1  2  5
2  3  6
0  2  5
1  3  6
2  4  7

上面的操作你看着眼熟吗?我希望如此,因为这就像你设置axis=0时用concat可以实现的一样。然而,append 的独特之处在于,您可以实际追加一个dict对象,这为我们提供了追加不同类型数据的灵活性。

>>> df0.append({"a": 1, "b": 2}, ignore_index=True)
   a  b
0  1  4
1  2  5
2  3  6
3  1  2

上面显示了一个简单的例子。请注意,您必须将ignore_index设置为True,因为字典对象没有数据帧可以使用的索引信息。

结论

在这篇文章中,我们回顾了熊猫的 5 个最常用的数据合并函数。这里有一个快速回顾。

  • concat:按行和按列组合数据
  • join:使用索引按行组合数据
  • merge:按列组合数据,就像数据库连接操作一样
  • combine:按列组合数据,进行列间(相同列)元素操作
  • append:以DataFramedict对象的形式逐行追加数据

感谢阅读这篇文章。通过注册我的简讯保持联系。还不是中等会员?用我的会员链接支持我的写作。

作为数据科学家,如何更有效地沟通

原文:https://towardsdatascience.com/how-to-communicate-more-effectively-as-a-data-scientist-de7dfc361b4f?source=collection_archive---------18-----------------------

我从有效培训解决方案(ETS)培训中学到了什么

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由莱昂Unsplash 上拍摄

有效的沟通技能是数据科学家必备的技能,但却是容易被忽视的东西。缺乏这种技能会导致项目效率低下和对可行见解的误解,这对任何公司来说都是代价高昂的。作为数据科学家/分析师,我们的工作不仅仅是看数字。我们提供可操作的见解,并提出数据驱动的建议。分析完数据后,我们需要向业务涉众解释结果,并帮助他们及时做出业务决策。因此,能够向利益相关者解释您的工作并实际应用您的分析和建议是非常重要的。

沟通和公共演讲技巧是我仍在努力提高的领域。当然,我们自己总有可以改进的地方。我们知道的越多,就越意识到我们不知道。在这篇博客中,我想分享我从有效培训解决方案(ETS) 培训中学到的一些技巧,以及这些培训如何帮助我更好地与利益相关者和同事沟通,希望你也会发现它们很有帮助!

一.舒适地待在那里

信不信由你,只要舒服地坐着或站着,你就能立刻增强自信。当我们微笑时,我们往往会感到更快乐。自信的肢体语言可能也是如此。当我们舒适地坐着说话,就像在和朋友交谈一样,我们确实会感到更加放松和自信。自从我开始应用这个技巧,我注意到我的声音听起来更加肯定和自信。作为一个说话温和的人,有时我很难让别人听到我的声音,我通常不得不有意识地努力大声说话。我想如果我大声说话,我的意见会被听到。但是,这不是音量的问题,而是声音听起来有没有优柔寡断。事实上,在培训期间,培训师和有效培训解决方案的首席执行官 Ingrid Gudenas 帮助我们实践了这一点,观察这一小小的调整如何能够戏剧性地改变别人对我们的看法,这是一次令人大开眼界的经历。试试看,如果你也感觉到了不同,请告诉我!

二。做一个好的倾听者+全神贯注

做一个好的倾听者意味着什么?一个好的积极的倾听者会和说话者交流并提问。在学校,我们没有被训练去问利益相关者问题,因为问题通常是由老师提供的。然而,在解决现实世界的问题时,我们首先需要理解涉众试图解决的业务问题,然后寻找数据。即使你有多年数据科学家的工作经验,你仍然需要仔细倾听业务背景,因为你不想浪费时间在分析上,而利益相关者告诉你你误解了请求。我发现在开会时关闭任何通知很有帮助。这样,我可以保持专注,避免旁敲侧击,并提出澄清性的问题。

三。在虚拟会议中进行眼神交流

作为一个实际上在疫情期间上船的人,我还没有亲自见过我的任何同事。起初,我发现很难与同事建立牢固的关系。虚拟增加距离。英格丽建议我们说话时看着镜头。这模拟了虚拟的眼神交流。我发现这非常有用,尤其是在 30 多名同事面前做演示的时候。看着镜头让我感到更加强大和自信。最重要的是,当我听到观众的一些背景噪音时,我没有分心。

四。有同理心

同情你的听众,用他们能理解的格式和语言向他们展示他们想要的信息。首先,我们要知道观众关心什么,他们已经知道什么。我们绝对不想浪费时间一遍又一遍地重复同样的事情,尤其是当他们已经知道的时候。同时,我们也不应该假设他们已经知道了。了解观众是我们工作的一部分。

业务涉众和高管不关心我们使用了哪些工具进行分析,他们更关心的是调查结果、业务方向以及他们下一步可以做什么;其他数据科学家/分析师/ML 工程师更关心你的方法,以及是否有任何折衷。一旦我们了解了受众,我们就可以定制语言并提供有针对性的演示。对于非技术利益相关者,我们应该避免使用高度技术性的术语。不要假设每个人都知道你在说什么。如果我们不能用外行人的语言解释复杂的结果,我们作为优秀的数据科学家是失败的。成为一名优秀的数据科学家并不是要建立很酷的模型,而是要用数据来讲述一个有助于提出战略性商业计划的故事。

动词 (verb 的缩写)如果有不同意见,请跟进

不骗你,让人们改变他们的价值观真的很难。在这种情况下,我们需要更多的耐心。意见不合是常有的事!不要把它当成一个问题,而是把它当成一个你更好地解释自己的机会。误解会导致分歧。当有冲突时,最好开会而不是发信息。别往心里去!每个人都有自己的顾虑。做一个好的倾听者,有同理心。试着理解他们不同意的原因,心平气和地解释你的观点。归根结底,我们都在努力解决冲突。

在会议期间,双方可以讨论问题,并提出一个潜在的解决方案。这意味着双方达成口头协议,并将致力于上述解决方案。这不是大团圆结局吗?然而,你又等了几个星期,仍然没有听到其他人的任何消息。你可能想知道…我以为我们已经达成协议了?🤔英格丽德告诉我们,我们其实可以通过肢体语言和面部表情来判断协议是否有效。例如,避免眼神交流,看起来很困惑,双眉低垂是他们仍然不同意你的危险信号。当这种情况发生时,承认他们,直到他们愿意听你说什么。安排一次后续会议来了解他们的进展情况是非常重要的。

不及物动词说“我不知道”没关系

首先,寻求帮助并不可耻。有时,我们不知道答案,因为在给出解决方案之前,我们需要时间进行进一步的调查。你不需要觉得自己一直都知道所有的事情。事实上,鼓励数据科学家提出问题。通过提问,你提供了一个不同的视角,也许你不是唯一一个迷路的人。说“我不知道”比当我们不知道的时候假设我们理解了问题,并提供一个错误的答案要好。没有愚蠢的问题,但如果有人已经多次告诉你答案,你可能应该在再次问同样的问题之前思考一下。

最后的想法

有效的沟通是成为一名优秀数据科学家的最重要技能之一。发展这项技能需要时间、努力和练习。以上我通过有效培训解决方案(ETS) 培训学到的技巧帮助我提高了沟通技巧,我真的希望你也能开始看到成效:)

如何轻松比较两个数据帧

原文:https://towardsdatascience.com/how-to-compare-2-dataframes-easily-b8f6788d5f07?source=collection_archive---------18-----------------------

…使用全面的数据协调脚本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Abel Y CostaUnsplash 上拍摄的照片

4 年前,我参与了一个数据迁移项目,是一家全球金融机构业务部门的一员。业务部门需要在 4 小时内完成对账,并为项目上线提供签准。在这个项目之前,我已经开始涉猎 python,当时只听说过pandas库。

这项任务听起来很简单:

确保所有记录都正确迁移。

但是和所有任务一样,通常有一个if语句和一个跟随其后的子句。

如果有任何记录不匹配,则生成这些记录的报告。

业务部门提出的最初想法是使用 Excel 和宏来执行这种调节。但是我理解这种复杂性,并认为 Excel 可能不适合这样的任务。经过一些努力,我让各种利益相关者相信我可以足够快地掌握 python 来完成这项任务。

快进 2 个月,经过几次彩排,我的剧本终于准备好了。在源数据和目标数据之间有一些转换逻辑,但是为了本文的目的,我将展示脚本如何在经过转换的源数据目标数据之间进行比较。

点击此处直接跳转到脚本。

一些假设

df1df2分别为目标数据帧。现在,让我们假设它们具有相同数量的列,并且这些列成对地具有相同的数据类型(即df1中的列 1 与df2中的列 1 具有相同的数据类型,…)。还假设进行比较的列存储在uid变量中。

在文章的最后,我将简要讨论在执行主要的比较脚本之前,为确保数据足够干净而需要采取的额外步骤/检查。

1.记录迁移正确

对所有列执行内部合并,得到的数据帧将是所有记录都匹配的数据帧。注意,uid无关紧要,因为合并是在所有列上完成的。

df_merge = pd.merge(df1, df2, how='inner', on=df1.columns.tolist())

2.记录在源中,但不在目标中

经常会有一些不确定的记录永远不会被迁移,也就是说,它们在源中,但不在目标中。

有几种方法可以识别这些记录,这里有一种:

  • df_merge追加回df1
  • 标记重复的行;使用keep=False将所有重复标记为True
  • 选择不重复的行。
df1_only = df1.append(df_merge).reset_index(drop=True)
df1_only['Duplicated'] = df1_only.duplicated(keep=False)
df1_only = df1_only[~df1_only['Duplicated']]

3。记录在目标中,但不在源中

可能有记录在迁移过程中神秘地创建,可能是由于一些转换错误或人工干预。

以类似的精神,人们可以识别出这些在目标中而不在源中。

df2_only = df2.append(df_merge).reset_index(drop=True)
df2_only['Duplicated'] = df2_only.duplicated(keep=False)
df2_only = df2_only[~df2_only['Duplicated']]

4.源和目标中的记录,但具有不同的值

现在假设有 2 个数据帧,每个数据帧有一条记录:

df1 = pd.DataFrame([['Apple',1]], columns=['Fruit', 'Qty'])
df2 = pd.DataFrame([['Apple',2]], columns=['Fruit', 'Qty'])

通过观察,df_merge将是空的,并且这些数据帧也将分别等同于df1_onlydf2_only

创建一个新的数据帧来显示Apple同时出现在df1df2中是有意义的,但是它们在Qty列中有不同的值。

# Label each dataframe
df1_only['S/T'] = 'Source'
df2_only['S/T'] = 'Target'# Identify the duplicated rows
df3 = df1_only.append(df2_only).reset_index(drop=True)
df3['Duplicated'] = df3.duplicated(subset='Fruit', keep=False)# `subset` argument considers only a subset of the columns when identifying duplicated rows.

将此应用于一个不太重要的例子:

>>> cols = ['Fruit', 'Qty']
>>> df1 = pd.DataFrame([['Apple',1],['Orange',3]], columns=cols)
>>> df2 = pd.DataFrame([['Apple',2],['Pear',4]], columns=cols)
...
... 
>>> # Note that `df1` is still the same as `df1_only`
>>> # Repeat the step in the above code block to get `df3`
>>> df3
    Fruit  Qty      S/T  Duplicated
0   Apple    1   Source        True
1  Orange    3   Source       False
2   Apple    2   Target        True
3    Pear    4   Target       False

现在,可以使用Duplicated栏上的布尔索引来选择:

  1. 在源和目标中具有相同的Fruit值但具有不同的Qty的记录
  2. 严格按照来源的记录
  3. 严格位于目标中的记录
df_diff = df3[df3['Duplicated']]
df1_only = df3[(~df3['Duplicated']) &(df3['S/T']=='Source')]
df2_only = df3[(~df3['Duplicated']) &(df3['S/T']=='Target')]

5.附加步骤/检查

该脚本进行额外的检查,以确保下游代码成功;它检查:

  1. 两个数据帧都有相同数量的列
  2. 两个数据帧具有相同的列名集否则打印识别的orphans
  3. 两个数据帧的列处于相同的顺序(这对于比较并不重要,但是对于一个人来说,检查两个列混杂在一起的数据帧在视觉上是困难的。)
  4. 两个数据帧中每一列的数据类型都是成对相同的。(如果源列具有int数据类型,而对应的目标列具有float数据类型,这可能意味着存在具有空值的行。)
  5. 根据应用比较的列检查记录的唯一性。(这应该总是 100%,否则应该在uid中包含更多的列来进行比较。)

6.使用脚本

使用该脚本非常简单,只需传递 3 个位置参数:

  • df_leftdf_right是指你输入的数据帧
  • uid指组成唯一键的单个列(str)或一列列。(即Fruits)

也可以传递两个可选的关键字参数:

  • labels(默认= ( LeftRight))允许您将输入的数据帧命名为Source & Target。标签构成了输出有序字典的关键字。
  • drop(默认值= [[],[]])可以接受要从比较中排除的列的列表。
def diff_func(df_left, df_right, uid, labels=('Left','Right'), drop=[[],[]])
   ...
   ...

基于我们迄今为止的例子:

>>> df1 = pd.DataFrame([['Apple',1],['Orange',3],['Banana',5]], columns=['Fruit','Qty'])
>>> df2 = pd.DataFrame([['Apple',2],['Pear',4],['Banana',5]], columns=['Fruit','Qty'])
>>> d1 = diff_func(df1, df2, 'Fruit')

输出d1将是具有 6 个数据帧的有序字典:

>>> d1['Left']
    Fruit  Qty
0   Apple    1
1  Orange    3
2  Banana    5
>>> d1['Right']
    Fruit  Qty
0   Apple    2
1    Pear    4
2  Banana    5
>>> d1['Merge']
    Fruit  Qty
0  Banana    5
>>> d1['Left_only']
    Fruit  Qty
1  Orange    3
>>> d1['Right_only']
  Fruit  Qty
3  Pear    4
>>> d1['Diff']
  Left or Right  Fruit  Qty
0          Left  Apple    1
1         Right  Apple    2

结论

虽然创建这样一个脚本的最初目的仅仅是为了协调一组特定的迁移数据,但是我认识到,如果可以将其一般化,它可以用于比较任意两个数据帧。因此,我决定编写一个通用函数,它按顺序进行一系列检查,然后比较数据帧,最后在包含 6 个数据帧的字典中输出结果。

这不是在 stackoverflow 上吗?

有趣的是,虽然 stackoverflow 上有许多比较两个数据框架的答案,但没有一个答案是我真正想要的。它很少是完整的,也没有我正在寻找的检查。随后,我在 stackoverflow 上发布了这个答案——这也是我的第一个答案——到目前为止收到了 3 次投票。

Pandas merge 有一个关键字参数“indicator=True ”,它指示记录是存在于左侧、右侧还是两个表中。

indicator=True指示记录是存在于两个表中还是只存在于其中一个表中。然而,当替换表不包含比较的键时,具有整数值的列被转换成float,这里有一个例子。

>>> import pandas as pd
>>> df1 = pd.DataFrame([['Apple',1],['Orange',3],['Banana',5]], columns=['Fruit','Qty'])
>>> df2 = pd.DataFrame([['Apple',2],['Pear',4],['Banana',5]], columns=['Fruit','Qty'])
>>> df3 = pd.merge(df1, df2, on='Fruit', how='outer', indicator=True)
>>> df3
    Fruit  Qty_x  Qty_y      _merge
0   Apple    1.0    2.0        both
1  Orange    3.0    NaN   left_only
2  Banana    5.0    5.0        both
3    Pear    NaN    4.0  right_only

df3中,我们可以很容易地看到Orange只存在于左边的表格中。然而,Qty_x列不再是一个具有int数据类型的序列对象,而是一个float64数据类型。这可能会造成混乱,因此我决定不使用这种方法。

既然已经对词典进行了排序,为什么还要使用 OrderedDict?

这个脚本最初是在 python 字典还是无序的时候编写的,因此我使用了有序字典。我怀疑如果我切换到一个普通的字典,性能会有显著的提高,因此我决定保留它,为了怀旧,并确保它对那些使用旧版本 python 的人是兼容的。

完整代码如下:

数据团队的事件管理

原文:https://towardsdatascience.com/how-to-conduct-incident-management-on-your-data-pipelines-2dfc20b1b0b7?source=collection_archive---------20-----------------------

大规模识别、找出根本原因并解决数据质量问题的 4 个步骤

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由巴尔·摩西提供。

随着数据系统变得越来越分散,公司接收越来越多的数据,出错(和事故)的机会只会增加。几十年来,软件工程团队一直依靠多步骤流程来识别、筛选、解决和防止问题影响他们的应用程序。

随着数据操作的成熟,是时候我们以同样的勤奋对待 数据停机 了,换句话说,就是数据丢失、不准确或其他错误的时间段,特别是在构建更可靠、更有弹性的数据管道时。

虽然关于数据团队如何处理其数据的事件管理的文献并不多,但我们已经从软件开发的朋友那里获得了大量资源。经过一些调整,这些技巧已经成为一些最好的数据工程团队的无价工具。

当涉及到为您的管道构建数据事件管理工作流时,4 个关键步骤包括:事件检测响应根本原因分析(RCA)、&解决方案,以及无可指责的事后分析

在本文中,我们将介绍这些步骤,并分享数据团队在制定自己的事故管理策略时可以使用的相关资源。

事件检测

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将自动数据质量监控集成到您的关键工作流中是您的事件管理流程成功的基础,并允许您的团队指定谁在调查问题及其状态(即待定、调查、已解决)。图片由巴尔·摩西提供。

不言而喻,在数据进入生产之前,您首先应该 测试数据 。尽管如此,即使有了最强大的测试和检查,在您说“数据管道损坏”之前,坏数据还是会从裂缝中掉出来,并被推到戳中。

当数据宕机发生时,第一步是事件检测。可以通过 数据监控和警报 来检测事件,这既可以在您的数据管道上手动实施,也可以基于特定阈值触发,或者作为 数据可观察性 解决方案的一部分分层实施,并基于历史数据模式和自定义规则定期自动触发。

数据监控的一个关键组件是 异常检测 ,即识别数据健康支柱(即,容量、新鲜度、模式和分布)何时偏离正常的能力。异常检测在端到端(跨您的仓库、湖泊、ETL 和 BI 工具)实施时最有价值,而不是仅在您的数据生态系统的特定孤岛中实施。良好的异常检测还将调整算法以减少白噪声和误报。

事件检测可以集成到数据工程和分析工作流中,确保在通过适当的通信渠道(Slack、电子邮件、SMS、信鸽等)出现问题时,所有数据利益相关方和最终用户都能收到通知

建议的资源:

反应

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作为一名事故指挥官,能够专注于数据质量问题可以更容易地了解数据管道中的问题。图片由巴尔·摩西提供。

良好的事件响应始于——也止于——有效的沟通,幸运的是,大部分事件响应可以提前准备好,并在适当的时候通过 PagerDuty 和 Slack 通过适当的工作流程自动完成。

数据团队应该花时间创建运行手册和行动手册,以完成标准事件响应。操作手册为您提供了如何使用不同服务以及遇到的常见问题的说明,而行动手册则提供了处理事件的分步流程。两者都应该提供代码、文档和其他材料的链接,这些链接可以帮助团队理解当关键管道破裂时该做什么。

一本好的操作手册的一个重要部分?发生停机或故障时委派角色。

在传统的现场可靠性工程项目中,一种随叫随到的过程,根据服务委派特定的角色,通常按小时、天或周进行分段。除了“事件响应者”,通常还有一名“ ”事件指挥官 ”,负责在响应者和其他利益相关者解决问题时分配任务和综合信息。

事故指挥官还负责与可能受影响的上游和下游消费者进行沟通,即那些使用由破裂管道提供动力的数据产品的消费者。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

端到端沿袭是一种有价值的工具,用于在数据管道中断时了解上游和下游的依赖性,以便在坏数据影响业务之前通知相关方。图片由巴尔·摩西提供。

对于业务上下文, 元数据是一个强大的工具 ,用于了解哪些团队受到给定数据停机事件的影响;再加上自动化的、端到端的沿袭,沟通这些受影响的资产之间的上游和下游关系可以是一个无痛且快速的过程,节省了团队手工绘图的时间。

一旦发生数据宕机,就必须将其影响传达给上游和下游用户,包括处理数据的用户和使用数据的用户。通过正确的方法,可以使用 PagerDuty、Slack 和其他通信工具将其中的大部分内容融入到自动化工作流中。

建议的资源:

根本原因分析和解决方案

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

了解哪些数据源会导致数据管道中断,这对根本原因分析至关重要。图片由巴尔·摩西提供。

理论上,根本原因听起来就像运行几个 SQL 查询来分割数据一样简单,但在实践中,这个过程可能相当具有挑战性。事件可能以不明显的方式出现在整个管道中,并影响多个(有时是数百个)表。

例如,数据质量差的一个常见原因是新鲜度,即当数据异常过时时。这种事件可能是由多种原因造成的,包括作业卡在队列中、超时、合作伙伴未及时提供其数据集、错误或意外的计划更改从 DAG 中删除了作业。

根据我们的经验,我们发现大多数数据问题都可以归因于以下一个或多个事件:

  • 输入作业、管道或系统的数据发生意外变化
  • 逻辑的变化 (ETL、SQL、Spark 作业等。)转换数据
  • 运营问题,如运行时错误、许可问题、基础设施故障、日程变更等。

快速确定手头的问题不仅需要适当的工具,还需要考虑这三个来源如何以及为什么会中断的整体方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

随着软件(和数据)系统变得越来越复杂,查明停机或事故的确切原因(或根源)变得越来越困难。亚马逊的“五个为什么”方法提供了一个有用的框架,通过这个框架,我们可以了解 RCA:

  • 找出问题所在
  • 询问问题发生的原因,并记录原因
  • 确定原因是否是根本原因
  • 原因是否可以避免?
  • 原因有没有可能在事情发生之前就被检测出来?
  • 如果原因是人为失误,为什么可能呢?
  • 将原因作为问题,重复该过程。当你确信你已经找到了根本原因时,就停下来。

你的系统崩溃的原因很少是单一的。随着数据工程师努力通过更智能的流程、测试、数据新鲜度检查和其他解决方案来减少人工劳动,他们应该能够在问题浮出水面之前发现问题。当他们不这样做时,这是一个强烈的迹象,表明这些故障保险是不够的。正如在软件工程领域一样,自动化解决方案,如数据可观察性和端到端监控,通常是对抗数据宕机的最佳选择。

首先,我们确定了数据团队在对其数据管道进行 RCA 时必须采取的四个步骤:

  1. ****看看你的血统:要了解什么出了问题,你需要找到系统中出现问题的最上游节点——那是事情开始的地方,也是答案所在。如果你幸运的话,万恶之源出现在有问题的仪表板上,你会很快发现问题。
  2. ****查看代码:查看创建该表的逻辑,甚至是影响事件的特定字段,将有助于您对问题所在提出合理的假设。
  3. ****查看您的数据:在第 1 步和第 2 步之后,是时候更仔细地查看表格中的数据,寻找可能出错的地方。这里有一种很有前途的方法,那就是研究表中有异常记录的其他字段如何提供线索,说明数据异常发生在哪里。
  4. ****看看您的操作环境:许多数据问题是运行您的 ETL/ELT 作业的操作环境的直接结果。查看 ETL 引擎的日志和错误跟踪可以找到一些答案。

(如果你还没有读过,可以看看 Francisco Alberini 的文章关于数据工程师如何进行根本原因分析,非常值得一读)。

一旦您发现出了问题,了解了其影响,确定了根本原因,并与适当的利益相关者沟通了后续步骤,就该解决问题了。这可能与暂停数据管道或模型并重新运行它们一样简单,但是由于数据可能由于数百万种原因而中断,这通常涉及大量的故障排除。

建议的资源:

无可指责的验尸

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

无可指责的事后分析通常以对问题的深入分析和明确的后续步骤结束,以防止类似事件影响未来的管道。图片来自 万花筒 un splash**

我的一个朋友是一名现场可靠性工程师,在 Box、Slack 和其他硅谷公司有十多年的灭火经验,他告诉我,如果不把这一点说得非常清楚,我就不能写一篇关于事故管理的文章:

“对于每一个事件,都是系统出了问题,而不是编写代码的人。好的系统是为容错和人类宽容而构建的。允许你犯错是系统的职责。”

当谈到数据可靠性和数据运营时,同样的精神听起来是真实的。管道应该是容错的,有适当的流程和框架来考虑数据管道中的 已知未知和 未知。

无论发生了何种类型的事故或事故原因是什么,数据工程团队都应该在解决问题并进行根本原因分析后,进行全面的跨职能事后分析。

以下是一些最佳实践:

  • 把一切都框定为一次学习经历:为了有建设性,验尸报告必须是无可指责的(如果不是,那么知道指责)。试图对事件进行“指责”是很自然的,但在向你的同事灌输信任或培养合作文化时,这很少有帮助。通过围绕“学习和改进”的目标重新构建这种体验,更容易主动采取解决数据质量所必需的组织(创建更好的工作流和流程)和技术步骤(为投资新工具提供理由)。
  • ****以此为契机,评估您对未来事件的准备情况:更新操作手册,调整您的监控、警报和工作流管理工具。随着您的数据生态系统的发展(添加新的第三方数据源、API,甚至消费者),这一步在事件预防方面将变得至关重要。
  • ****记录每一次事后分析,并与更广泛的数据团队分享:就像在软件工程中一样,记录哪里出错了,系统是如何受到影响的,以及根本原因是什么,这些通常是事后才想到的。但是,文档记录与事件管理流程中的任何其他步骤一样重要,因为它可以防止在拥有部落知识的工程师离开团队或无法提供帮助时出现知识缺口。
  • 重温 SLA:之前的一篇文章中,我讲述了为什么数据团队需要为他们的数据管道设置 SLA。简而言之,服务水平协议(SLA)是许多公司用来定义和衡量给定供应商、产品或内部团队将提供的服务水平的一种方法,以及在失败时的潜在补救措施。随着数据系统的成熟或随着时间的推移而变化,不断地重新审视您的SLA、服务级别指标( SLIs )和服务级别目标( SLOs )非常重要。六个月前有意义的 SLA 可能不再有意义;你的团队应该是第一个知道这些变化并与下游消费者沟通的人。

说到底,事后检讨对于数据团队和软件工程师一样重要。随着我们领域的不断发展(毕竟,我们正处于数据时代),了解数据停机是如何发生的以及为什么会发生是我们不断提高系统和流程弹性的唯一途径。

建议的资源

引用我们 SRE 前辈的话: 希望不是战略

但是,有了这些最佳实践,您就可以将事件管理从“四处探索并希望有最好的结果”变成一台运转良好、高度可靠的机器。

有兴趣了解更多关于 Vimeo Eventbrite Compass 以及其他领先公司 如何利用数据可观察性大规模防止管道破裂?

伸出手去 巴尔摩西***蒙特卡洛团队的其他人。T38*

如何配置 Julia 包

原文:https://towardsdatascience.com/how-to-configure-julia-packages-93a26e28ea76?source=collection_archive---------56-----------------------

朱莉娅综合教程

深入了解 Julia 中的配置和类型

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(图片由作者提供)

本文视频:

我们项目的存储库:

https://github.com/ChifiSource/SuperFrames.jl

介绍

在之前的“Julia 综合教程”中,我们介绍了在 Julia 编程语言中使用 Project.toml 文件和虚拟环境的基础知识。如果您还没有阅读或观看这个系列教程的迭代,如果您感兴趣,可以在这里查看:

Project.toml 文件是描述任何 Julia 项目的宝贵资产。这个文件不仅包括项目需要的所有依赖项,还包括那些包的兼容版本,以及关于包的元信息。虽然 Project.toml 的大部分可以通过创建新的虚拟环境来机械地生成,但是配置的某些部分必须手动完成。

配置我们项目文件的其余部分

完成这个项目设置的第一步是完成我们的 Project.toml 文件的配置。首先,我们应该看看我们的武器库中的一些配置选项,比如“名称”、“版本”和“UUID”这是我们完成的 Project.toml 文件,它将使解释其中每个资产为 Julia 的包管理器做什么变得容易得多。

authors = ["emmett [emmett@emmettboudreau.com](mailto:emmett@emmettboudreau.com)"]
name = "SuperFrames"
uuid = "19a2823e-5050-11eb-208c-916d674a0ad5"
[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
[compat]
julia = "1.5"
DataFrames = "0.22.1"

作者

“作者”是一个不言自明的领域;这些是参与这个项目的人。当然,在这里我们看到我和我的电子邮件在一个字符串中,这个字符串是用 Lisp 风格的列表编写的。也就是说,应该在包含 Lisp 风格列表字符串的 Julia 风格数组中提供额外的条目。

名字

名称是我们包装最重要的属性之一。这将是最终用户调用和使用软件包的方式,因此这当然非常重要。虽然“using”调用可能会使用模块名,但是您的模块名使用与您的 Pkg 名相同的名称可能是明智的,因为否则人们甚至会很难弄清楚如何导入您的包!也就是说,这个文件中描述的名字将被 Julia 注册中心用来识别你的包的名字。

uuid

UUID (Universal Unique Identifier,通用唯一标识符)是字母和数字的组合,用于抽象地表示任何东西,但在涉及到包时有明确的用途。UUIDs 允许包管理器 Pkg 跟踪几个包,可能有相同的名字,有时来自完全不同的注册中心,并允许它们一起工作。

我们需要的 Julian 包的 UUID 类型可以使用 UUIDs.jl 包获得。我们可以通过以下方式导入模块

using UUIDs

既然模块已经导入,现在有一个名为

uuid1()

这需要一个位置参数。一个随机数发生器。通常在这些情况下,随机数生成器是一种接受种子并基于该种子返回随机数的类型。默认情况下,该参数使用全局随机数生成器,该生成器将使用编译器在编译时提供的种子。

考虑到这一点,我们真的不需要种子,所以我只是像这样传递方法:

uuid = uuid1()

然后将生成的 UUID 记录到我们的 Project.toml 文件中。

[deps]

DataFrames 是我们在[deps]部分中唯一的依赖项。该键的对应值是 DataFrames.jl 包的 UUID。这当然会在我们创建虚拟环境时自动添加到我们的 Project.toml 文件中。

[兼容]

compat 部分用来告诉 Julia 的包管理器这个项目要处理哪些版本的依赖项。对于一般的 Julia 应用程序,让 Julia 兼容性至少为 1.0 或更高可能是个好主意。对于今天的产品包,我将把 Julia 的兼容性设置为 1.5,因为我使用的是 1.5.2,我将把 DataFrames 的兼容性设置为 DataFrames 的最新版本:

[compat]
julia = "1.5"
DataFrames = "0.22.1"

基本模块扩展

正如我们在讨论显式导入时所讨论的,我们将需要显式导入任何我们想要从中扩展方法或类型的包。虽然我们可能不会扩展 DataFrame 类型的功能,但是只要我们利用了 DataFrames.jl 包的类型层次结构,我们就可以在 DataFrame 上使用 DataFrames.jl 提供的方法。

类型层次结构只是一种类型在一系列类别上的分类。当某些类型可以用某些方式处理时,这就很方便了,因为它们有共同的属性,但有时它们没有。对于本例,由于 DataFrames.jl 包中的大多数方法都使用“AbstractDataFrame”类型,我们将直接导入它并创建一个新类型,它将继承它的所有方法。首先,让我们导入构建我们自己的相似类型 AbstractDataFrame 和 Index 所需的两种类型。

import DataFrames: AbstractDataFrame
import DataFrames: Index

我们今天要做的最后一件事是创建一个新类型,它将继承已经赋予抽象类型 AbstractDataFrame 的所有属性。我们使用<:/>

结论

虽然 Julia 的 Pkg 包管理器在开发包时可能需要做一些工作来启动和运行,但一旦包发布并感受到好处,这肯定是值得的。虽然在这一版的 Julia 教程中没有太多的编程,但将来肯定会有更多的计划深入算法和 Julian 编程。我期待着展示这种语言在类型和方法方面的更多功能!感谢您的阅读!

如何将本地或远程机器连接到 Databricks 集群

原文:https://towardsdatascience.com/how-to-connect-a-local-or-remote-machine-to-a-databricks-cluster-18e03afb53c6?source=collection_archive---------11-----------------------

业内笔记

Databricks、Python 和 Docker 的交集

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

粘土银行Unsplash 拍摄的照片

当您开始使用 Databricks 时,您将会决定在 Databricks 之外进行编码,并远程连接到它的计算能力,也就是 Databricks 集群。为什么?主要是因为 Databricks 的主要特性之一是它的 Spark 作业管理,这可以让您的生活变得轻松。使用该服务,您可以向大规模数据集提交一系列 Spark 作业,并在几秒钟内返回您的结果;多亏了它的火花引擎。在本文中,我想描述如何配置您的本地或远程机器连接到 Databricks 集群,作为这个过程的第一步。

https://www.amazon.com/gp/product/B08D2M2KV1/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0

—什么是数据块?

Databricks 是一个抽象层,位于 AWS 和 Azure 等冷云基础设施上,使您可以轻松管理计算能力、数据存储、作业调度和模型管理。它为您提供了一个开发环境,以获得您的数据科学或人工智能项目的初步结果。Databricks 由 Spark 提供支持,Spark 是一个开源数据处理引擎,专门为大规模数据设计。

Databricks 提供的简单性有一些限制。例如,Databricks 使您作为数据科学新手能够快速生成结果,因为您不需要大量处理云配置或可视化工具。然而,如果您想要控制开发的每个方面,Databricks 肯定会限制您。

—要求是什么?

1-使用受支持的数据块运行时创建数据块集群

每个 Databricks 集群都必须运行一个称为 Databricks 运行时的专用操作系统。在配置集群时,您会发现许多版本的 Databricks 运行时。如果您想要远程连接到 Databricks 集群,您必须谨慎选择 Databricks 运行时版本。为什么?因为databricks-connect客户端支持有限数量的数据块运行时版本,所以 Spark 客户端库支持这种远程连接。

数据块运行时版本必须与数据块连接库兼容。

换句话说,您不能远程连接到其数据块运行时不受databricks-connect支持的集群。您可以在 Databricks Connect 的原始文档中找到 Databricks 运行时版本的更新列表。

https://docs.databricks.com/dev-tools/databricks-connect.html#requirements

2-安装所需的 Python 和 Java 版本

选择与databricks-connect兼容的 Databricks 运行时版本后,您必须确保在您的机器上使用兼容的 Python 版本。如原始文档中所述:“客户机 Python 安装的次要版本必须与 Databricks 集群的次要 Python 版本相同。”

开发环境的 Python 版本必须与在 Databricks 集群上工作的 Databricks 运行时版本兼容。

假设您为 Databricks 运行时版本选择了 7.3 LTS 。在这种情况下,您必须在本地或远程机器上安装 Python 3.7 才能与之兼容。您还必须在您的机器上安装 Java 运行时环境(JRE) 8。这些都是由 Databricks 网站指导的。

3-安装所需的 Databricks Connect 版本

正如 Python 开发所建议的,最好创建一个隔离的虚拟环境,以确保没有冲突。你可以用你选择的库,如venvpipenvconda,轻松构建一个虚拟环境。我在这里选了最新的。

如果不想创建新的虚拟环境,确保不要在现有环境上安装(或卸载)pyspark。您应该卸载现有版本的pyspark,因为它与databricks-connect客户端冲突。databricks-connect有自己的方法,相当于pyspark的方法,这使得它可以独立运行。通过下面的代码,您用 Python 3.7 和一个版本的databricks-connect创建了一个虚拟环境。

conda create --name ENVNAME python=3.7
conda activate ENVNAME
pip3 uninstall pyspark
pip3 install -U databricks-connect==7.3.*

你可能不需要上面的pip3 uninstall pyspark,因为虚拟环境是干净的。我把它放在那里只是为了完整。

—如何根据需求创建 Docker 映像

如果您想用 Python 3.7 和 Java 8 以及一个版本的databricks-connect构建 docker 映像,您可以使用下面的 docker 文件。

FROM ubuntu:20.04RUN apt-get update && apt-get -y install sudo
RUN sudo apt-get -y install software-properties-common### INSTALL PYTHON
RUN sudo apt-get -y install libssl-dev openssl
RUN sudo apt-get -y install libreadline-gplv2-dev libffi-dev
RUN sudo apt-get -y install libncursesw5-dev libsqlite3-dev
RUN sudo apt-get -y install tk-dev libgdbm-dev libc6-dev libbz2-dev 
RUN sudo apt-get -y install  wget
RUN apt-get update && apt-get install make
RUN sudo apt-get -y install zlib1g-dev
RUN apt-get -y install gcc mono-mcs && \
    rm -rf /var/lib/apt/lists/*
RUN wget [https://www.python.org/ftp/python/3.7.10/Python-3.7.10.tgz](https://www.python.org/ftp/python/3.7.10/Python-3.7.10.tgz)
RUN tar xzvf Python-3.7.10.tgz
RUN ./Python-3.7.10/configure
RUN sudo make install
RUN alias python=python3### INSTALL JAVA
RUN sudo add-apt-repository ppa:openjdk-r/ppa
RUN sudo apt-get install -y openjdk-8-jre### INSTALL DATABRICKS-CONNECT
RUN pip3 install --upgrade pip
RUN pip3 uninstall pyspark
RUN pip3 install -U databricks-connect==7.3.*

—如何配置连接属性?

使用databricks-connect configure,很容易配置databricks-connect库以连接到 Databricks 集群。运行此命令后,它会以交互方式询问您有关主机、令牌、组织 ID、端口和集群 Id 的问题。要了解更多信息,您可以查看下面的官方文档。

https://docs.databricks.com/dev-tools/databricks-connect.html#step-2-configure-connection-properties

然而,如果您想自动配置 Docker 映像中的连接属性,您可以将以下代码添加到上述 Docker 文件的末尾。

RUN export DATABRICKS_HOST=XXXXX && \
    export DATABRICKS_API_TOKEN=XXXXX && \
    export DATABRICKS_ORG_ID=XXXXX && \
    export DATABRICKS_PORT=XXXXX && \
    export DATABRICKS_CLUSTER_ID=XXXXX && \
    echo "{\"host\": \"${*DATABRICKS_HOST*}\",\"token\": \"${*DATABRICKS_API_TOKEN*}\",\"cluster_id\":\"${*DATABRICKS_CLUSTER_ID*}\",\"org_id\": \"${*DATABRICKS_ORG_ID*}\", \"port\": \"${*DATABRICKS_PORT*}\" }" >> /root/.databricks-connectENV *SPARK_HOME*=/usr/local/lib/python3.7/site-packages/pyspark

上面的代码人工创建了配置文件,并将其保存在适当的地址。此外,它将SPARK_HOME地址设置为正确的值。当您运行databricks-connect configure时,这些步骤在没有您参与的情况下被执行。当您想要自动配置连接属性时,您应该这样做。

最后,但同样重要的是,您可以通过运行databricks-connect test来检查连接的健康状况。

感谢阅读!

如果你喜欢这个帖子,想支持我…

https://pedram-ataee.medium.com/membership

如何从 Mac 将本地 R 项目连接到 GitHub

原文:https://towardsdatascience.com/how-to-connect-a-local-r-project-to-github-from-a-mac-4f183d57477e?source=collection_archive---------37-----------------------

带截图的逐步指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由来自佩克斯克里斯蒂娜·莫里洛拍摄

在创建一个新的 R 项目时,设置一个 GitHub 连接是相当简单的。然而,有时您最终会得到一个只存储在本地的回购协议。也许你从一个不使用 GitHub 的人那里接受了一个项目,或者也许你今天不在状态,只是忘了从 GitHub 连接开始。

无论哪种方式,您都可以轻松地将这个 repo 复制到 GitHub 中并建立连接。这个循序渐进的指南会告诉你怎么做。

1.下载 GitHub for Mac 应用程序

首先,前往 GitHub for Mac 的网页:【http://mac.github.com/

您应该会看到以下屏幕:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

点按屏幕中间的紫色“macOS 下载”按钮。zip 文件应该立即开始下载。下载完成后,双击 zip 文件。GitHub 桌面应该出现在您的下载文件夹中,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将 GitHub Desktop 从下载文件夹拖到“应用程序”中,该文件夹在下方左侧突出显示。您应该会看到一个紫色的 GitHub 桌面图标出现(见右下角):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.打开 GitHub 桌面并建立连接

双击 GitHub 桌面图标。您可能会收到一条警告,指出“GitHub Desktop”是一个从互联网下载的应用程序,并询问您是否要打开它。如果您看到此警告,请选择“打开”:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

GitHub 桌面打开后,选择“添加现有存储库”如果这是你第一次打开 GitHub 桌面,你的屏幕看起来可能会有些不同,但是仍然应该有一个“添加现有库”选项。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

应该会出现以下窗口。单击“选择…”按钮并导航到包含您的 R 项目的文件夹。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一旦您选择了包含您的本地项目的文件,您将会得到下面的通知:“这个目录似乎不是一个 Git 存储库。是否要在这里创建一个存储库?”单击蓝色的“创建存储库”文本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

应该会出现以下窗口。只需点击右下角的“创建存储库”按钮。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

出现以下屏幕时,单击“发布存储库”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将弹出以下窗口,您可以简单地单击“发布存储库”如果您希望公开您的回购协议,您可以取消选中“将此代码保密”复选框

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

根据项目的大小,发布可能需要几分钟时间。一旦项目被推送到 GitHub,你就应该一切就绪了!

3.验证连接是否成功

您可以通过登录 GitHub 帐户并验证您是否在“Repositories”下看到新的 repo 来确保连接成功建立。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

此外,当您的项目在 RStudio 中打开时,您现在应该会看到“Git”选项卡,您可以在其中推送和获取任何更新。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

就是这样!通常,在创建 R 项目时,您会希望坚持使用创建 GitHub repo 的标准工作流程。这样,您将能够充分利用 GitHub 的版本控制功能。您的代码将始终被备份,并且您可以在以后访问您的工作的早期版本。然而,当无法遵循此工作流程时,GitHub Desktop 提供了一种便捷的方式将现有的本地项目连接到 GitHub repo。

如何使用私有端点将 Azure 数据工厂连接到 Azure SQL 数据库

原文:https://towardsdatascience.com/how-to-connect-azure-data-factory-to-an-azure-sql-database-using-a-private-endpoint-3e46984bec5e?source=collection_archive---------10-----------------------

循序渐进的教程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Unsplash 上由 Hafidh Satyanto 拍摄的照片

Azure Data Factory (ADF)非常适合从多个来源提取数据,其中最明显的可能是 Azure SQL。然而,Azure SQL 有一个拒绝公共网络访问的安全选项,如果启用,将阻止 ADF 在没有额外步骤的情况下进行连接。

在本文中,我们将了解设置私有端点并使用它从 Azure Data Factory 连接到 Azure SQL 数据库所需的步骤。

Azure SQL 中的“拒绝公共网络访问”设置

在我们开始之前,让我们回顾一下我在 Azure SQL 中所指的设置。这是一个名为拒绝公共网络访问的开关,位于 Azure 门户网站的安全>防火墙和虚拟网络下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作者

启用此设置时,如果没有私有端点,Azure Data Factory 将不会连接。你可以看到在 toggle 控件下面甚至有一个创建私有端点的链接,但是现在不要使用它——我们马上会从 Azure Data Factory 创建请求。

ADF 集成运行时

要在 Azure Data Factory 中使用私有端点,必须使用启用了虚拟网络配置的集成运行时。该设置不能更改,所以如果您还没有启用它的运行时,您需要创建一个新的运行时。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作者

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作者

现在您已经有了一个启用了虚拟网络配置的集成运行时,您已经准备好创建一个新的链接服务了。

ADF 链接服务

仍在 Azure Data Factory 中时,单击以创建新的链接服务。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作者

当您选择启用虚拟网络配置的集成运行时,一个受管理私有端点设置将出现在帐户选择方法部分。该设置是只读的,将在您输入订阅和服务器详细信息时填充。如果受管私有端点已经可用,您就可以开始了!

如果受管理的私有端点不可用,请单击创建新的链接按钮开始该过程。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作者

当您在 Azure Data Factory 中保存新的托管私有端点时,它将在 Azure 中被提供,但在获得批准之前将保持在挂起状态。

Azure 私有端点

我们跳回 Azure 来批准新的私有端点。在 Azure 门户中找到你的 Azure SQL 数据库,并浏览到安全>私有端点连接

您应该会看到由 Azure Data Factory 创建的连接,状态为 Pending 。选中其复选框,点击批准按钮。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作者

在 Azure 门户中,状态将变为已批准。状态到达 Azure 数据工厂需要一两分钟,但是过一会儿它也会显示为已批准

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作者

一旦显示为批准,您就可以开始了。您可以输入其余的连接信息并连接!

概述

我展示的大多数设置都可以通过几种不同的方式访问,并以不同的顺序执行。例如,您可以从 Azure 门户创建私有端点,而不是通过 Azure 数据工厂。很明显,你可以尝试并找到适合你的方法。

重要的部分如下:

  1. Azure Data Factory 有一个支持虚拟网络配置的集成运行时
  2. Azure SQL 具有批准的私有端点连接。
  3. Azure Data Factory 有一个使用集成运行时和私有端点连接的链接服务。

就这样,现在去享受你的新连接吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值