TowardsDataScience 博客中文翻译 2020(五百八十七)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

让我们来谈谈分析:我真实的项目经验

原文:https://towardsdatascience.com/lets-talk-about-analytics-my-real-world-experience-988d66c91e8a?source=collection_archive---------63-----------------------

与真实世界项目经验的相遇

在发表了一系列(技术)文章之后,我们主要讨论了数据科学和机器学习的基本概念,今天,我想谈谈我的工作经验。

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

图片由 Unsplash 上的克拉克街商业拍摄

首先,我的一个客户被认为是我的国家(印度)最大的零售巨头之一。他们在全印度经营着 180 多家连锁店,名下注册了 27 个品牌。现在你可能想知道为什么我要谈论我的客户?我应该谈谈分析,以及我所做的工作。我给出这个背景的原因是因为我想让你们想象一下每天产生的数据量。让你感受一下,不同类型的数据点包括:进店人数、销售收入、产品数量、退货、忠诚度计划等。所有 180 多家商店的这些和许多其他数据点。想象一下每天生成的数据量。

我们有数据了,现在呢?

我在零售分析领域工作。在零售领域,执行分析的范围是巨大的。无论是市场营销、物流、忠诚度计划、客户细分、商店细分等。对于任何分析项目,定义项目的目标和范围都非常重要。定义目标和范围创建了我们需要执行的基本框架。它还帮助我们理解我们需要收集来执行分析的数据点的种类。如果我们知道我们在找什么,在哪里可以找到,那么收集数据就更简单了?就我而言,我必须处理多种来源的数据。我使用 MySQL 数据库、PostgreSQL,甚至一些静态数据的 csv 文件。一旦您收集了所需的数据点,下一步就是清理这些数据。我看过很多文章,在这些文章中,人们分享了他们的经验,他们谈到要花 60–70%的时间来收集和清理数据。这在我的情况下是 100%真实的。我花了相当多的时间编写 SQL 查询,通过正确的计算获得正确的数据点。

个人经验亮点:您从数据库中提取的用于执行分析的数据和管理团队使用各种报告引用的数据可能不同。在我的案例中,各种来源的报告呈现给管理团队的数据包含了许多我完全不知道的内部过滤器。我是吃了苦头才知道的。然而,我个人认为这样的事情发生在一个组织中,并成为未来项目的学习曲线。

因此,您获得了所需的数据点,甚至对其进行了清理,但是您究竟如何处理这些数据呢?

好吧,我告诉你我是怎么做的。但在此之前,我需要向你们解释一个术语。一个术语,描述了我的整个项目。其每平方英尺销售额叫做又名。有些人甚至称之为 SPF。**

你可能在某个时候去过某个特定品牌的零售店。当你走进商店时,你会惊叹于它们的空间之大。有许多是多层的。现在,这个巨大的空间有它自己的一套利弊。

优点:

  • 有足够的空间展示他们的选择
  • 不觉得拥挤(尤其是在高峰时间)
  • 顾客可以在购物时拥有自己的空间(改善顾客购物体验)

缺点:

  • 大型商店的维护变得困难
  • 在多层商店的情况下,很多时候顾客甚至不去上面的楼层
  • 增加运营成本

所以,当你去这些商店的时候,你会在特定的地方看到特定的品牌。你认为他们为什么会在那里?进行了大量的数据研究和分析,以得出品牌在商店中的位置。还有一整个视觉营销领域与之相关。

所有这些听起来都很有趣,但你仍然没有介绍你的角色?

耐心点。一切都在一起。

在零售行业,衡量每一个商店的业绩是非常重要的。这有助于公司了解哪些商店表现最好,哪些不好。在此基础上,他们可以做出关键的决定,如商店扩张或关闭特定的商店。有各种衡量商店绩效的指标。一个这样的措施是 SPSF

让我们剖析一下这个术语:每平方英尺销售额(SPSF)。从常识上来说,我做术语所说的。我衡量商店的 SPSF,并分析数据以发现模式,并提出改进建议。让我们举个例子:

比方说,商店 A 产生的收入为卢比。2018-2019 财年为 1,000,000 英镑。这家商店的地毯总面积大约是 20,000 平方米。制成

所以,商店 A 的 SPSF = 10000000/20000

因此,商店 A 的 SPSF = 500 卢比/平方米。脚

为了用简单的语言解释上述结果,我们可以说,在 2018-2019 财年,为每平方英尺的面积存储一个生成的 500 卢比。衡量商店业绩是一个多么有趣的想法。

然而,我想强调一个重要的想法。所以,当你去商店时,一个典型的商店包括收银台、更衣室(如果是服装商店)、自动扶梯、电梯、步行区、展示区、储藏室等。现在,有人会说,自动扶梯或电梯所占据的空间不是我们为顾客购买产品的地方,因此这些空间对商店的整体收入没有贡献。我们姑且称这个空间为“非销售”空间。所以现在我们在同一个商场里有两种空间。一个展示实际产品的地方称为“”销售空间,另一个没有展示任何产品的地方(如收银台、电梯、自动扶梯、储藏室)称为“ ”非销售空间 ”。让我根据我的经验告诉你另一个事实。

这一“非销售空间”平均占总商店面积的 35–40%。

这意味着在 20,000 平方英尺的范围内。英尺面积,我们使用 13,000 平方英尺。英尺(65%)的面积。其余 7000 平方米。ft (35%)被占用在“非销售空间”下。

现在,如果我们修改上述计算中的值,仅考虑“销售空间”,那么我们得到商店 A 的 SPSF = 769.23 卢比/平方英尺。现在,下一个问题出现了,两者中哪一个是正确的?因为即使“非销售空间”不产生收入,它也是整个商店的一部分,因此应该包括在计算中。这是争论的话题。一些品牌认为“销售空间”是面积,而另一些品牌认为是“地毯总面积”。现在,我将遵循我的客户希望我遵循的(毕竟“客户是国王”)。在进行计算时,我们仅使用“销售空间”区域。这就是我们计算 SPSF 的方法。

结论

这篇文章的目的是给我的读者一个关于零售分析和一般分析的简要想法。本文的讨论只是冰山一角。一个更有趣的故事是,我们从不同的角度对数据进行分析,并收集模式以了解客户行为、品牌行为、商店布局、商品分类等。以及我们如何利用这些信息来增加 SPSF。但这是另一篇文章的主题。

请在评论区随意回复。你的回应激励我写更多。

快乐学习!

再来说说数据科学中的消极性!

原文:https://towardsdatascience.com/lets-talk-about-negativity-in-data-science-5cff57fa1990?source=collection_archive---------49-----------------------

“现实是由思想创造的,我们可以通过改变思想来改变现实.” —柏拉图

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

资料来源:gwendal 的 unsplash

数据科学中的消极!你在说什么?我听说这是 21 世纪最性感的工作之一,怎么会有负面影响呢?这些都是你看完文章标题后脑子里一定会蹦出的问题。

我是来澄清一切的。

嘿,伙计们,我带着另一篇激动人心的文章回来了,在这篇文章中,我将揭开数据科学的一些秘密。

目录:

  1. 什么是数据科学?
  2. 它为什么受欢迎?
  3. 它有哪些好的方面?
  4. 它在哪些方面有一些负面性?
  5. 结论。

什么是数据科学?

数据科学是一个跨学科领域,涉及各种科学方法、数据处理、算法、优化等。从数据中挖掘出洞察力。

当哈佛商学院称这是 21 世纪最性感的工作之一时,它受到了极大的欢迎。随着互联网接入的增加和数十年来数十亿兆字节数据的产生,计算能力的增强给了它更多的发展动力。软件工程这个最受欢迎的技术领域被推到了更低的位置,被数据科学所取代。有趣的是,现在越来越多的软件开发人员转向数据科学,以获得更高的职业安全感。

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

来源: unsplash

为什么它如此受欢迎?

随着越来越多的企业期望更好地了解他们的客户,通过学习他们的数据来了解他们的选择和要求,数据科学在行业中变得如此受欢迎。在对数据进行一些分析并使用各种算法进行一些未来预测之后,我们可以从数据中获得信息。

商业公司现在已经开始越来越多地投资于公司数据基础设施,这使得对数据从业者的需求越来越多,同时招聘门槛也在提高。

由于巨大的平均工资,人们现在越来越关注 it,认为这是一个安全的职业选择,而不认为他们能够提供该领域所需的东西。

它有哪些好的方面?

正如我已经强调的那样,利用数据,公司已经开始更多地关注他们的客户群,以了解他们的行为并扩大他们的覆盖范围。

由于这一切,我们可以得到个性化的建议,你管等。根据我们在平台上观看的内容,这使得客户越来越有吸引力。

数据除非转化为信息,否则就是一种浪费。数据科学从业者就是这么干的。

我不会在这部分写太多,因为这会让这篇文章失去真正的目标。

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

来源:Kylejglenn 的 Unsplash

它在哪些方面有一些负面性?

  1. 并非所有的数据科学项目都能完成。由于可用数据较少,或者算法给出了错误的预测,很多研究都流产了。
  2. 非技术主管认为数据角色的申请人应该知道一切。一切都意味着一大堆新技术,比如 Hadoop、Spark、Pig、Hive、SQL、MySQL、Scala、Tensorflow、A/B 测试、NLP Python、R 以及一切与机器学习相关的技术。但事实并非如此。
  3. 数据科学家在一个项目中只使用了他们所知道的所有工具和技术的 20%。其余的很少使用。
  4. 参与分析的人应该有一种实验性的思维方式,领域知识是必须的。但是这个领域的 noobies 并不太关心这个。他们只是在学习了一些工具后就自称为数据科学家,我认为这不好。
  5. 数据科学的工作不容易找,招聘参数一天比一天大。
  6. 并不是说每次我们都有机会接触到所有必要的数据来做出洞察。隐私问题就出现了。
  7. 我们在每一步都要考虑我们使用的数据是否侵犯了客户的隐私,这让工作变得更加繁琐。
  8. 作为一个新的领域,每天都有新的算法、新的技术和工艺出现,考虑到日常的项目工作,更新自己并熟练掌握它们是有点乏味的。
  9. 数据科学不仅仅是寻找见解,它还包括将我们的发现传达给相关的利益相关者,这些非技术人员可能会有点烦人,以防他们无法理解思维过程,这可能会导致项目流产。
  10. 数据从业者的每一个决定都会让公司前进,但一个错误的决定会让曲线急剧下降。因此,巨大的角色伴随着巨大的责任。
  11. 有时不知道一个模型的错误预测会造成什么后果,他们盲目地跟随他们的预测结果。

结论

总之,我会说这个领域没有不好的。只是一个人必须意识到这个领域的一切是如何进行的。应该采取什么样的思维方式,才能做到这一点,我们在心理上是否有足够的能力?。我们不应该仅仅因为市场上的巨大需求而选择任何领域。我们应该做一些我们有能力做的事情。

谢谢你

让我们来谈谈投资组合

原文:https://towardsdatascience.com/lets-talk-about-portfolios-d2d02f3c1ffd?source=collection_archive---------42-----------------------

它们是什么,它们不是什么,以及为什么你应该专注于弄脏你的手

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

凯利·西克玛在 Unsplash 上的照片

投资组合这个词曾经让我害怕。听起来那么专业,高不可攀。我不知道到底对我有什么期望。我想我必须让我的项目看起来非常时尚和完美。我认为它必须包括在数据科学中有某种突破或新想法的项目。我认为,我首先必须作为一名数据科学家专业地工作,才能拥有一个投资组合。我想,也许如果我不为客户或在专业环境中做项目,它们就不重要。互联网上大多数关于找工作的建议都提到要有一个投资组合,但这并没有让事情变得更好。

我很确定,作为一名有抱负的数据科学家,你每隔一天就会听说拥有一个投资组合的重要性。但是没有理由对此感到焦虑。我们来谈谈投资组合。

投资组合只不过是你工作过的东西的集合

不要被这个词本身淹没。人们喜欢用花哨的词语,而 portfolio 是一个花哨的词语,用来表示你的作品的集合。它是你努力、思考过的事情的集合。任何能说明你到目前为止学到的东西和你想到的聪明的解决方法的东西。

你的工作不一定要专业。不一定要有利益相关者。从雇主的角度考虑一下。在他们雇佣某人之前,他们希望能够看到一些证据,申请人知道些什么。Python 可能是你在简历中提到的技能之一,但你能展示一段 Python 代码吗?你的求职信可能会说你完成了五门在线课程,但你能展示一个你自己分析数据并训练机器学习算法的项目吗?

雇主大多只是想看到一些证据。你的作品不一定要前沿或完美。它只需要在某个地方,他们可以看到它,并透过它看。

你如何制作投资组合?

你要做的就是选择一个可以有效呈现作品的平台。一些流行的平台是:个人网站/博客,GitHub 账户,媒体博客。

无论你选择何种形式或平台来展示你的作品,你都需要涵盖几个要点。讨论

  • 你决定用你的项目解决的问题,
  • 你使用的数据,
  • 数据的问题以及你是如何解决的,
  • 你得到的结果和它们对你的问题的意义。

你可以包括图表和图形,但它真的不一定要装饰完美,你的投资组合才重要。重要的是内容。

最后,您希望展示您了解主要的数据科学概念,您知道如何处理问题,您知道如何避免潜在的陷阱,并且您可以为潜在的问题想出创造性的解决方案。

不要因为人们发布的惊人的投资组合而感到紧张。把自己和已经有几年专业经验的人相比是没有用的。一旦你开始工作,收集项目就容易多了。你会成功的。第一件事是找到一份工作,要找到工作,你需要专注于学习和展示你所学到的东西。

专注于把事情做好

你知道什么是最好的投资组合吗?存在的那个。重要的是把你的手弄脏。这不是我的新建议。我真的认为你越早开始做项目越好。因为这是你从在线课程和书籍中获得理论知识的基础。

尽管反复试验需要时间。独自开始一个项目并努力完成它可能会有些低效。在你身边有一个人可以帮助你在决策点上做出好的选择,指出你的错误,并暗示你接下来应该学习什么,这很有帮助。

当我第一次涉足数据科学时,我没有这样的人。因此,我花了相当多的时间来弄清楚如何制定一个适当的数据科学项目,需要注意什么,如何决定算法和许多其他事情……幸运的是,我有一个实习,给了我足够的空间和时间来通过试错学习东西。然而,并不是每个人都有充裕的时间来开始自己的项目。

我正在研究能帮你解决这个问题的东西。有了它,您将能够从头到尾了解一个数据科学项目是如何完成的,并准备好开始您自己的项目,这些项目将构成您的投资组合。我将很快公布更多的细节。敬请关注更新!

与此同时,想想你喜欢做、看或阅读的事情。你能想出一个关于他们的项目吗?如果可以,把它们写下来,当你准备好了,你可以做一个关于你感兴趣的项目,向你的下一任雇主展示你的技能。

👉对数据科学领域以及如何开始学习感到困惑? 免费参加数据科学入门迷你课程

让我们谈谈测试驱动的开发

原文:https://towardsdatascience.com/lets-talk-test-driven-development-c73551ca2871?source=collection_archive---------40-----------------------

干净的代码

它的意思是通过在“如何”之前关注“什么”来支持你。

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

照片由凯·皮尔格Unsplash 上拍摄

许多程序员认为在编写代码之前编写测试的想法是荒谬的。他们认为这是没有用的,并减缓了开发过程。从某种意义上说,这是正确的,它确实影响了发展的速度。但是如果你的系统没有弹性,那么开发的速度就没什么关系了。

开发人员的工作是交付不仅实用,而且可读和可维护的代码。测试驱动的开发可以帮助你做到这一点。

根据 Martin Fowler 的说法,TDD 是:

  • 为您想要添加的下一个功能编写测试。
  • 编写功能代码,直到测试通过。
  • 重构新旧代码,使其结构良好。

TDD 最重要的一个方面是它将焦点从如何转移到问题的什么上。

让我们编码

我们将把 TDD 应用到面试中普遍被问到的一个问题上,并尝试提出一个解决方案。这个问题叫做反向波兰符号

在逆波兰记法中,运算符跟在它们的操作数后面;例如,要将 3 和 4 相加,可以写成 *3 4 +* 而不是 *3 + 4* 。如果有多个操作,操作符在第二个操作数后立即给出;因此,在传统符号中,表达式被写成 *3 − 4 + 5* ,而在逆波兰符号中,表达式被写成 *3 4 − 5 +* :首先从 3 中减去 4,然后加 5。

我们将把问题分成更小的步骤,并思考每一步期望我们做什么。我们稍后将考虑“如何”。用来求解的语言是 Java。

测试 1

我们的起始状态是一个输入字符串:3 4 +

我们想要实现的是对每个 char 进行控制,以便我们可以对其进行操作。所以我们想从一个字符串中得到一个字符串数组。

我们的测试将如下所示:

[@Test](http://twitter.com/Test)
public void removeSpacesFromTheString() {
        ReversePolishNotation rpn = new ReversePolishNotation();
        String[] result = rpn.getStringArray("3 4 +");
        assertEquals("3", result[0]);
        assertEquals("4", result[1]);
        assertEquals("+", result[2]);
    }

一旦我们有了确定我们需要什么的测试,我们将考虑如何去做。将字符串转换成字符串数组非常简单。

public String[] getStringArray(String s) {
        return s.split(" ");
    }

测试 2

我们的第一个测试及其实现已经准备好了。让我们看看下一步我们想要什么。我们希望将运算符应用于我们遇到的数字。

所以在这种情况下,我们想把两个数相加。

[@Test](http://twitter.com/Test)
public void addNumbersWhenPlusOperatorIsFound() {
        ReversePolishNotation rpn = new ReversePolishNotation();
        double result = rpn.evaluate("3 4 +");
        assertEquals(7.0, result, 0.1);
    }

因此,我们需要一种方法将运算符应用于我们的数字。因为我们只有两个数,我们可以把它们相加。

public double evaluate(String s) {
        String[] elements = getStringArray(s);
        double result = 0.0;
        for (int i = 0; i < elements.length; i++) {
            String c = elements[i];
            if (c.equals("+") && i >= 2) {
                result = parseDouble(elements[i - 1]) + parseDouble(elements[i - 2]);
            }
        }
        return result;
    }

我们迭代数组,并添加我们遇到的数字+

测试 3

现在让我们通过在字符串中添加多个+操作符来增加趣味性。我们的测试会失败,因为它是硬编码的。对于输入5 5 2 + +,我们的实现会失败。

我们希望我们的函数返回这个字符串5 + (5 + 2)的结果。我们的代码应该这样评估。

[@Test](http://twitter.com/Test)
public void evaluateWhenMultiplePlusOperatorsAreFound() {
    ReversePolishNotation rpn = new ReversePolishNotation();
    double result = rpn.evaluate("5 5 2 + +");
    assertEquals(12.0, result, 0.1);
}

要做到这一点,我们需要想出一种方法,使用某种数据结构来处理运算符和数字。在这种情况下,我们可以使用一个Stack来推动数字,直到我们找到一个操作符,并通过弹出最后两个值来应用它。

public double evaluate(String s) {
        String[] elements = getStringArray(s);
        Stack<Double> numbers = new Stack();
        double result = 0.0;
        for (int i = 0; i < elements.length; i++) {
            String c = elements[i];
            if (c.equals("+") && i >= 2) {
                result = numbers.push(numbers.pop() + numbers.pop());
            } else {
                numbers.push(Double.parseDouble(c));
            }
        }
        return result;
    }

测试 4

下一步是确保我们能够应用所有的四个操作符,这现在非常简单。我们只需要检查不同的操作符,并相应地应用它们。

[@Test](http://twitter.com/Test)
public void addNumbersWhenMinusOperatorIsFound() {
    ReversePolishNotation rpn = new ReversePolishNotation();
    double result = rpn.evaluate("5 5 2 + -");
    assertEquals(2.0, result, 0.1);
}[@Test](http://twitter.com/Test)
public void multiplyNumbersWhenMultiplyOperatorIsFound() {
    ReversePolishNotation rpn = new ReversePolishNotation();
    double result = rpn.evaluate("5 5 2 + *");
    assertEquals(35.0, result, 0.1);
}

我们可以跳过一步,为所有操作符实现该方法。它也会处理乘法和除法。

public double evaluate(String s) {
    String[] elements = getStringArray(s);
    Stack<Double> numbers = new Stack();
    double result = 0.0;
    for (String c : elements) {
        switch (c) {
            case "+":
               result = numbers.push(numbers.pop() + numbers.pop());
               break;
            case "-":
               result = numbers.push(numbers.pop() - numbers.pop());
               break;
            case "*":
               result = numbers.push(numbers.pop() * numbers.pop());
               break;
            case "/":
               result = numbers.push(numbers.pop() / numbers.pop());
               break;
            default:
                numbers.push(Double.parseDouble(c));
                break;
        }
    }
    return result;
}

最后试验

一切正常,似乎我们已经达到了我们的最终结果。我们来测试一下大输入10 6 9 3 + -11 * / * 17 + 5 +。输入包含多个运算符和负数。

[@Test](http://twitter.com/Test)
public void evaluateWhenAllOperatorAreFound() {
    ReversePolishNotation rpn = new ReversePolishNotation();
    double result = rpn.evaluate("10 6 9 3 + -11 * / * 17 + 5 +");
    assertEquals(21.5, result, 0.1);
}

我们在这一点上的实现失败了。这有点令人惊讶,因为它应该已经工作了,但似乎操作符\的工作方式与+*不同。让我们更改实现来处理这个问题。

public double evaluate(String s) {
    String[] elements = getStringArray(s);
    Stack<Double> n = new Stack();
    double result = 0.0;
    for (String c : elements) {
        switch (c) {
            case "+": {
                result = n.push(n.pop() + n.pop());
                break;
            }
            case "-": {
                double fNumber = n.pop();
                double sNumber = n.pop();
                result = n.push(sNumber - fNumber);
                break;
            }
            case "*": {
                result = n.push(n.pop() * n.pop());
                break;
            }
            case "/": {
                double fNumber = n.pop();
                double sNumber = n.pop();
                result = n.push(sNumber / fNumber);
                break;
            }
            default:
                n.push(Double.*parseDouble*(c));
                break;
        }
    }
    return result;
}

优势

我们已经找到了最终的解决方案。花点时间理解这一点。在我们开始实现算法之前,焦点总是在我们期望从算法中得到什么。TDD 的优势是真实的:

  • 你写出更好的软件。
  • 你避免过度工程化。
  • 引入新功能时,您会受到保护。
  • 你的软件是自我记录的。

如果您想了解如何在解决方案中消除切换阶梯,您可以阅读这篇文章。

[## 如何摆脱 If-Else 阶梯

使用高阶函数和 HashMaps 编写干净代码的简单方法

levelup.gitconnected.com](https://levelup.gitconnected.com/how-to-get-rid-of-if-else-ladder-b70f36cd834d)

最终想法

我试图解释为什么我们应该使用测试驱动开发。有更好的文章可以帮助你理解如何去做。其中一个是这里的。TDD 实际上是一种设计技术。TDD 的基础集中在使用小型测试以紧急的方式从头开始设计系统。

一开始可能看起来很慢,但是通过练习,你会获得动力。

我希望这有助于您理解 TDD 背后的原因。

给年轻诗人的信

原文:https://towardsdatascience.com/letters-to-a-young-poet-translating-advice-given-by-an-artist-into-lessons-for-data-scientists-f1fce5025123?source=collection_archive---------64-----------------------

20 世纪初一位作家的建议对于今天的数据科学家来说是珍宝

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

jules a. 在 Unsplash 上拍摄的照片

啊,不知道该如何对待我们的生活。它超越了年龄和文化。它让我们梦到一张导游图。这不是什么新鲜事…

1902 年至 1908 年间,赖内·马利亚·里尔克,一位放荡不羁的奥地利诗人,写了十封信给弗兰茨·卡普斯,一位 19 岁的 T4 特里萨军事学院的军官学员。雷纳本人曾在同一所军事学院学习,但选择退出军事生涯。现在,弗兰兹正试图决定是否从事文学事业,并就他的诗歌质量征求意见。

1929 年,莱纳去世 3 年后,弗朗兹决定出版他的信件。

这些信充满了智慧,虽然诗歌和数据科学并不完全相同,但雷纳给弗朗兹的一些建议可能是迈克尔·乔丹(不是 NBA 乔丹)给安德鲁·吴或约舒阿·本吉奥的。

[## 给年轻诗人的信

www.goodreads.com](https://www.goodreads.com/book/show/46199.Letters_to_a_Young_Poet?ac=1&from_search=true&qid=QFkkdOCd5n&rank=1)

1.你不会完全明白的。这没关系。

并非所有事情都像人们想象的那样容易解释。而有些事情根本没有解释。我们感到奇怪的感觉。我们会有奇怪的想法。我们的生活如此广阔,包含了大量的经历,我们根本无法理解所有的经历。

这没什么,Rainer 说,我们必须有足够的勇气去承认和接受它。否则,我们可能无法接触到新的、未知的事物。这是有后果的。

例如,我们的个人关系可能会变得单调。某些动力在一段关系发展的早期就已经形成。除非我们做到以下几点,否则这些不会改变:

  1. 积极地、有目的地发展不同的动态;
  2. 接受结果不确定,愿意应对不可预知的事情;

关于我们通过数据科学和机器学习的旅程也是如此。这是一个广阔的领域,拥有庞大的知识体系,分支到许多子主题,每个子主题都有自己的世界。我们不能简单地理解这一切。此外,当旧的方法不起作用时,我们必须积极调整我们的方法以适应新的挑战。

承认我们不明白的事情是我们成长的一步。在我们的头脑中有一些没有答案的问题并不是什么坏事,而是我们确实在思考这个问题的一个信号。其实有些事情谁都不理解。同样,我们的一些理解也可能是错误的。这是说你不是唯一不理解事物的人。我们都是人。保持一个初学者的心态,并不断质疑你所学到的东西。

“未来取决于某个对我所说的一切深感怀疑的研究生。”—杰弗里·辛顿

2.慢下来,自省。

内在自我有很多知识要分享。但是要学,一定要听。倾听来自内心的声音。Rainer 说,我们的感觉可能是对的。如果不是,内在的自我会慢慢引导我们得出新的结论。没必要着急。我们必须让我们的观点和道德价值观以自然的速度发展。我们必须让他们成熟。

内在的自我不会大声说出来,对莱纳来说,只有一种方式能够倾听它:我们必须独处。孤独是很难的。这太难了,为了避免它,我们愿意做任何其他的事情,不管它是多么的平庸或者毫无意义。我们不得不反对这种便利和舒适。

雷纳让我们想象我们的存在是空间。我们大多数人只知道这个空间的一角。这是靠近窗户的安全角落。为了了解我们自己,我们必须探索整个空间,不要害怕可能存在的陷阱和鸿沟,因为如果它们存在的话,它们是我们的陷阱和鸿沟,是要我们去发现的,而不是其他的。只有通过探索,我们才能成长,变得自由自在。

在这样一个快速发展的领域,比如我们,很难放慢脚步。在这样一个联系紧密的社区里,很难独处。有太多的声音在大声呼喊我们的道路应该是什么样子,成功的定义是什么,以至于很难听到来自内心的胆怯而低沉的声音。

在我们的旅途中,我们必须对我们消费的信息有所选择。这个选择应该包含我们自己的想法和感受。

慢下来并反省有助于获得看待事物的新视角。我们自己的观点。成功(无论这对你意味着什么)意味着寻找我们在这个领域的动机。你可能还不认识他们。

没关系。很少有人知道。

我不是那种人。

所以我继续寻找和探索,并相信这种寻找会让我到一个更好的地方,因为它会帮助我发现我的内部个人空间 Rainer 说。希望你正在揭开你的秘密。

这些教训虽然简单,但实施起来不一定容易。他们需要专注的能力和抵抗外力的力量。

从这本书里有很多可以带回家的教训,它是另一个例子,说明我们如何能够/应该超越我们的领域,以找到有意义的见解,帮助指导我们的旅程。

感谢阅读🙏希望你能从这些课程中找到价值。

用谷歌的公共数据集升级

原文:https://towardsdatascience.com/level-up-with-googles-public-datasets-5ffce0893ea0?source=collection_archive---------56-----------------------

将 Jupyter 笔记本电脑连接到万亿字节的数据

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

瓦西里·科洛达在 Unsplash 上的照片

我记得我的第一个数据科学项目,分析一万部电影的 6.5MB 文件。从几个击键的数据中快速找到模式是很神奇的,很快我就开始寻找其他数据集进行分析。通过 Kaggle 并最终通过网络爬行产生独特的数据,我发现大多数可下载的数据集都很小(<1GB) and that collecting and working with large datasets required a different type of skill: data engineering.

Most aspiring data scientists only know how to analyze clean, comma separated files that fit on their RAM (usually <8GB). In practice, data science is much more unpredictable when you deal with terabytes of data in different formats from different data streams. So how does an aspiring data scientist gain exposure to big data?

To take you to big data, we will explore:

  1. Diving into Big Data with Google Cloud Public Datasets
  2. What is BigQuery?
  3. How to Connect Your Jupyter Notebook to BigQuery

Diving into Big Data with Google Cloud Public Datasets

It turns out that Google has a repository of most publicly available data such as [空气质量](https://console.cloud.google.com/marketplace/product/openaq/real-time-air-quality?filter=solution-type:dataset&q=air quality)、美国人口普查Reddit航班)。如果有一个公共数据集,谷歌可能会托管它,供你查询。更重要的是,新的数据集(即新冠肺炎)不断被添加和更新。

有了 BigQuery 上托管的数据,您可以轻松地查询数据,看看它是否有趣。例如,我可以查询并回答这个问题:“谷歌上有多少针对佛罗里达州女性的政治广告活动?”

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

探索谷歌公共数据集上的其他可用数据集!

什么是 BigQuery?

BigQuery 是 Google 的无服务器数据仓库。获取数据很容易,因为每月第一个 1tb 的查询是免费的。正如一位 Spotify 工程师所说:

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

我喜欢 BigQuery 的是它的速度。将它的速度与超过 100 个公共数据集的存储库结合起来,我们可以快速分析数据,以确定它是否值得分析。

由于数据集托管在同一个数据仓库中,我们可以连接两个公共数据集来进行唯一的分析。例如,我们可以根据天气预报来预测对纽约出租车的需求。谷歌甚至为此写了一篇不错的博文:如何用谷歌大查询、公共数据集和 TensorFlow 预测需求

如何将您的 Jupyter 笔记本连接到 BigQuery

既然我们已经找到了想要在 BigQuery 上分析的数据,让我们把它带到本地 jupyter 笔记本环境中。我们可以利用 BigQuery 的 API 将数据加载到 dataframe 中。

第一步是安装 BigQuery 客户端库,可以使用 pip 或 conda 来完成。

pip install --upgrade google-cloud-bigquery

或者

conda install -c conda-forge google-cloud-bigquery

接下来,我们需要为我们的 jupyter 笔记本创建一个服务帐户密钥,以便在 Google Cloud 上使用和验证。

  1. 在云控制台中,转到创建服务帐户密钥页面
  2. 从服务帐户列表中,选择新建服务帐户。
  3. 在“服务帐户名称”字段中,输入一个名称(即 pythonBigQuery)
  4. 从角色列表中,选择项目>所有者。您可以稍后使用云控制台查看和更改此字段。如果您正在开发生产应用程序,请指定更精细的权限。
  5. 单击创建。一个 JSON 文件,包含下载到您计算机的密钥

下载 JSON 密钥后,我们可以验证 jupyter 笔记本以连接到 BigQuery。我们导入操作系统库,将我们的 Google 凭证设置为下载的密钥。如下面的笔记本所示,我现在可以将 BigQuery 表作为 dataframe 查询和检索,其中列名和数据类型都是从该表继承的!

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

df . head()for big query-public-data . baseball . schedules

Google 官方文档: BigQuery API 客户端库

结论

谷歌公共数据集是探索大数据的良好开端。利用云计算和仓储,我们可以在几秒钟内探索万亿字节的数据。有了本地支持的 API,我们可以轻松地将 BigQuery 上的数据集成到我们的 jupyter 笔记本中!

R 中带半连接的升级

原文:https://towardsdatascience.com/level-up-with-semi-joins-in-r-a068426096e0?source=collection_archive---------31-----------------------

变异连接和过滤连接的区别

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

图片由 inmorino 来自 Pixabay

介绍

假设您已经对其他更常见的连接类型(内、左、右和外)有了一些了解;添加 semi 和 anti 可以证明非常有用,可以节省您原本可以采取的多个步骤。

在这篇文章中,我将只关注半连接;也就是说,semi 和 anti 之间有很多重叠,所以准备好了解一下这两者。

过滤连接

半连接和反连接与我刚才强调的其他四个有很大的不同;最大的区别是它们实际上被归类为所谓的过滤连接。

从语法上看,它与任何其他连接都非常相似,但其目的不是用额外的列或行来增强数据集,而是使用这些连接来执行过滤。

过滤连接不是通过添加新的信息列来分类的,而是有助于保留或减少给定数据集中的记录。

半连接

使用半连接的目的是获取一个数据集,并根据某个公共标识符是否位于某个附加数据集中对其进行过滤。

一个很好的方法就是编写替代方案。

机会数据集示例

假设我们有一个来自 salesforce 的数据集,其中包含我们已经处理或正在处理的所有交易或机会。

这个机会数据集为我们提供了许多关于交易本身的非常有用的信息。让我们假设它看起来像这样:

| opp_id | account_id |创建日期|结束日期|金额|阶段|

现在,假设我们需要过滤该数据集,以便只包括企业客户。碰巧的是,我们的机会数据集中没有可用于筛选的细分字段…我们必须利用其他地方的信息。

让我们假设企业帐户被跟踪的唯一位置是在一个随机的 excel 文件中。假设数据集看起来像这样:

|帐户标识|客户细分|

在一个没有半连接的世界里

根据我们现在对左连接的了解,我们可以做以下事情:

opportunities %>%
left_join(enterprise_accounts, by = 'account_id')%>%
filter(!is.na(customer_segment))

如您所见,我们可以将企业客户数据集与我们的主 opps 数据集左连接,如果没有匹配值,客户细分将为空,因此您可以添加一个筛选器语句,说明您只需要非空的案例。

这很好,并且有效地执行了我上面解释的相同功能。一件烦人的事情是它给了你一个新的字段,customer_segment,它对每条记录都是一样的。

之后,我们还可以添加一条 select 语句来提取该字段,这只是增加了另一行代码,您可以编写这些代码来实现该功能。

opportunities %>%
left_join(enterprise_accounts, by = 'account_id')%>%
filter(!is.na(customer_segment))%>%
select(-customer_segment)

假设您已经学习了内部连接,我们也可以用稍微简单一点的代码实现类似的功能。

opportunities %>%
inner_join(enterprise_accounts, by = 'account_id')%>%
select(-customer_segment)

使用半连接简化

现在让我们用一个半连接来进一步简化事情。

opportunities %>%
semi_join(enterprise_accounts, by = 'account_id')

这将使我们得到与上面每个例子完全相同的输出。它将筛选出在企业客户表中没有匹配 account_id 的机会记录。它不会向数据集中添加列或行。它专门存在,并用于过滤目的。

结论

现在,在短短的几分钟内,我们已经介绍了很多内容,并提供了一些 dplyr 功能,可以简化您的代码和工作流程。

我们了解到:

  • 变异连接和过滤连接之间的区别
  • 如何在没有半连接的情况下执行“过滤连接”
  • 半连接的特定输出和意图
  • 如何使用半连接

我希望这能对你作为数据专家的日常工作有所帮助。

祝数据科学快乐!

提升你的代码

原文:https://towardsdatascience.com/level-up-your-code-e1424fff031d?source=collection_archive---------45-----------------------

编写干净、高质量代码的 5 个简单步骤

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

作者使用 Canva 拍摄的图片

“任何傻瓜都能写出计算机能理解的代码。优秀的程序员会写出人类能理解的代码。”马丁·福勒

颂歌不总是程序员和计算机之间的对话;事实上,它通常是一组开发人员一起工作或单独工作来构建一个工作产品。通常,编写一段有效的代码并不是唯一的目标;相反,它是编写一段干净、可读、有效的代码。

什么是“干净代码”?

Clean code 是一种以读者为中心的代码编写风格,可以生成可读性强、易于维护的代码。编写不需要太多解释的干净代码(如果有的话)被认为是艺术。程序员通常在意识到他们编写的代码不仅仅是计算机要执行的代码后就开始编写干净的代码;其他人也可以阅读、扩展或构建它。编写干净的代码是每个专业程序员都应该努力获得的技能,这不是一件容易的事情,但最终,这绝对是值得努力的。

为什么干净的代码很重要?

在很多情况下,糟糕的代码会导致大公司和优秀产品的失败,如果他们的内部代码写得很清楚,这些产品会很棒。尤其是在今天,如果一个产品或应用程序运行不正常,公司可能会损失数百万美元的利润,更不用说客户和时间损失了。干净的代码,使任何代码库的开发和部署过程高效和顺利。

干净代码是包含以下特征的高质量代码:

  • 可读性: 可读代码是一个编程新手和一个专业开发人员都能同等理解的代码。这是一种理解和使用起来并不耗时的代码。
  • 可维护性: 如果代码写得很好,那么测试、发现 bug 并为每个从事代码基础工作的人修复它们就更容易了。
  • 可伸缩性: 任何成功的产品都可能需要可伸缩性来保持成功,如果代码库是稳定的、干净的、写得好的,那么可伸缩代码和在其上扩展的过程将会更加简单。

编写干净的代码

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

作者使用 Canva 拍摄的图片

尽管“干净的代码”这个短语可能是主观的,我的意思是,并不是我们所有人对什么是干净的代码都有相同的理解。但是,可以使用一些技术来使代码看起来更好,读起来更舒服,伸缩更流畅。以下是我从 9 年多的代码编写经验中学到的 5 个步骤,教你如何在编写代码时遵循这些步骤,这将有助于你的代码更加整洁和高质量。

样式和格式

想想写任何一行代码,就像用英语或者其他口语写一个句子一样,长而复杂的句子更难理解;你可能需要看两遍或更多遍才能完全理解。代码也是如此,尽量让你的代码简洁明了,避免那些你认为会让你看起来像个编程巨星,却让其他人看不懂的超级复杂的语法。您还应该关心样式,这意味着编写的代码对于人眼来说很容易理解。这里有一个 Python 中的例子,说明了样式和格式是如何产生巨大影响的。

代替这个:

写这个:

今天几乎所有的编辑器都有短绒来帮助你写一个风格和格式都很好的代码。

Linters 是 IDE 的插件,可以帮助你发现小错误。例如变量名中的拼写错误、忘记了右括号、Python 中不正确的跳转、调用带有错误数量参数的函数。它们还可以帮助你处理风格不一致和危险的逻辑,这些会让你的代码看起来不太好。

命名

命名是编写干净代码的重要方面之一。确保您的方法、变量和其他自定义定义的名称是自描述的,并且易于理解,这是非常有益的,不仅对于那些将与您的代码进行交互的人,甚至对于作为代码作者的您也是如此。您会发现以后编辑和扩展会更容易。以下是一些帮助我提高代码可读性的命名技巧:

  • 使用可以发音的名字。避免那些只会引起混乱的奇怪的名字。
  • 不要在代码(函数或类)的各个位置用不同的词来指代同一个动作,比如在指代同一个内存交互时同时使用 【保存】【存储】
  • 命名函数时使用动词,命名变量、常数和类时使用名词。

分解大块

当你写代码的时候,尽可能的简洁。不可能设置一个数字来表示正确的块大小。然而,肯定有一个临界长度。如果你觉得你的代码太混乱或太长,那么是时候重组和重构它,也许把它分成更小的单独的代码文件。

移除冗余

您的代码应该只包含对代码功能有贡献的行,仅此而已。如果你写了一个测试函数,然后又写了一个更好、更有效的版本,删除旧的,不要对它进行注释。这会使代码看起来混乱。此外,使用内部的内置函数,而不是创建自己的函数,这只会让你的代码毫无理由地变得更长、更复杂。

如果您发现自己有多个嵌套的条件语句或循环,请重新编写代码以避免冗余嵌套,您可以使用保护子句、早期返回或函数式编程的某些元素来实现这一点。

评论

养成对代码写注释的习惯是非常好的。这是使代码更加清晰的一个很好的方法。然而,他们不是来详细解释你的代码的,把这些留给文档吧。你的评论应该甜蜜、简短、切中要点。为了方便起见,请使用注释来强调以下几点:

  • 表达你对一个函数或一段代码的目标。
  • 警告代码中可能的异常或错误。
  • 强调函数或类的主要工作,或者代码的任何部分。

为了写出更好的评论,我总是提醒自己,评论不是来给人解释代码的;代码是用来向计算机解释注释的。

编写干净、高质量的代码不是一件容易的事情;这很有挑战性,好的方面是,这是可行的,只是需要练习。然而,有时编写干净的代码并不是一个选项或者是一个非常棘手的选项!

那是什么?

只要尽你所能让代码尽可能的干净和可读,记住,写代码是一种艺术,所以写一些让你自豪的艺术,人民会喜欢阅读。

用 Python decorators 提升你的代码

原文:https://towardsdatascience.com/level-up-your-code-with-python-decorators-c1966d78607?source=collection_archive---------17-----------------------

日志记录、类型检查、异常处理等等!

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

由 pexels 上的 kaboompics

在每一个 Python 用户的生活中,都会有一个阶段,你可以从写好代码提升到伟大的代码。

一旦你掌握了 Python 的核心功能,比如列表理解和三元运算符,你就应该准备好编写更具可读性的 Python 了。装饰器是提升代码可读性的关键,这里我们将介绍它们的基础知识,以及使用它们的 3 种方法。

什么是室内设计师?

简而言之,装饰器是包装其他函数的函数。如果你在一个功能的开始和结束都想要一些东西,那么装饰者会让你的生活变得更容易。

装饰者可以被看作是函数定义前的一个@符号。你可能已经在一个 flask appclick CLI 中发现了它们,但是解释它们如何工作的最简单的方法是通过一个简短的例子来完成。

假设在函数的开始,我们想打印“开始”,在函数的结尾,我们想打印“完成”。为了实现这一目标,我们可以采取以下措施:

def circle_area(radius):
    print("Started: circle_area")
    area = 3.142 * radius ** 2
    print("Finished")
    return areaarea = circle_area(2)

这种方法是可行的,但是现在我们的代码充斥着打印语句。函数的实际内容可以只用一行来写,但是我们用了三行!因此,让我们通过创建一个包含我们操作的主要成分的新函数和另一个仅包含打印语句的函数来使这一点更清楚:

def circle_area(radius):
    return 3.142 * radius ** 2def circle_area_and_print(radius):
    print("Started: circle_area_and_print")
    area = circle_area(radius)
    print("Ended")
    return areaarea = circle_area_and_print(2)

乍一看,你可能会说这看起来并不清楚,因为我们比以前拥有更多的代码。乍一看,您可能会注意到我们添加的代码可读性更好。然而,我们的工作还没有完成,如果我们想从代码中得到更多呢?

比方说,我们也想在其他函数之前和之后打印。作为懒惰的数据科学家,我们不希望多次编写同一行代码,所以让我们尝试概括我们已经拥有的代码。我们可以用这个新的printer函数做到这一点。

def printer(function):
    def new_function(*args):
        print(f"Started: {function.__name__}")
        output = function(*args)
        print("Finished")
        return output
    return new_functiondef circle_area(radius):
    return 3.142 * radius ** 2area = printer(circle_area)(2)

那么printer函数在这里做什么呢?

这个函数的美妙之处在于,它构造了一个新函数,方法是在执行传递的函数之前和之后,将我们的原始函数添加到打印语句中。现在printer返回了新的函数句柄,允许我们获取任意函数并使用打印语句返回它。

这就是 Python 装饰器真正发挥作用的地方。现在我们已经编写了printer函数来返回原始函数的修改版本,我们需要做的就是在函数定义前加上@printer:

@printer
def circle_area(radius):
    return 3.142 * radius ** 2area = circle_area(2)

即使在这个简单的例子中,当您将 printer decorator 的使用与我们在开始时编写的代码进行比较时,我们的代码要清晰得多。

我还能用它们做什么?

装饰者有一些巧妙的技巧,可以让你的代码更容易理解和阅读。

我们来看看:

  1. 日志记录(类似于第一个例子,但更有用)
  2. 类型检查
  3. 错误处理

1.记录

对于第一个示例,我们需要在脚本中编写一个小函数来设置日志记录:

import loggingdef setup_logging(name="logger",
                  filepath=None,
                  stream_log_level="DEBUG",
                  file_log_level="DEBUG"):

    logger = logging.getLogger(name)
    logger.setLevel("DEBUG")
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    ) ch = logging.StreamHandler()
    ch.setLevel(getattr(logging, stream_log_level))
    ch.setFormatter(formatter)
    logger.addHandler(ch) if filepath is not None:
        fh = logging.FileHandler(filepath)
        fh.setLevel(getattr(logging, file_log_level))
        fh.setFormatter(formatter)
        logger.addHandler(fh) return loggerlogger = setup_logging(name="default_log",filepath="logger.log")

现在我们可以编写新的日志装饰器了:

def log_decorator(log_name):
    def log_this(function):
        logger = logging.getLogger(log_name)
        def new_function(*args,**kwargs):
            logger.debug(f"{function.__name__} - {args} - {kwargs}")
            output = function(*args,**kwargs)
            logger.debug(f"{function.__name__} returned: {output}")
            return output
        return new_function
    return log_this

这比我们之前看到的printer装饰稍微复杂一些。这一次,我们想要构建一个可以接受参数(记录器的名称)的装饰器。

然而装饰函数只能接受一个参数,所以我们将这个函数包装在另一个可以接受许多参数的函数中。你需要一段时间来理解这种类似于 inception 的函数包装,但是一旦你这样做了,它就是数据科学家工具箱中的无价工具。

2.类型检查

现在这是一个有争议的问题,所以抓紧你的帽子,我们可能会经历一段颠簸的旅程…

有些人会说这种修饰类型检查函数输入的方式被许多人认为是“非 Pythonic 化的”。Python 是一种动态类型的语言,所以冒着惹起太多麻烦的风险,重要的是要注意,一般来说,在编写 Python 时,我们应该请求原谅,而不是请求许可。

然而,如果你愿意对 Python 的法则有点厚脸皮,那么你会发现这是一个非常方便的工具,尤其是在开发代码的时候。当识别正在传递的错误类型时,它变得非常清楚。

记住所有这些,下面是代码:

def accepts(*types):
    def check_accepts(function):
        assert len(types) == function.__code__.co_argcount,\
            "Number of typed inputs must match the function inputs"
        def new_function(*args, **kwargs):
            for (a, t) in zip(args, types):
                assert isinstance(a, t), \
                       "arg %r does not match %s" % (a,t)
            return function(*args, **kwargs)
        return new_function
    return check_accepts@accepts((int,float))
def circle_area(radius):
    return 3.142 * radius ** 2

所以现在我们已经确保了circle_area函数的输入只接受类型intsfloats,否则它将引发一个AssertionError

3.错误处理

对于这个例子,让我们假设我们试图从一个 API 访问数据,但是这个 API 每分钟只允许给定数量的请求。我们可以编写一个装饰器来包装 API 调用,并继续尝试获取数据,直到成功。

import api
import time
API_WAIT_TIME = 5 #minutes
MAX_RETRIES = 10def error_handling(api_function):
    def trial(*args, num_retries=0, **kwargs):
        try:
            return api_function(*args, **kwargs)
        except api.error.RateLimitError:
            if num_retries > MAX_RETRIES:
                raise RuntimeError("Too many retries")
            else:
                msg = f"rate limit reached. Waiting {API_WAIT_TIME} minutes ..."
                time.sleep(API_WAIT_TIME * 60)
                return trial(*args, num_retries=num_retries + 1, **kwargs) return trial

每次我们从api模块请求数据时,我们都可以使用这个装饰器。装饰器将继续尝试,直到它获得数据或达到允许的最大重试次数,如果是这种情况,将引发一个RuntimeError

同样,这个函数的一个非常相似的版本可以用来任意捕捉不同的异常,并以不同的方式处理它们。我将让读者自己去思考使用这种装饰器的新方法。

我们学到了什么?

希望您现在对什么是 Python 装饰器有了更好的了解,并且有信心在您的代码库中使用它(如果没有,那么我让您失望了……)。

这里的关键是,如果你有一个函数经常出现在另一个函数的开头和结尾,那么装饰器将是你新的最好的朋友。装饰者将帮助你的代码不仅可读性更好,而且更加模块化和可重用。

提升你的朱莉娅词典

原文:https://towardsdatascience.com/level-up-your-julia-dictionaries-76f633ae2975?source=collection_archive---------41-----------------------

充分发挥 dict 数据类型的潜力!

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

(茱莉亚标志由http://julia-lang.org/提供))

D ictionaries 不仅是 Julia 中最有用的数据类型之一,也是 Python 和 Nimrod 等许多类似语言中最有用的数据类型之一。字典对于数据科学家来说是一个特别有价值的工具,一旦你意识到这一点,这一点就会更加明显

数据帧。JL 的数据框架只是字典。

字典经常被忽视,被视为相对简单的数据类型,只包含数组和键,但我认为这是一个错误。我认为这是一个错误,因为 Julia 字典非常强大,用途极其广泛,可以毫不费力地用于从数据帧到 API 返回的许多事情。

笔记本

句法表达

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

Julia 最酷的特性之一是能够使用语法表达式。这对于字典来说没有什么不同,因为您可以使用语法表达式用字典做一些非常酷的事情。这对于统计计算来说真是太棒了,因为它可以用一些非常简洁的语法提供一个简单且性能更好的选项。我个人喜欢使用矩阵乘法的语法表达式:

det2(A) = A[1,1] * A[2,2] * A[3,3] + A[1,2] * A[2,3] * A[3,1] + A[1,3] * A[2,1] * A[3,2] - A[3,1] * A[2,2] * A[1,3] - A[3,2] * A[2,3] * A[1,1] - A[3,3] * A[2,1] * A[1,2]

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

尽管我热爱矩阵,但我认为在字典上使用它的能力可能比在矩阵上使用它更有价值。我发现这种方法的一个很好的用途是在我目前正在开发的图形库内部,在那里我使用线程和字典索引进行迭代,而不是使用双重迭代。

这使得它快了很多。

获取()

为了证明使用这种方法的合理性,我将首先向您展示一个场景。假设我们刚刚使用 get 请求从 API 中提取了一堆数据,我们希望在脚本运行时持续提取这些数据,但不会监控这些脚本。在这种情况下,我们会想尽一切办法避免访问数据中不存在的键,因为那样会终止脚本并导致异常。

为了减轻这种情况,我们可以使用 get()方法为我们的脚本创建一个缺省值,以便在我们要搜索的索引不在字典中的情况下使用。该方法采用 3 个参数;我们的字典,exampdict,我们的键,在这个例子中是:a,以及我们的缺省值,如果在字典中找不到这个键,我们可以使用这个缺省值。

exampdict = Dict(:a => 5,:b => 7,:c => 8)
a = get(exampdict, :a, 0)

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

如您所见,即使:d 因为数据不在字典中而无法访问,我们仍然相应地得到了所有的值,以及 d 的默认值。

在()

使用 in()方法,我们可以更快地检查一个键或一对键。这将返回一个布尔值,并带有两个参数,我们想要搜索的键和我们想要搜索的字典。

in((:b => 8), exampdict)

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

过滤器()

由于 Julia 的多重调度,filter()方法可以用在字典键上,也可以用在其他任何地方。使用 filter(),我们基本上可以从数据框架中过滤掉任何可以表示为条件的东西。在这里,我结合条件来检查以字母 K 开头并且值小于 4 的键。

strdict = Dict("Orange" => 3, "Kiwi" => 2, "Kayak" => 5)
filter(tuple -> startswith(first(tuple), "K") && last(tuple) < 4, collect(strdict))

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

不用说,filter()当然是一个非常有用的方法!这种方法可以用于任何事情,从只从字典中获取特定的键到删除丢失的值和低于特定数字的值。

地图键

另一个从茱莉亚基地归来的帅魔是 map()。当然,map 在各种语言中都有使用,并且也证明了它的实用性。但是,在 Julia 中,我们可以映射字典的键和值,例如,我们可以映射所有的大写键:

map(uppercase, collect(keys(dict)))

这在许多情况下肯定是有用的,但在我看来肯定比 filter()强!

结论

在 Julia 中,你可以用字典做很多很酷的事情。在我看来,他们确实是经过深思熟虑的!Julia 的一个优点是,由于多态性,您可以在语言中使用的几乎每种类型上使用 Julia 的 10 个标准函数,这使得语言中的学习方法及其操作变得非常简单。希望这些提示有用,并派上用场,也许使用这些提示甚至会提高你的朱莉娅词典!

用 Tableau 提升你的 Kaplan-Meier 曲线

原文:https://towardsdatascience.com/level-up-your-kaplan-meier-curves-with-tableau-bc4a10ec6a15?source=collection_archive---------26-----------------------

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

来源: Unsplash

方便访问整个公司的生存分析!

之前的一篇文章中,我展示了我们如何使用 Python 创建卡普兰-迈耶曲线。尽管我热爱 Python 和编写代码,但可能有一些替代方法有其独特的好处。进入 Tableau!

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

来源

Tableau 是一个商业智能工具,用于在来自大量来源的数据基础上创建优雅的交互式可视化(你会惊讶地发现有这么多不同的来源!).为了使定义更简短,Tableau 用于构建仪表板。

那么,为什么数据科学家会对使用 Tableau 而不是 Python 感兴趣呢?当用 Python 创建一个包含生存分析练习结果的笔记本/报告时,读者将总是限于:

  • 视觉化图像的创造者在想什么,
  • 创建报告时有哪些数据可用。

换句话说,读者没有多少自由去探索其他的角度。此外,如果公司中有人在几年后偶然发现了该报告,使分析保持最新的唯一方法是找到数据科学家,让他们重新运行笔记本并生成另一份报告。绝对不是最好的情况。

这就是基于 Tableau(或其他商业智能工具,如 PowerBI、Looker 等)的解决方案。)闪耀。由于可视化是直接在数据源之上构建的,因此可视化将与数据一起更新。数据科学家的工作量减少了!

另一个额外的好处是可以包含一些过滤器,因此读者可以尝试探索不同的数据子集。根据经验,这是产品负责人经常使用的功能,他们希望深入了解细节,同时不希望不断地向数据人员提出新过滤器或功能的另一个请求。又赢了:)

最后,通过使用这样的工具,分析师使数据和分析的访问民主化,因为基本上公司中的任何人都可以访问仪表板,并尝试回答他们自己的问题或验证他们的假设。

在这个介绍之后,让我们直接进入重新创建我们在上一篇文章中创建的完全相同的卡普兰-迈耶曲线。我们再次使用电信客户流失数据集,在分析之前几乎不需要额外准备。如果你需要复习 Kaplan-Meier 估计量,请参考那篇文章,因为我们这次不讨论理论。此外,我们假设一些基本的 Tableau 知识。

: Tableau 是一个商业软件,需要许可证。您可以按照这里的说明获得 14 天的试用期。

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

图片来自 Pixabay穆罕默德·哈桑

方法 1:简单模式

第一种方法被称为 easy,因为它有利于速度和简单性,同时也带来了一些缺点。首先,我们从一个文本文件中加载数据(此处可用)。

为了在 Tableau 中进行生存分析,我们需要以下变量:

  • 事件发生时间-表示为从加入样本到发生感兴趣的事件或审查所经过的时间段(例如,几天或几个月)。
  • 感兴趣的事件-用二进制变量表示,其中 1 表示事件已经发生,否则为 0。
  • 附加分类变量-用于过滤和/或分组。

tenure变量不需要任何准备,因为它已经表示了自注册电信公司的服务以来的月数。但是 Churn 变量表示为是/否字符串,因此我们需要使用计算字段将其编码为二进制:

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

要创建该字段,右击左侧变量选择器中的Churn变量(数据选项卡),选择创建- >计算字段。

下一步,我们将创建一个新的计算字段d_i,它表示一段时间内发生的事件数量:

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

我们使用的变量名称对应于 Kaplan-Meier 估计量公式中的元素。

我们创建的下一个变量将是在给定时间用于计算风险函数的分母。它表示自上一个时间段以来的观察总数:

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

正如您可能已经猜到的,变量Number of Records是一个用于统计观察值的辅助变量。为此,较新版本的 Tableau 基于数据源的名称创建一个变量。然而,您可以通过创建一个计算字段并将1放入字段定义中来轻松地手动创建这个变量。最后,我们将卡普兰-迈耶曲线定义为:

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

更正:图片中的公式应该写明 PREVIOUS _ VALUE(1)*(1-[d _ I]/[n _ I])。

在这里,生存的概率被定义为1 - hazard function

所有的积木都准备好了。现在,我们将tenure放在 x 轴上,将Kaplan-Meier Curve放在 y 轴上,将曲线格式化为百分比,添加图块并将PaymentMethod变量放置为颜色。这样,我们创建了以下可视化:

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

这与我们上次使用lifelines获得的结果非常相似:

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

一些快速观察:

  • Tableau 中获得的存活曲线或多或少是直的,没有特征性的阶梯结构,
  • 没有置信区间,因为它们的计算没有 Tableau 那么简单。

使用 Tableau,我们可以很容易地向可视化添加一些额外的过滤器,如群组日期、年龄或任何可用的分类变量。

方法#2:正常模式

在这种方法中,我们将着重于再现卡普兰-迈耶曲线特有的阶梯状形状。这种方法被称为正常模式,因为它需要更多的准备。

对于附加的数据预处理,我们需要完成两个步骤。首先,在包含电信客户流失数据的 CSV 文件中添加一个名为link的列。该列应该用一个‘link’字符串填充。事实上,这个字符串可以是任意的,就像列名一样。重要的是一致性,但一切很快就会明朗。第二步是创建一个新的 CSV 文件(我们称之为blending.csv,它包含以下内容:

link, set
link, 1
link, 2

是的,差不多就是这样。为了您的方便,我将两个文件都存储在我的 GitHub 中。

有了这两个文件,我们将它们加载到 Tableau 中,并使用link变量连接这些表。你可以在下图中看到这一点。

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

由于这是“正常模式”,我们将同时结合几个步骤,创建一个名为Kaplan-Meier Dots的计算字段:

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

您可以从“简易模式”中轻松识别该字段的内容,这一次,我们将所有内容都放入一个字段中。这样做之后,新的部分就来了。我们将Kaplan-Meier Curve定义为:

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

这个复杂的公式将使我们能够得到曲线的阶梯形。最后,我们还需要一个辅助变量:

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

进行此操作时,请点击默认表格计算,并指定沿着tenure计算结果。

最后,我们有了创建曲线的所有构件。我们的设置与“简单模式”相似,不同之处在于将Index作为路径,将set作为细节。为了重新创建 Python 中的曲线,我们再次使用PaymentMethod作为颜色。

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

在上图中,我们使用 Python 中的lifelines库精确地重新创建了之前获得的曲线。这肯定需要更多的工作,但最终会有回报。

我们还可以使用Kaplan-Meier Dots来形象化事件沿着曲线发生的过程。在这种情况下,我认为这只会使可视化变得混乱。它更适合于较小的数据集。

我们可以通过添加一些过滤器/拆分来进一步改进仪表板,然后通过公司的报告门户(在这种情况下,是 Tableau Server 的一个实例)与我们的同事共享它。

结论

在本文中,我解释了使用 Tableau 等商业智能工具进行生存分析的潜在好处,并展示了如何使用 Kaplan-Meier 曲线创建仪表板。

通常情况下,没有免费的东西,这种方法也有一些缺点:

  • 计算置信区间肯定更难,需要相当大的努力。
  • 在 Tableau 中,没有简单的方法来执行对数秩检验以比较不同的生存曲线(除非我们使用 Tableau 中的 R,但这可能是未来文章的一个想法)。
  • 如果向数据中添加新的功能,例如,新的客户细分或每个观察的另一个类别,这仍然需要分析师做一些工作来添加到已经存在的仪表板中。然而,大多数情况下这并不经常发生,或者只需要很少的额外工作。

我希望你喜欢这种可视化卡普兰-迈耶曲线的替代方法。一如既往,我们欢迎任何建设性的反馈。你可以在推特上或者评论里联系我。

如果您喜欢这篇文章,您可能也会喜欢这个系列中的其他文章:

[## 生存分析导论

了解生存分析的基本概念,以及可以用来做什么任务!

towardsdatascience.com](/introduction-to-survival-analysis-6f7e19c31d96) [## 生存分析导论:卡普兰-迈耶估计量

了解用于生存分析的最流行的技术之一,以及如何用 Python 实现它!

towardsdatascience.com](/introduction-to-survival-analysis-the-kaplan-meier-estimator-94ec5812a97a) [## 生存分析导论:尼尔森-艾伦估计量

了解如何使用非参数方法来估计累积风险函数!

towardsdatascience.com](/introduction-to-survival-analysis-the-nelson-aalen-estimator-9780c63d549d)

参考

[1] Kaplan Meier 生存测试完整解决方案(无 R) —此处可用

提升可视化效果:使用 Python 和散景制作交互式地图

原文:https://towardsdatascience.com/level-up-your-visualizations-make-interactive-maps-with-python-and-bokeh-7a8c1da911fd?source=collection_archive---------11-----------------------

学习用 Python 制作交互式热图、气泡图和分类图

让我们面对现实吧,数据科学家们:我们的客户喜欢仪表盘。为什么不呢?可视化我们的数据有助于我们讲述一个故事。可视化将数千行数据转化为引人注目的美丽故事。事实上,仪表盘可视化已经变得如此普遍,以至于几乎每份简历都至少有一个(也许几个)仪表盘项目。怎样才能让自己的脱颖而出?条形图和时间序列折线图是不够的。

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

地图帮助我们讲述一个故事!

输入:地理数据。什么是地理数据?广义来说,它是任何你可以放到地图上的东西。它有纬度/经度坐标吗?存在于地理空间吗?那是地理数据。

地图帮助我们讲述故事。想想你最喜欢的一些小说——其中有多少书中有地图?地图让我们沉浸在故事的环境中;在这种情况下,你的客户的数据的故事。

本文将教你处理三种类型的地图:热图、气泡图和分类图。在本教程结束时,您将成为一名空间数据向导,可以将您的仪表板可视化效果与其他工具区分开来。让我们开始吧!

笔记本

要获得与这个项目相关的完整代码,并查看交互式图例和悬停工具提示,请参见与这个项目相关的 Jupyter 笔记本

我们的数据

出于本教程的目的,我们将使用来自武装冲突地点事件数据库(ACLED) 的数据。我敦促你在这个项目中尝试使用你自己的数据!如果这对您来说听起来太复杂,您可以从与本文相关的 github repo 中获得我使用的数据

简短的免责声明:

本文不会对数据集进行探索性分析;我将假设您已经熟悉基本的可视化技术和术语,以及与 Bokeh、Numpy 和 Pandas 库相关的基本概念。要查看我对数据的探索性分析,请参见本笔记本

如果这是你第一次使用散景,试试他们的用户指南中的一些初学者教程。

让我们开始吧!

导入模块

我们将在这个项目中使用所有的散景、熊猫和 Numpy。

加载数据

您可以在此访问用于本项目的数据。使用 pandas ‘read_csv()’ 方法导入数据。您需要将纬度经度列设为浮点类型,以便我们稍后可以将它们转换为 web 墨卡托单位。无论你选择哪一列来定义你的气泡图的半径,都应该是一个 intfloat 类型。在本演示中,是死亡人数列。

初始化地图对象

像许多 Python 库一样,Bokeh 非常面向对象。在绘制数据之前,我们必须以散景图的形式初始化一个地图对象。使用散景制作地图时需要考虑的一个重要因素是散景使用墨卡托单位进行绘图。大多数空间数据可能以经纬度坐标的形式出现(通常称为 wgs84)。首先,我们将把这些坐标转换成墨卡托坐标,然后我们将为我们的数据初始化绘图对象。

要初始化绘图对象,我们必须定义地图可见性的 x 和 y 范围或范围。我希望地图的范围与我稍后将可视化的六边形和气泡的大小成恒定的比例,所以我使用一个变量来建立地图比例。为此选择的数字是任意的——我只是简单地摆弄了几个不同的数字,直到我对缩放级别满意为止。将它设置为一个变量使得以后更改非常容易!

此外,您还必须为您的地图选择一个切片提供商。我更喜欢开放的街道地图(OSM),但你可以在这里找到完整的 Bokeh 支持的地图区块列表。将地图级别设置为“underlay ”,如果使用 Jupyter 笔记本,使用*“output _ notebook()”*方法在线显示地图。

创建地图生成函数

首先,我们将为 hexbin 映射创建一个函数。Hexbins 在数学上比大多数标准热图更精确,尤其是对于以椭圆形式呈现的数据或地理精度范围较低的数据。它们还有视觉上吸引人的额外好处!您还会注意到,我创建了一个悬停工具,它将显示每个六边形中的项目数以及与每个六边形相关联的 q,r 坐标。

接下来,我们将编写一个函数来创建气泡图。气泡图有助于描述事件的规模。在这种情况下,气泡的半径将与每个事件造成的死亡人数成比例-这种类型的地图也非常适合描绘天气事件、疫情案例和其他标量数据集。

来看看我们的作品吧!

现在只需将您的参数输入到您创建的函数中!请注意,在我编写的函数中,我设置了一些默认参数,以使调用函数更容易。

一旦你的情节出现在窗口中,尝试用鼠标悬停在它上面!当您将鼠标悬停在地图数据上时,除了信息性的工具提示之外,您还应该看到地图数据会改变颜色。尝试单击图例中的条目来打开和关闭地图图层!

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

为什么是函数?

为了便于重复使用,我们使用函数来创建地图。将来,如果我们有想要使用气泡图或热图绘制的数据,我们可以重用这些相同的函数,而不是完全重写代码。使用函数完成常见的任务是一个很好的习惯,尤其是如果你在一个团队中工作,团队成员可能会经常使用彼此的代码!

分类数据的交互式图例

您可能已经注意到,在上面的地图中,您可以通过单击图例中的项目来切换图层可见性。怎样才能更好的利用这个特性呢?接下来,我们将分类显示我们的数据。对于这个数据,我将使用事件类型。请注意,下面的代码不是为最大效率或可重用性而设计的;而是为了可读性。初学者应该能够阅读和理解接下来的几个步骤。如果你是更高级的,试着写一个函数,使这个情节更可重用!

首先,让我们初始化一个新的绘图对象。

有许多方法可以完成下一步,但是分类变量的每个因素都需要单独绘制到它自己的级别。在这段代码中,我为每个因子初始化了空列表,并将附加与每个类型相关的信息。

对于每个空列表,迭代器在数据帧中搜索该类型的事件,并在列表中附加诸如 x 和 y 坐标、纬度/经度坐标以及其他描述性信息。如果您选择这种方法,您将不得不对每个空列表都这样做。您也可以将迭代器嵌套在一起来实现这一点,但是出于演示的目的,我选择编写每个单独的代码块来提高代码的可读性——如果不大量使用注释,嵌套迭代器通常很难理解。

一旦列表中填充了与每个类别相关的信息,每个列表都会作为我们之前创建的绘图对象的一个单独的层进行迭代绘图。我们这样做的原因,而不是一次绘制所有数据,是为了增强交互式图例的切换能力。现在,在生成的地图绘图中,用户可以单击图例中的不同类别,按事件类型过滤数据。

使用 Bokeh 的 ‘show(row())’ 方法在仪表板上同时显示两幅地图。佩服你的作品!尝试将鼠标悬停在地图条目上以获取更多信息,并单击图例以过滤显示内容。就是这样!

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

摘要

现在,您可以在散景中绘制地图,并创建有用的交互,让您的客户或顾客从他们的空间数据中获得最大的洞察力。您学习了如何创建 hexbin 热图、气泡图和交互式分类图。通过将这些技能与其他数据可视化技术相结合,您将准备好为您的下一个数据科学项目创建视觉上令人惊叹且有用的仪表板可视化!

解释自动驾驶汽车的等级

原文:https://towardsdatascience.com/levels-of-self-driving-cars-explained-24454463b8eb?source=collection_archive---------36-----------------------

定义自主性的 6 个层次及其重要性

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

查理·迪茨在 Unsplash 上的照片

当你听到自动驾驶汽车时,你的脑海中会浮现出什么形象?这是一辆很普通的车,但允许你有时松开方向盘,也许可以自己停车?或者是一个未来的卧室,你可以在那里看电影和放松,而汽车将为你做所有的驾驶?

嗯,没有正式的定义。所以,汽车工程师协会的人给我们提供了一个如何评价汽车的便捷指南。

但是这有什么关系呢?难道只是在不需要的时候随意的练习分类?

事实证明,它可能比我们预期的更有用。美国政府采用了 SAE 自动化水平。这意味着它可以在未来用于管理特定级别车辆的生产和测试。

不仅如此,它还可以用于标记车辆和确定保险费率。毕竟,让汽车自动驾驶并不能让它免于事故。

0 级

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

照片由丹金Unsplash 上拍摄

这个级别可能描述了你现在正在使用的汽车。司机全权负责驾驶汽车,基本上不涉及自动化。

它可能包括一个接近警告系统来帮助你停车。但是,它仍然需要用户干预才能真正停止。

这个级别的汽车无法在老式巡航控制之外自动驾驶。

一级

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

何塞·卡巴贾尔在 Unsplash 上拍摄的照片

接下来是第一级。如果汽车能够根据从周围环境收集的信息在某种程度上控制自己,它就属于这一类。

所以,像车道辅助这样受欢迎的功能,当你的车开始有点漂移时,可以帮助你回到车道上。或者是基于雷达的巡航控制,它会根据车前的情况自动减速并恢复到之前的速度。

这些小的辅助技术将会使你的车达到 1 级。

第二级

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

Meik Schneider 在 Unsplash 上拍摄的照片

这里有一些汽车可以在特定的情况下完全靠自己驾驶,通过转向和操控加速,而不是只做其中一项。

如果你有一个更先进的自动巡航控制系统,也可以将汽车向左或向右移动。或者也许你有一个自动泊车功能,可以在没有你的帮助下将你的车挤进一个狭小的停车位。这是适合你的类别。

请记住,尽管这种程度的自动驾驶汽车仍然需要驾驶员始终保持专注,并随时准备干预。

第三级

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

彼得·布鲁姆菲尔德Unsplash 上拍摄

现在,我们开始了一些有趣的事情。3 级汽车能够根据驾驶员选择的目的地沿正常道路和特定路径行驶。

应该很棒吧。不完全是。这些汽车没有有意义的故障保险。

这让他们处于一种奇怪的中间状态。制造自动驾驶汽车的全部目的是增加安全性,并允许驾驶员在路上做其他有意义的任务。

然而,3 级汽车应该仍然有人类司机,如果出现问题,他们可以立即干预。这意味着,如果你的全自动驾驶汽车在你看电影时遇到了它无法独自解决的情况,这种情况可能不会有好结果。

因此,许多汽车制造商试图直接跳到第四级也就不足为奇了。

四级

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

Bram Van Oost 在 Unsplash 上拍摄的照片

与 level 3 类似,这些汽车使用人类驾驶员作为自动防故障装置,但它足够智能,可以自行处理某些棘手的情况。这意味着 4 级汽车可以被设计成完全处理某些任务或在有限的地理区域内行驶。

它仍然需要人类驾驶员来处理过于复杂的情况,比如在繁忙的高速公路上进行艰难的合并。最大的区别是,如果这种级别的汽车遇到它自己无法处理的情况,它必须能够通过停车来安全地中止驾驶,直到里面的人可以接管。

目前,谷歌的自动驾驶 Waymo 车队包含 4 级车辆。这意味着它们可以在没有人的情况下运行,但是它们被限制在特定的位置。现在,他们位于凤凰城内。

福特计划在 2022 年之前制造自己的商用自动驾驶汽车,由于疫情的原因,时间表略有变动。

第 5 级

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

照片由梅丽莎·乔恩Unsplash 拍摄

这是自动驾驶车辆的圣杯。一辆在转向时能控制一切的汽车。它根本不需要驾驶员的任何干预。

更疯狂的是,大多数 5 级概念车连方向盘都没有。它应该能够处理人类会处理的任何情况。理论上,它应该能够做得更好,比人类司机更安全。

尽管像英伟达和奥迪这样的公司目前正在研究第 5 级汽车和所需的技术,但还不清楚这何时会成为现实。

不仅公众必须相信自动驾驶汽车会从头到尾安全地载着他们,不会把他们推下悬崖。政府对这类汽车的监管也存在重大问题。

结论

完全自动驾驶的汽车还没有出现,很难定义这些汽车应该能够做什么。SAE 量表允许我们更好地定义当前的发展水平。它还可以帮助监管此类车辆及其所需的测试。

它还有助于突出与每个级别相关的问题,以及要真正实现完全自动驾驶汽车必须做些什么。

参考

[1] SAE International 发布了自动驾驶车辆“驾驶自动化水平”标准的更新视力表。(2018).于 2020 年 10 月 7 日从https://www . SAE . org/news/press-room/2018/12/SAE-international-releases-updated-visual-chart-for-its-% E2 % 80% 9 clevels-of-driving-automation % E2 % 80% 9D-standard-for-self-driving-vehicles-vessels

[2]k .科罗塞克(2020 年)。福特将自动驾驶汽车服务推迟至 2022 年。检索 2020 年 10 月 07 日,来自https://TechCrunch . com/2020/04/28/Ford-deflates-autonomous-vehicle-service-until-2022/

利用 Chrome 开发工具进行动态网页抓取

原文:https://towardsdatascience.com/leverage-chrome-dev-tools-for-dynamic-web-scraping-2d3f7703ea4a?source=collection_archive---------12-----------------------

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

奥斯曼·拉纳

如何利用 ChromeDev 工具

所以你有一个你想刮的网站?但是不一定知道使用什么包或者如何进行这个过程。这是常见的,当第一次开始网页抓取。了解如何有效地从网站上获得你想要的东西需要时间和多个脚本。

在这篇文章中,我们将通过规划一个网页抓取脚本的过程。

在本文中,您将了解到

  1. 了解网页抓取的工作流程
  2. 如何快速分析一个网站进行数据提取
  3. 如何利用 Chrome 工具进行网页抓取

了解网页抓取的工作流程

有三个关键领域要考虑时,寻找做网页抓取

  1. 视察网站
  2. 从页面中规划您需要的数据及其选择器/属性
  3. 编写代码

在本文中,我们将重点检查网站。这是网络抓取的第一步,也是最重要的一步。这也是最少被谈论的,这就是为什么你在这里读这篇文章!

1.数据是在一个页面上,几个页面上还是通过页面的多次点击?

当你第一次想到要从中提取数据的网站时,你会对你想要的数据有所了解。

您可以想象,一个页面上的信息是最简单的,代码必然会更简单,而嵌套的信息页面会产生更多的 HTTP 请求,结果代码会更复杂。了解这一点有助于计划进行清理需要什么类型的函数。

2.网站是怎么搭建的?Javascript 的使用率有多高?

在这个过程的早期,了解网站是如何建立的是至关重要的一部分。这通常决定了刮擦的难易程度。互联网上几乎所有的页面都将使用 HTML 和 CSS,python 中有很好的框架可以轻松处理这些。然而,知道是否有任何 javascript 被实现来操纵网站。加载可访问或不可访问的新信息很重要。

3.该页面需要登录吗?

登录在网络抓取中是一个特殊的挑战,如果需要登录,这会降低抓取的效率,但也会使你的抓取器很容易被阻塞。

4.有动态生成的内容吗?

我们的意思是,看一眼就足以知道网站的功能是交互式的,很可能是由 javascript 生成的吗?网站上的互动越多,刮刮乐就越有挑战性。

5.是否启用了无限滚动?

无限滚动是面向 javascript 的特性,其中向服务器发出新的请求,并且基于这些通用或非常具体的请求,操纵 DOM 或使来自服务器的数据可用。现在无限滚动需要发出 HTTP 请求,并在页面上显示新信息。理解这一点很重要,因为我们通常要么需要模拟这种行为,要么使用浏览器活动来模拟这种行为。

6.有下拉菜单吗?

任何类型的下拉菜单都会给网页抓取带来特殊的挑战。这是因为您通常需要模拟浏览器活动来获取数据。

7.有表格吗?

许多网站经常使用表单,要么是为了搜索数据,要么是为了登录网站的一部分。HTML 表单通常调用 javascript 将数据发送到服务器,服务器将进行身份验证并用您想要的信息进行响应。Javascript 能够调用 HTTP 请求,并且经常是在不呈现页面的情况下更改页面信息的来源。所以你需要了解网站是如何做到这一点的,有没有 API 响应 javascript 调用的 HTTP 请求?这能用来获得你想要的信息吗?还是需要自动化?

8.有没有可以提供信息的表格

让我们面对现实吧,桌子是一种痛苦!在 HTML 中创建是痛苦的,清除也是痛苦的。小心表格数据,你可能会头疼。幸运的是,有一些框架可以快速获取表数据,但是要做好准备,不能 100%确定您能够使用这些框架,并且可能需要手动循环访问行来获取您想要的数据

9.是否有隐藏的 API?

这是抓取动态内容网站的关键。通常,API 端点用于提供响应,这些响应携带了网站在现代页面上显示的数据。网站通常不会明确显示这一点,但是通过查看呈现网站的请求,我们可以了解网站是否使用了 API。这就是面向 javascript 的网站的工作方式,它们向服务器发出 HTTP 请求,显示的数据出现在网站上。如果我们能够模拟这些 HTTP 请求,我们就有机会获得相同的数据。这被称为重新设计 HTTP 请求。

10.我们需要浏览器活动来抓取数据吗?

这一点值得仔细思考。自动化浏览器活动应该是最后的手段,如果刮擦一点也不小的话。需要浏览器活动的中型到大型的抓取会花费很长时间,并且容易受到网站结构变化的影响。有时,这是获取所需数据的唯一方法,因此如果有其他选择,我们应该使用它。

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

乔巴·塔拉贝尔 Unsplash

网页抓取示例

因此,在考虑了这些问题之后,现在让我们来深入研究一个例子,它展示了其中的一些原则。

挑战:

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

从 WeatherUnderground 网站这里刮取当前温度

那么我们如何近距离分析这一页呢?答案是 Chrome 的开发工具!Chrome 浏览器为你提供了大量分析任何网站的方法,应该成为你所有网络抓取项目的一部分。

在 5 分钟内分析网页

如果你看看谷歌的开发工具页面,你可以看到有很多关于网络开发人员的细节。工具集中有几个区域对 Web Scrapers 非常有用。

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

网站概述

让我们一次检查一个问题。

  1. 数据是在一页还是多页上?
    信息在一页上!太好了,这让生活变得简单多了
  2. 网站是怎么搭建的?

查看信息,有多个选项卡可以点击,很可能调用一些 javascript 来显示您想要的数据。大多数现代网站会将来自服务器的数据显示在网站上,并通过视觉检查,这里就是这种情况。

提示:禁用 javascript 是了解网站布局和信息中包含多少 javascript 的可靠方法。

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

右键单击并检查要分析的页面

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

导航到 Chrome 开发工具设置。不要忘记点击右边的三个点!

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

在设置中禁用 Javascript

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

我们已经禁用了 javascript,看起来我们仍然能够访问您想要的所有数据!这让我们的生活更轻松!

3.网站需要登录吗?不要!

4.内容是动态创建的吗?一句话,大概!温度数据可能会发生变化,这些变化很可能会反映在服务器级别上,然后可以显示出来,而无需不断更新网站。禁用 javascript 似乎不会改变温度数据,但这只是一次一个快照。

5.有没有无限滚动?不要!

6.有下拉菜单吗?不要!

7.有什么表格吗?不要!

8.有桌子吗?是的,但我们会看看如何驾驭它!

在我们继续之前,让我们总结一下。

我们知道这个页面在一个表中有数据,在一个页面上,不需要任何登录,当 javascript 被禁用时也不会改变。我们现在能够更好地获取这些数据。

现在,我们准备看看我们是否可以轻松地获取信息。

9.有 API 吗?

要知道这是不是真的,我们必须对 Chrome 开发工具有更多的了解。在每个被检查的页面下,都有一个名为“网络”的选项卡。在这里,我们可以通过在网络选项卡打开时刷新页面或在网站上执行特定功能来记录浏览器发出和接收的任何传入请求和响应。记得打开网络标签,否则,活动将不会被记录!

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

我们可以从屏幕上看到我们没有记录任何东西。刷新页面给我们下图

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

红框:这是概述所有的行都是服务器活动的量度
绿框:这是对服务器的单个请求。这里显示了名称、使用的 HTTP 方法和响应的大小!

开发工具上有一个名为“XHR”的标签。这代表 XML HTTP 请求,与服务器交互的任何内容都将从浏览器发出的所有请求中过滤掉。API 最有可能出现在这里,因为所有的 API 都与服务器交互。

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

单击 XHR 获取 API 请求

按照大小对请求进行排序是一个很好的做法。你想要的数据通常是最大的回复。

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

这里我们根据响应的大小对请求进行了排序。单击一个请求会给我们带来一个右侧面板,显示 HTTP 请求和响应的标题信息,以及需要在 HTTP 请求中传递给服务器的任何数据。

有一个非常有用的预览选项卡,你可以看到数据的快照。我们可以立即看到,我们想要的数据有可能来自那里。

让我们来看看它的“headers”选项卡

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

在右侧面板中,我们可以看到请求 URL,我们可以看到它是一个 API api.weather.com/v2/pws/obeservations/.....

有几个参数和 URL 一起传递,包括一个apiKey, units, stationid,format。请注意,我们稍后会用到它。

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

同样重要的是,从回复标题中我们可以看到content-type: application/json; charset=UTF-8。这告诉我们响应是在一个 JSON 对象中!高度结构化的数据!太棒了。

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

这是数据随请求传递的地方。注意,在单位、stationID 和格式旁边有一个apiKey。这是我们在请求 URL 中看到的数据,但是它在这里被清楚地格式化了!

获取数据

现在,我们可以使用参数对请求进行硬编码,并潜在地获得对数据的访问。但是有一个方便的网站通过转换请求的 cURL 命令并将其转换为 python 请求来消除这一点。为此,请参见下图

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

我们复制了“复制为卷曲”( bash ),并把它粘贴到一个网站上curl.trillworks.com

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

现在我们有了一个很好的格式化的 HTTP 请求,我们可以把它复制到任何我们想要的编辑器中。见下面的例子。

代码示例

import requestsheaders = {
    'authority': 'api.weather.com',
    'accept': 'application/json, text/plain, */*',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36',
    'origin': '[https://www.wunderground.com'](https://www.wunderground.com'),
    'sec-fetch-site': 'cross-site',
    'sec-fetch-mode': 'cors',
    'sec-fetch-dest': 'empty',
    'referer': '[https://www.wunderground.com/calendar/gb/edinburgh'](https://www.wunderground.com/calendar/gb/edinburgh'),
    'accept-language': 'en-US,en;q=0.9',
    'dnt': '1',
}params = (
    ('apiKey', '6532d6454b8aa370768e63d6ba5a832e'),
    ('units', 'e'),
    ('stationId', 'IUNITEDK517'),
    ('format', 'json'),
)response = requests.get('[https://api.weather.com/v2/pws/observations/current'](https://api.weather.com/v2/pws/observations/current'), headers=headers, params=params)

请注意,它不仅包括我们正在讨论的参数,还包括请求头。这是一个需要提出的重要概念。我们正试图模仿 HTTP 请求从网站上抓取数据。现在,有时 API 端点只需要一个简单的 HTTP Get 请求。但有时它需要更多,有时它需要头,包括用户代理或 cookies。有时它需要参数,比如这里的例子。

在 python 中尝试不带头文件的 HTTP 请求和带头文件的 HTTP 请求,以查看它们是否需要这些信息来获取您想要的数据,这很有用。玩了一圈之后,你会发现实际上所需要的只是参数。

import requests
params = (
    ('apiKey', '6532d6454b8aa370768e63d6ba5a832e'),
    ('units', 'e'),
    ('stationId', 'IUNITEDK517'),
    ('format', 'json'),
)response = requests.get('[https://api.weather.com/v2/pws/observations/current'](https://api.weather.com/v2/pws/observations/current'), params=params)
response.json()

笔记

  1. 使用requests.get()方法,我们发出一个 HTTP get 请求
  2. get()中,该方法允许随请求体一起传递参数。在这种情况下,我们希望具体指定 apiKey 和其余的查询参数。
  3. 这允许与服务器进行认证,并给我们正确的输出
  4. response.json() 将 JSON 对象转换成 python 字典

输出

{'observations': [{'stationID': 'IUNITEDK517',
   'obsTimeUtc': '2020-08-28T08:54:16Z',
   'obsTimeLocal': '2020-08-28 09:54:16',
   'neighborhood': 'Edinburgh',
   'softwareType': 'N23DQ V2.2.2',
   'country': 'GB',
   'solarRadiation': 123.3,
   'lon': -3.210205,
   'realtimeFrequency': None,
   'epoch': 1598604856,
   'lat': 55.943665,
   'uv': 1.0,
   'winddir': 79,
   'humidity': 84,
   'qcStatus': 1,
   'imperial': {'temp': 54,
    'heatIndex': 54,
    'dewpt': 49,
    'windChill': 54,
    'windSpeed': 7,
    'windGust': 12,
    'pressure': 29.68,
    'precipRate': 0.0,
    'precipTotal': 0.0,
    'elev': 243}}]}

现在查看我们刚刚创建的 python 字典,我们可以看到,实际上我们需要的数据在一个名为observations的键后面。观察值是一个只有一项的列表,所以要从字典中获取值,我们需要选择该项observations[0]

在这个列表中,item 是一个名为imperial的键,其中嵌套了一个名为temp的键。大量的嵌套,但这是 JSON 对象的本质!

为了访问我们想要的数据,我们向下迭代到我们需要的键。

response.json()['observations'][0]['imperial']['temp']

输出

54

浏览这本字典,我们现在可以发布最后一段代码了

import requests
params = (
 ('apiKey', '6532d6454b8aa370768e63d6ba5a832e'),
 ('geocode', '55.95,-3.37'),
 ('language', 'en-US'),
 ('units', 'e'),
 ('format', 'json'),
)
response = requests.get('[https://api.weather.com/v3/wx/forecast/daily/15day'](https://api.weather.com/v3/wx/forecast/daily/15day'), params=params)
response = requests.get('[https://api.weather.com/v3/wx/forecast/daily/15day'](https://api.weather.com/v3/wx/forecast/daily/15day'), params=params)
temp = response.json()['observations'][0]['imperial']['temp']
print('Temperature: ', temp)

输出

Temperature:  52

摘要

在本教程中,我们已经有效地了解了网页抓取的工作流程,以及每个网页抓取项目中我们应该问的问题。我们还介绍了如何通过 API 端点获取动态数据。这些 API 通常不是显式的,需要利用 chrome 开发工具来理解如何模拟 Javascript 调用的请求。Chrome Dev Tools 中的网络非常适合为我们提供做出正确 HTTP 请求所需的所有信息。

这被称为重新设计 HTTP 请求,是抓取动态内容的最有效的方法。当然还有其他方法,但它们通常涉及浏览器活动,并且如上所述,这通常不适合大型数据集抓取,因为效率低,并且可能很容易受到网站需求变化的影响。

关于作者

我是一名执业医师和教育家,也是一名网站开发者。

请在这里查看关于我在博客和其他帖子上的项目进展的更多细节。更多技术/编码相关内容,请点击这里订阅我的简讯

我将非常感谢任何评论,或者如果你想与 python 合作或需要帮助,请联系我。如果你想和我联系,请在这里 asmith53@ed.ac.uk 或在 twitter 上联系。

相关文章

[## 学习 Python 的方法

今天如何最大限度地学习 python

towardsdatascience.com](/approach-to-learning-python-f1c9a02024f8) [## 如何从脚本运行 Scrapy

忘记 scrapy 的框架,全部用使用 scrapy 的 python 脚本编写

towardsdatascience.com](/how-to-run-scrapy-from-a-script-ff07fd6b792b) [## 使用 Scrapy 进行有效的网页抓取

Scrapy 的新功能使您的刮削效率

towardsdatascience.com](/efficient-web-scraping-with-scrapy-571694d52a6)

利用云函数和 API 来监控 Google 表单中的云数据准备作业状态

原文:https://towardsdatascience.com/leverage-cloud-functions-and-apis-to-monitor-cloud-dataprep-jobs-status-in-a-google-sheet-b412ee2b9acc?source=collection_archive---------46-----------------------

如果您在 Google Cloud 中管理数据和分析管道,您可能希望监控它并获得端到端分析流程的全面视图,以便在出现问题时快速做出反应。

本文向您展示了如何通过利用云函数的 API 来捕获云 Dataprep 作业状态。然后,我们将状态输入到一个 Google Sheet 中,以便简单地检查作业的状态。使用相同的原理,您可以在 Google Sheets 中结合其他 Google 云服务状态,以获得您的数据管道的全面视图。

为了说明这个概念,我们将假设您想要通过快速查看 Google 工作表来监控一个每日调度的 Dataprep 作业,以获得潜在故障的概述。锦上添花的是,你还可以在 Google Sheets 中查看菜谱名称和工作简介结果。

本文是一个分步指南,介绍了当一个云数据准备任务完成时触发云功能以及将任务结果、状态和直接链接发布到谷歌表单的过程。

下面是一个谷歌表单的例子,其中发布了工作结果和链接。

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

图 1-Google Sheet data prep 工作结果,可访问工作简介 PDF

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

图 2 —基于云数据准备作业执行触发云功能的高级流程

1.入门指南

为了让这个指南更实用,我们在 Github 中分享了它,这是云函数的 Node.js 代码。

你需要一个有效的谷歌帐户,并访问云数据准备和云功能来尝试它。你可以从谷歌控制台https://console.cloud.google.com/启动服务。

备注:要调用 API,需要一个访问令牌。要生成这个访问令牌,必须是 Google Cloud 项目的所有者。如果你不是谷歌云项目负责人,你可以使用个人 Gmail 帐户进行尝试。

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

图 3 —从设置菜单中获取访问令牌

2.创建 HTTP 云函数以在 Google 工作表中发布

首先,我们需要创建 HTTP Cloud 函数,当 Dataprep 作业完成时,它将作为 Webhook 被触发。

从谷歌云控制台这里创建一个云功能。触发器类型必须是“HTTP”。给它起个名字,得到一个类似https://us-central 1-data prep-premium-demo . cloud functions . net/data prep-web hook-Function的 URL。稍后,在 Dataprep 中创建 Webhook 时,我们将需要这个 URL。在我们的示例中,我们将使用上面提供的 Node.js 作为源代码部分下的运行时。

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

图 4 创建从 Dataprep 调用的云函数

如果你想探索更多关于云函数的知识,可以看看这个教程

云函数代码遵循以下逻辑:

  1. 检索由 Dataprep 提供的作业 id 和状态(失败或完成)。
  2. 在 API 调用中利用 Dataprep 用户访问令牌,以便由云 Dataprep 进行身份验证。
  3. 通过 getJobGroup Dataprep API 调用获得关于作业的更多信息(状态、配方 id)。关于这个 Dataprep API 端点的文档可以在这里找到:https://clouddataprep . com/documentation/API/# operation/getJobGroup
  4. 通过 getWrangledDataset Dataprep API 调用获取有关作业配方的信息(名称、描述)。关于这个 Dataprep API 端点的文档可以在这里找到:https://clouddataprep . com/documentation/API/# operation/getwrangeddataset
  5. 发布信息和链接到谷歌表。工作结果页面和下载 PDF 格式结果简介的链接写在 Google 表单中:

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

图 5——node . js 代码获取作业细节并在 Google 工作表中发布作业结果状态

Node.js 代码这里是这里是。您需要编辑突出显示的红色值,并将其替换为您在 Cloud Dataprep 项目中检索到的正确值。

  • 调用 Dataprep API 的访问令牌:

var DataprepToken = " eyjhjkfrye 353 lgh 12 ghjkdfsghk "

  • 您要发布结果的 Google 工作表 ID:

const job sheetid = " 1x 63 lfifsdfd D3 dsfn 0 WM 3 skx-Ro "

要检索谷歌电子表格 ID,请遵循这里的解释。

  • Google API 密钥:

sheet SAPI . spreadsheets . values . append({ key:" aizasdfsfdflh 0 qu 8 q ",

要检索 Google API 密钥,请遵循这里的解释。

您还需要将以下依赖项添加到 Node.js 云函数(包。JSON 选项卡):

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

图 6 — Node.js 依赖包

然后,您需要部署云功能。部署后,云函数正在运行,并等待在执行作业时从 Cloud Dataprep 调用。你可以在这里了解更多关于部署和执行云功能的

3.创建一个云数据准备流并配置一个 Webhook

接下来,您需要创建 Cloud Dataprep 流,它将调用 HTTP Cloud 函数在 Google Sheets 中发布作业结果。

您需要在您的流中创建并配置一个 Webhook 任务,它将调用您的 HTTP Cloud 函数。

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

图 7——创建云数据准备流程并在流程上配置 Webhook 任务

Webhook 任务需要配置以下信息:

  • URL :这是您之前创建的 HTTP Cloud 函数的 URL。比如https://us-central 1-data prep-premium-demo . cloud functions . net/data prep-web hook-Function
  • Headers :使用类似下面截图中的内容类型和应用程序/json 的头。
  • Body :使用值{“jobid”:“ j o b I d " , " j o b s t a t u s " : " jobId "," jobstatus":" jobId""jobstatus":"jobStatus”},如下图所示。
  • 触发事件:您可以决定触发任何状态的 Webhook,或者只触发失败或完成的作业。
  • 触发对象:您可以决定只为流程中的特定输出,或者为流程中执行的任何作业触发 Webhook。

输入这些信息后,就可以测试调用云函数的 Webhook 任务了。

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

图 8 —调用云函数的 Webhook 任务参数

保存 Webhook 任务后,就可以在执行作业时调用它了。

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

图 9 —创建的 Webhook 任务

4.测试端到端流程

现在,您已经准备好测试端到端流程,方法是从 Dataprep 作业中运行一个作业,并查看添加到 Google 工作表中的作业结果状态。

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

图 10 —运行一个数据准备作业

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

图 11——Google 工作表中发布的工作结果状态和链接

最后,您还可以通过查看位于此处的 Google Cloud Functions 日志来检查正确的执行细节(带参数的 API 调用和 Cloud Dataprep 作业状态)。

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

图 12 —云函数日志

结论

现在,您应该理解了在 Google Sheet 中自动发布 Dataprep 工作结果的基本原则,这样您就可以轻松地监控和与更广泛的团队共享摘要信息。

你已经了解了

  • 云数据准备 API
  • 云数据准备 Webhooks
  • 调用 API 的云函数

您还可以扩展这个解决方案来监控额外的 Google 云服务,以实现端到端的数据管道监控。

现在,您可以自动监控您的工作状态了。您还可以利用另一个云功能或外部调度程序来自动化云数据准备。看看这些文章,它们解释了如何使用 Cloud Composer 编排云数据准备作业,以及如何在文件到达云存储时自动化云数据准备管道。

原载于www.trifacta.com

在 Scikit-Learn 中利用多核实现更快的性能

原文:https://towardsdatascience.com/leverage-multicore-for-faster-performance-in-scikit-learn-147c374ad2d3?source=collection_archive---------39-----------------------

内部 AI

随着物联网、传感器和存储能力的进步,可用的数据量呈超级指数级增长。

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

翁贝托Unsplash 上的照片

十年后我们生活的世界将会完全不同,比现在的世界更加复杂。

随着世界变得越来越复杂,底层数据也越来越复杂。机器学习的挑战之一是处理复杂数据集对计算能力和时间的需求不断增加。

Scikit-learn 不支持像 Keras 或 TensorFlow 这样的 GPU,但我们可以利用多核 CPU 并行执行几个任务。

在本文中,我们将看到加速机器学习和缩短建模时间的过程。

我们将在本文中使用“Volcanoes”数据集来理解 Sckit-learn 中的并行任务处理过程。

from sklearn.datasets import fetch_openml
from sklearn.ensemble import RandomForestClassifier
from time import time
from matplotlib import pyplot as plt

在下面的代码中,“火山”数据集是从 openml 中提取的。

X,y= fetch_openml(name="volcanoesb3",version=1,
return_X_y=True,as_frame=True)

训练每个模型所用的时间将保存在列表“timetaken”中。我有一台四核笔记本电脑,因此将训练最多四核的机器学习模型。如果您有一个八核或更多内核,那么您可以提到“n_cores ”,最多八个或更多内核。

timetaken = []
n_cores = [1, 2, 3, 4]

在下面的代码中,机器学习模型在一个循环中从单核到四核进行训练,并且节省了训练所用的时间。

我们可以用 RandomForestClassifier 中的“n_jobs”参数指定并行运行的作业数量。如果我们希望使用所有可用的内核,那么我们可以将“n_jobs”指定为“-1”

for n in n_cores:
    start = time()
    model = RandomForestClassifier(n_estimators=1500,
                                   random_state=42, n_jobs=n)
    model.fit(X, y)
    end = time()
    elapsedtime = end - start
    timetaken.append(elapsedtime)

直观显示用不同核心训练模型所需的时间是很有帮助的。

plt.plot(n_cores, timetaken)
plt.show()

我们可以看到,模型训练时间大幅减少,因为它是从一个核心训练到三个核心。从使用三个内核到使用所有四个内核只会略微增加一点时间。

用单核训练该模型花费了将近 22 秒,现在下降到大约。约 11 秒,三核。

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

结论和要点

随着物联网、传感器和存储能力的进步,可用的数据量呈超级指数级增长。

GPU 和 TPU 是加速处理和提高机器学习算法性能的救星。

不幸的是,Scikit-Learn 不支持 GPU,但我们可以利用多核微处理器并行处理少量任务,并更快地获得结果。

即使是四核和八核笔记本电脑,我们也可以大幅缩短机器学习的处理时间。

可以在 Python 中了解更多关于线性回归的内容:Sklearn vs Excel

利用 D3.js v4 构建 Tableau 的网络图

原文:https://towardsdatascience.com/leverage-on-d3-js-v4-to-build-a-network-graph-for-tableau-with-ease-cc274cba69ce?source=collection_archive---------23-----------------------

使用 D3.js 自动计算每个节点的(x,y)坐标,并根据您的喜好调整布局

因此,最近世界各国都在狂热地追踪接触者,以控制新冠肺炎感染率。作为一名数据分析师,我最近接触了很多网络图。看到一个主要由节点链接组成的图不仅美观,而且有效地表示了不同实体之间的连接,这很有趣。

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

Image by Author |一个由 d3.js 渲染的网络图示例,用于可视化 stackoverflow 上#标签的出现频率

大多数网络图可视化大多部署在 web 应用程序上。残酷的事实是 web 开发时间远远超过 dashboarding。此外,我工作过的团队通常只对网络图的快照感兴趣,因此在 Tableau 等仪表板工具上绘制网络图的能力将为突出显示与图形的交互性不太重要的重要发现提供更大的便利。因此,我继续探索和实现用最小的努力在 Tableau 上绘制完全相同的图形的方法。这让我创建了一个由 2 部分组成的宠物项目

**第一部分:**直接为 Tableau 输出数据的 web 应用程序(功能包括手动调整图形布局的灵活性+最终 Tableau 就绪数据输出的导出)

**第二部分:**使用在第一部分中创建的数据生成器,相应地在我的下一个 Tableau 仪表板中包含一个网络图。

第一部分:创建 Web 应用工具

关于项目的这一部分,我的网络应用程序的布局和功能是基于特里斯坦·吉列文的 https://observablehq.com/@ladataviz/network-data-generator

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

图片由作者提供|展示了https://observablehq.com/@ladataviz/network-data-generator上的功能,包括:使用户能够输入自己的 JSON 文件来呈现网络图,并为 Tableau 导出 2 个 CSV 文件。此外,可以调整节点尺寸参数的配置,以改变整体布局。

不要误会我的意思,虽然我觉得这很棒,而且我对利用 d3 图形库的独创性印象深刻,但当我试图使用 Tableau 中的输出时,有两个主要限制——

  • 约束 1:该工具不允许直接将节点拖动到其他位置来实现更加定制的布局。虽然强度和碰撞参数可以切换,但节点的移动是不可预测的,难以操纵。
  • 约束 2:最终生成的输出确实呈现了工具中预览的精确布局。然而,当我试图过滤一些节点链接的显示时,数据输出中没有特定的字段— nodes.csvlinks.csv ,这使得这在 Tableau 中很容易发生。

在解决以上两个问题之前,我继续开发了一个类似于 Tristan Guillevin 的 web 界面:

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

作者图片|我在https://tableau-data-utility.glitch.me/部署的 web 应用预览。类似地,用户可以按照指定的格式输入他们自己的 JSON 文件。图形布局也启用了配置。此外,带有 Tableau 图标的按钮说明了两个输出文件— nodes.csvlinks.csv 之间的后续数据连接是如何发生的

基本上,它是一个单页应用程序,包含所有的说明和所需的信息。现在,这里出现了一个有争议的最用户友好的特性— 允许用户手动改变和拖动节点,以使图形符合他们想要的布局:

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

作者图片|在https://tableau-data-utility.glitch.me/对网络应用程序中图表的原始布局进行简单调整的演示

这里有一个明显的对比,工具在移动后成功地改变了节点的坐标:

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

作者图片| ( )D3 . js 渲染的网络图调整前布局| ( )导出 csv 文件的 Tableau 图形可视化

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

作者图片| ( )D3 . js 渲染的网络图调整后布局| ( )导出 csv 文件的 Tableau 图形可视化

因此,解决了(1/2)的约束条件——另一个未解决的问题是,当在 Tableau 中绘制时,生成的原始输出不允许对特定的节点链接进行过滤(这将在第二部分中进行阐述)。

第二部分:在 Tableau Dashboard 中包含一个网络图,用于数据剖析/分析

最终,我决定在 2020 年第三季度确定新加坡的登革热集群。原始数据源在最终的仪表板中说明,但是在地理编码和一些数据转换之后,生成 Tableau 图所需的 JSON 输入被生成:https://github . com/wended-geek-cc/Tableau-data-utility/blob/master/public/data/SG _ dengue _ clusters . JSON

在绘制网络图并将地图添加到仪表板上之后,我面临的第二个约束是无法通过特定节点/链接进行过滤:

  • [Id] (nodes.csv):每个节点的标识符
  • [Id] (links.csv):节点的[Id],即源/目标
  • [Key] (links.csv):自动生成的数值,用于标识源节点和目标节点
  • [类型] (links.csv):源/目标

实际上,只有[Id]字段可用于识别要过滤的节点/链接。然而,由于输出格式,当单个节点被过滤时,节点的链接默认不被过滤,这在图中留下了许多挂起的链接:

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

作者图片| Tableau 演示,显示节点 c0 至 c7 已过滤。请注意,过滤节点的链接仍然存在。

我想到的解决方案是生成一个名为[Link Id]的额外字段,它基本上连接了源节点的[Id]和目标节点的[Id]。这与用于区分链路的[Key]字段的目的相同,但是节点和链路现在都可以被[Link Id]识别。

此后,用以下公式创建一个称为[Filter by Link Id]的字段:

IF [Parameters].[Cluster Id]='All' THEN TRUE 
ELSE 
 RIGHT(link_id,LEN([Parameters].[Cluster Id]))=[Parameters].[Cluster Id] 
END

因此,仪表板最终可以同时在网络图和其他视图中交叉过滤:

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

图片按作者| Node [Id] c10 被选中,在部署于https://public . tableau . com/views/singapores dengue clusters 2020/SG _ dengue _ clusters _ 2020?:language = en&:display _ count = y&:origin = viz _ share _ link

感谢您花时间阅读,我在 Tableau 仪表盘上绘制网络图的探索到此结束!

请随意使用部署在 https://tableau-data-utility.glitch.me/的工具来生成 Tableau 网络数据集。

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

图片作者| Dashboard 部署于https://public . tableau . com/views/Singapore sdengeclusters 2020/SG _ dengue _ clusters _ 2020?:language = en&:display _ count = y&:origin = viz _ share _ link

[## 通过我的推荐链接加入灵媒——李思欣·崔

获得李思欣·崔和其他作家在媒体上的所有帖子!😃您的会员费直接…

geek-cc.medium.com](https://geek-cc.medium.com/membership)

利用 PyCaret 的力量

原文:https://towardsdatascience.com/leverage-the-power-of-pycaret-d5c3da3adb9b?source=collection_archive---------16-----------------------

用一行代码学习机器学习!

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

照片由 Guillaume JailletUnsplash

P yCaret 是一个开源、低代码的 Python 机器学习库,旨在减少周期时间,并允许您使用您选择的笔记本环境在几秒钟内从准备数据到部署模型。

本文的目标读者是熟悉机器学习概念,并且知道如何使用不同的库(如 Scikit-Learn)实现各种机器学习算法的人。完美的读者意识到自动化的需要,并且不想花太多时间寻找最佳算法及其超参数。

作为机器学习从业者,我们知道在一个完整的数据科学项目的生命周期中涉及到几个步骤,其中包括数据预处理——缺失值处理、空值处理、更改数据类型、分类特征的编码技术、数据转换——log、box cox 转换、特征工程、探索性数据分析(EDA)等。在我们真正开始建模、评估和预测之前。因此,我们使用 python 中的各种库来完成这些任务,如 numpy、pandas、matplotlib scikit-learn 等。因此 Pycaret 是一个非常强大的库,可以帮助我们实现过程的自动化。

正在安装 Pycaret

!pip install pycaret==2.0

一旦 Pycaret 安装完毕,我们就可以开始了!我将在这里讨论一个回归问题,Pycaret 可用于许多问题,如分类、异常检测、聚类、自然语言处理。

我将在这里使用我从 Flipkart 网站获得的笔记本电脑价格数据集

**df = pd.read_csv('changed.csv') # Reading the dataset
df.head()**

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

**from pycaret.regression import *
reg = setup(data = df, target = 'Price')**

Pycaret 的 setup()函数完成了大部分的校正工作,这通常需要多行代码才能完成——只用一行代码就完成了!这就是这个令人惊叹的图书馆的美妙之处!

我们使用设置变量,在目标中,我们提到特性名称(因变量)——这里我们想预测笔记本电脑的价格,因此它成为因变量。

**X = df.drop('Price',axis=1) 
Y = df['Price'] 
Y = pd.DataFrame(Y)**

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

比较所有回归模型

**compare_models()**

训练所有的回归模型。因此,在此之后,我们可以创建任何模型——要么是 CatBoost,要么是 XGBoost regressor 模型,然后我们可以执行超参数调优。

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

我们可以看到,与所有其他模型相比,我们的梯度推进回归(GBR)模型表现相对更好。但是我也使用 XGBoost 模型进行了分析,这个模型比 GBR 模型表现得更好。

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

使用梯度推进回归模型时出错

因为我们已经确定了最好的模型是 xgboost,所以我们在 create_model 函数的帮助下创建了 XGBoost 模型,并提到了 max_depth(模型运行的迭代次数)

创建模型

**xgboost = create_model('xgboost', max_depth = 10)**

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

使用 XGBoost 模型时出错

因此,在创建深度为 10 的模型后,它运行 10 次迭代,并在每次迭代中计算 MAE(平均绝对误差)、MSE(均方误差)、RMSE(均方根误差)、R2(R2 分数-R 平方值)、MAPE(平均绝对百分比误差)。最后,它显示这 10 次迭代中所有误差的平均值和标准偏差。机器学习模型的错误越少越好!因此,为了减小误差,我们试图找出能使误差最小的超参数。

为此,我们应用 tune_model 函数并应用 K-fold 交叉验证来找出最佳超参数。

模型的超调

**xgboost = tune_model(xgboost, fold=5)**

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

超调后出错

该模型运行 5 次迭代,并给出所有误差的平均值和标准偏差。5 次迭代后,GBR 和 XGBoost 模型的平均平均误差几乎相同,但在超调并进行预测后,XGBoost 模型的误差更小,表现优于 GBR 模型。

使用最佳模型进行预测

**predict_model(xgboost)**

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

做出预测

应用交叉验证后检查分数(我们主要需要平均绝对误差)。这里我们可以看到,最佳模型的平均误差已降至 10847.2257,因此平均绝对误差约为 10,000。

检查 xgboost 模型的所有参数

**print(xgboost)**

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

检查超参数

XGBoost 模型超参数

**plot_model(xgboost, plot='parameter')**

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

检查超参数

残差图

实际值和预测值之间的距离(误差)

**plot_model(xgboost, plot='residuals')**

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

残差图

我们可以清楚地看到,我的模型过度拟合,因为训练集的 R 平方是 0.999,测试集是 0.843。这其实并不奇怪,因为我的数据集总共只包含 168 行!但是这里的要点是强调 Pycaret 的优秀特性,因为您只需一行代码就可以创建图表和曲线!

绘制预测误差

**plot_model(xgboost, plot='error')**

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

预计误差

该模型的 R 平方值为 0.843。

厨师距离图

**plot_model(xgboost, plot='cooks')**

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

库克距离图

学习曲线

**plot_model(xgboost, plot='learning')**

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

学习曲线

验证曲线

**plot_model(xgboost, plot='vc')**

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

验证曲线

这两个图也向我们显示了模型明显过度拟合!

特征重要度图

**plot_model(xgboost, plot='feature')**

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

特征重要性

通过这个图,我们可以看到 Processor_Type_i9 (i9 CPU)是决定笔记本电脑价格的一个非常重要的特性。

将数据集分割成训练集和测试集

**from sklearn.model_selection import train_test_split
X_train,X_test,Y_train,Y_test = train_test_split(X,Y,test_size=0.2)**

部署的最终 XGBoost 参数

**final_xgboost = finalize_model(xgboost)**

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

XGB 模型的最终参数

对未知数据(测试集数据)进行预测

**new_predictions = predict_model(xgboost, data=X_test)
new_predictions.head()**

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

测试集上的预测

保存转换管道和模型

**save_model(xgboost, model_name = 'deployment_08082020')Transformation Pipeline and Model Succesfully Saved deployment_08082020 = load_model('deployment_08082020')Transformation Pipeline and Model Sucessfully Loadeddeployment_08082020**

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

最终机器学习模型

所以这是最终可以用于部署的机器学习模型。

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

模型以 pickle 格式保存!

更多信息,请查看文档此处

在这篇文章中,我没有详细讨论每件事。但是你可以随时参考我的 GitHub 资源库 获取完整代码。我从这篇文章得出的结论是,不要期待一个完美的模型,而是期待一些你今天可以在自己的公司/项目中使用的东西!

喊出 Moez Ali 为这个绝对辉煌的图书馆干杯!

在 LinkedIn 上与我联系 这里

底线是自动化降低了人为错误的风险,并为企业系统增加了一些智能。—史蒂芬·艾略特

我希望你觉得这篇文章很有见地。我很乐意听到反馈,以便即兴创作,并带来更好的内容。

非常感谢您的阅读!

利用 BigQuery 和 Google 分析数据

原文:https://towardsdatascience.com/leveraging-bigquery-with-google-analytics-data-b6085d8415b?source=collection_archive---------17-----------------------

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

作者照片

谷歌分析是一个了不起的工具。它使您能够让数据为您服务,获得更广泛的图片,并更好地了解您的访问者。

当你对这个“报告”工具有更多期望时,问题就来了。我会告诉你为什么你应该考虑利用 BigQuery(或类似的工具)以及你的谷歌分析数据。

目录:

A.为什么要将 BigQuery 与谷歌分析数据结合使用?

B.用 BigQuery 查询 Google Analytics 数据

一.如何运作?

二。先决条件

三。我们来查询一下

A.为什么要将 BigQuery 与谷歌分析数据结合使用?

3 个原因:

1。处理随时间变化:

随着时间的推移,每个网站都会经历变化。与此同时,存储数据的方式也将发生变化。因此,为了进行苹果之间的比较,您需要将数据转换成一个通用的视图。

2。数据采样

如果你依赖 Google Analytics,你会知道 GA 经常对其数据进行采样。只要你没有足够的建模数据或者你使用的是现成的报告,GA 会给你 100%准确的数据。只有当你开始过滤数据或增加其基数时,谷歌分析才会开始按比例对数据进行采样,以保持其速度。

*采样:在采样过程中,GA 会根据较小的样本空间而不是整个数据池返回指标。

3。缺乏数据操作和转换

一旦数据存储在分析服务器中,您将无法使用公式或其他逻辑修改数据。这一点非常重要,因为对于一个拥有大量受众和多种内容类别的网站来说,数据分类和转换的空间总是很大。此外,在一些情况下,您需要清理数据。这些场景可能是人为错误、实施出错、谷歌分析遗漏的机器人。如果你想知道更多关于识别被谷歌分析遗漏的机器人的信息,阅读我关于这个主题的文章

B.利用 BigQuery

BigQuery 是一个基于云的数据仓库工具,可以让你以闪电般的速度存储和分析数 Pb 的数据。对于 GA 360 用户,Google 为你提供了将网站每日会话数据转储到 BigQuery 的选项。你可以利用这些数据来克服谷歌分析的局限性。

一、如何运作?:

  1. Google Analytics 每天都将其会话数据存储在 BigQuery 服务器中。这个会话数据是一个表,其中每一行都专用于一次用户访问,而每一列都代表一个不同的维度或指标,可以重复和嵌套。大致来说:A 列:访问者 Id 或 cookie id,B 列:会话日期。当表在一行中存储所有的点击量(事件)、页面浏览量和定制维度时,它就变得复杂了。这就是 BigQuery 不同于平面表系统的地方。

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

BigQuery 中的 Google Analytics 数据示例(作者提供图片)

2.这个表作为我们的输入。首先,我们通过展平这个复杂的嵌套数据来取消嵌套和缝合。然后,我们根据需要把它缝回去。

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

扁平化数据(作者照片)

3.作为一个合适的基于云的 ETL 工具,它为我们提供了很好的转换特性,并以很快的速度返回未采样的数据。

在接下来的章节中,你将深入了解 Google Analytics 如何存储和计算所有报告。期待一些创造性的想法出现在你的脑海中,找到谷歌分析无法提供的答案。

二。先决条件

下面几节将期待谷歌分析指标的基本知识和 SQL 的一些知识。这是一篇来自“LovesData”的 Benjamin 的伟大文章,用来修正 Google Analytics Metrics 概念。我最喜欢的教程网站:W3 School 提供的另一个很棒的修改 SQL 概念的教程

三。让我们查询

下面是存储在 BigQuery 中的 Google Analytics 数据的详细模式。我将首先从高级和基本的指标开始,如会话、用户等,然后逐渐转向更深入和复杂的指标。有两种方法可以计算高级指标:第一种方法是查询表中的“总计”记录;第二种方法是查询扁平表(将复杂数据结构解析为扁平表)并应用相关逻辑。对于这篇博客中的所有指标,我将采用第二种方法。我们将使用这个特殊的数据集进行学习

  1. 用户

该表包含一个名为“完整访问者 Id”的字段。这只是一个 cookie ID,对于机器上的浏览器是唯一的。因此,如果您可以找到这些 id 的不同数量,您就可以找到用户的数量。

Select
Count ( Distinct fullVisitorId) as Usersfrom
`bigquery-public-data.google_analytics_sample.ga_sessions_20170801` , UNNEST(hits) AS hits

2.会议

除了“完整访问者 id”字段,该表还包含“visitNumber”等字段,这是该用户特定会话的序列号(完整访问者 Id)。此外,“visitStartTime”表示会话开始的时间。如果我们将这些术语连接起来并找到不同的计数,我们将得到会话的数量。

SelectCount ( DistinctCASE
WHEN totals.visits=1 THEN
CONCAT( fullvisitorid,"-",CAST(visitNumber AS string),"-",CAST(visitStartTime AS string))End)
as Sessionsfrom
`bigquery-public-data.google_analytics_sample.ga_sessions_20170801` , UNNEST(hits) AS hits

3.浏览量

为了计算浏览的页面数量,我们将通过计算会话中页面浏览点击/事件的次数来使用“点击类型”字段。

SelectSUM(
Case when hits.type="PAGE" then 1 else 0 END
)as Pageviewsfrom
`bigquery-public-data.google_analytics_sample.ga_sessions_20170801` , UNNEST(hits) AS hits

4.独特的浏览量

通过忽略一个会话的重复浏览量来计算唯一浏览量。如果页面 A 在一个会话中有 2 次浏览量,A 的唯一浏览量将只有 1 次。

因此,我们需要会话标识符和页面标识符的组合,并对该组合进行唯一计数。

SelectCount ( Distinct 
CONCAT( fullvisitorid,"-",CAST(visitNumber AS string),"-",CAST(visitStartTime AS string),"-",hits.page.pagePath)
)as Unique_Pageviewsfrom
`bigquery-public-data.google_analytics_sample.ga_sessions_20170801` , UNNEST(hits) AS hits

5.跳出率

退回是指只有一个交互事件的会话。为了计算这一点,我们将计算总反弹,并除以会话数。

SELECT
Page,( ( bounces / sessions ) * 100 ) AS Bounce_Rate,
SessionsFROM (SELECThits.page.pagePath AS Page,Count ( Distinct
CASE
WHEN totals.visits=1 THEN
CONCAT( fullvisitorid,"-",CAST(visitNumber AS string),"-",CAST(visitStartTime AS string))
End)
as Sessions,SUM ( totals.bounces ) AS Bouncesfrom
`bigquery-public-data.google_analytics_sample.ga_sessions_20170801` , UNNEST(hits) AS hitsGROUP BY
Page )
ORDER BY
Sessions DESC

6.入口

入口是通过使用一个名为 isEntrance 的字段来计算的。如果命中是会话的第一个,则该字段的值为“真”。

Select
hits.page.pagePath AS Page,SUM(
CASE
WHEN hits.isEntrance = TRUE and hits.type="PAGE" AND totals.visits=1 THEN 1
ELSE 0
END
) AS Entrances,from
`bigquery-public-data.google_analytics_sample.ga_sessions_20170801` , UNNEST(hits) AS hitsgroup by Page

7.出口

类似地,也有一个专用于出口的字段。如果点击是该会话的最后一次点击,则设置为 TRUE。

Select
hits.page.pagePath AS Page,SUM(
CASE
WHEN hits.isExit = TRUE and hits.type="PAGE" AND totals.visits=1 THEN 1
ELSE 0
END
) AS Exits,from
`bigquery-public-data.google_analytics_sample.ga_sessions_20170801` , UNNEST(hits) AS hitsgroup by Page

8.平均会话持续时间

用于计算参与度指标 Avg。会话持续时间,我们将首先计算每个会话的总持续时间。这是通过找到该会话中交互点击的点击时间来完成的。然后,将这个持续时间汇总到一个维度(如 Channel)中,并除以会话数。

Select Channel, SUM(Total_Session_Duration)/Count(Distinct Session) as Avg_Session_Duration
from(SelectChannel, Session,MAX(hitTIme)as Total_Session_Durationfrom(SelectchannelGrouping as Channel,case when totals.visits=1 then CONCAT( fullvisitorid ,"-",Cast(visitNumber as string),"-",cast(visitStartTime as string)) end as Session,Case when hits.IsInteraction=TRUE then  hits.Time/1000 else 0 end as hitTime,from
`bigquery-public-data.google_analytics_sample.ga_sessions_20170801` , UNNEST(hits) AS hits

 )
 group by channel, session)group by Channel

9.页面上的平均时间

计算一个页面的平均时间类似于计算 avg。会话持续时间。主要区别在于,我们汇总了特定页面的最后交互点击的时间戳,而不是会话的时间戳。

select 

  Page, SUM(TIMEOnPage) as TimeOnPage, SUM(Exits) as Exits, SUM(Pageviews) as Pageviews,
  safe_divide(SUM(TIMEOnPage),(SUM(Pageviews)-Sum(Exits))) as Avg_Time_On_Pagefrom(SELECT
  Sessions, Page, Pageviews,

 Case when exit =TRUE 
  then  LastInteraction-hitTime
  else  LEAD(hitTime) OVER (PARTITION BY Sessions ORDER BY hitseq) - hitTime
  end  as TimeOnPage, 

  Exits
FROM (
  SELECT
   CASE
      WHEN totals.visits=1 THEN CONCAT( fullvisitorid,"-",CAST(visitNumber AS string),"-",CAST(visitStartTime AS string))
  END
    AS Sessions,

    hits.Page.pagePath AS Page,
    hits.IsExit AS exit,
     Case when hits.Isexit =TRUE 
  then 1 else 0 end As Exits,
    hits.hitNUmber as hitSeq,
    hits.Type AS hitType,
    hits.time/1000 AS hitTime,

    CASE
      WHEN type="PAGE" AND totals.visits=1 THEN 1
    ELSE
    0
  END
    AS PageViews,
    MAX(
    IF
      (hits.isInteraction =TRUE
      ,
        hits.time / 1000,
        0)) OVER (PARTITION BY fullVisitorId, visitStartTime) AS LastInteraction,

 from
 `dm-corp-marketing-001.137933647.ga_sessions_20200803` , UNNEST(hits) AS hits

    order by Sessions,hitSeq
    )
WHERE
  hitType='PAGE'
  )
  group by Page order by Pageviews  desc

10.基于事件的目标

如果您想要计算基于事件的目标的总完成数,您需要计算发生该事件的会话数。以下示例计算了事件类别的目标完成情况:销售线索生成和事件活动:手册下载。我使用的是正则表达式筛选器,而不是“等于”运算符;在这种情况下你可以使用任何一个。

SelectCount( distinctCASE  WHEN 
REGEXP_CONTAINS(hits.eventInfo.eventAction,r'^Brochure Download$') AND 
REGEXP_CONTAINS(hits.eventInfo.eventCategory,r'^Lead Generation')THEN CONCAT( fullvisitorid,"-", CAST(visitStartTime AS string) ) 
end)as Goal_Lead_Generationfrom
`bigquery-public-data.google_analytics_sample.ga_sessions_20170801` , UNNEST(hits) AS hits

11.第 n()页路径

如果你想看到最常见的第 n()页比如最常见的第 1 页(登陆页),最常见的第 2 页(登陆页之后的页面)等等,那么这段代码就是为你准备的。您可以操作这些代码来查看不同的页面流,直到第 n()级和顶级页面路径级,还可以查看这些“数据视图”以了解特定的行为,如转换、设备类型等。

SELECT
    second_page_path, count (distinct SessionIdentity) as Sessions
  FROM (
    SELECT
      CASE
        WHEN totals.visits=1 THEN CONCAT( fullvisitorid,"-",CAST(visitNumber AS string),"-",CAST(visitStartTime AS string))
    END
      AS SessionIdentity,

      CASE
        WHEN hits.isEntrance=TRUE THEN hits.page.pagePath
    END
      AS Landing_Page,
      CASE
          WHEN hits.isEntrance = TRUE THEN LEAD( hits.page.pagePath,1) OVER (PARTITION BY fullVisitorId, visitNumber ORDER BY hits.type)
        ELSE
        NULL
      END
        AS second_page_path,
        CASE
          WHEN hits.isEntrance = TRUE THEN LEAD( hits.page.pagePath,2) OVER (PARTITION BY fullVisitorId, visitNumber ORDER BY hits.type)
        ELSE
        NULL
      END
        AS third_page_path,
        CASE
          WHEN hits.isEntrance = TRUE THEN LEAD( hits.page.pagePath,3) OVER (PARTITION BY fullVisitorId, visitNumber ORDER BY hits.type)
        ELSE
        NULL
      END
        AS fourth_page_path,
        CASE
          WHEN hits.isEntrance = TRUE THEN LEAD( hits.page.pagePath,4) OVER (PARTITION BY fullVisitorId, visitNumber ORDER BY hits.type)
        ELSE
        NULL
      END
        AS fifth_page_path,

   from
`bigquery-public-data.google_analytics_sample.ga_sessions_20170801` , UNNEST(hits) AS hits
   ORDER BY
      SessionIdentity,
      Landing_Page)
  WHERE
    SessionIdentity IS NOT NULL
    AND landing_page IS NOT NULL
  GROUP BY
    second_page_path

  ORDER BY
    Sessions Desc

最后,我要说 BigQuery 是利用 GA 数据的一个很好的工具。它为你提供了查看数据的自由,这是通过谷歌分析无法看到的。

认识作者: www.sumilmehta.in

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值