Power BI: M 与 DAX 以及测量值与计算值列
刚开始学 Power BI 时希望知道的基础知识。
当我踏上我的权力 BI 之旅时,我几乎立即被一股外来的和令人困惑的术语打了耳光,这些术语似乎都做着相似但又有些不同的事情。
这里有一种叫做 M 的语言,但也有一种叫做 DAX 的语言?计算列和度量值有什么区别?我应该在什么时候使用超级查询?
在我的旅程中,我很早就陷入了试图理解一些关键概念的困境,这些概念使 Power BI 看起来更加困难和混乱。我几乎放弃了我的商业智能抱负,爬回到我熟悉的伙伴 Excel 身边。最好是你认识的恶魔,对吧?不对!
我是如此,如此,如此高兴,以至于我一直用头撞墙来克服最初的障碍。今天我几乎每天都在用 Power BI,而且是兴高采烈地用,甚至是兴高采烈地,很少用 Excel。但是来到这里很难,真的很难。这比想象的要难,因为很长一段时间以来,我对一些关键的 Power BI 概念没有清晰的概念性理解。
我会尽量让事情简单,只给你一个提示,一个色调,一个味道让你开始。
更有经验的 Power BI 用户可能会对我简化和减少这些概念的方式感到畏缩,但是你知道吗?在这一点上,所有的细微差别和细节真的无关紧要。你需要一个开始的地方。相信我,复杂性会来的。
所以,我无畏的战士,我的学徒,我未来的力量 BI 大师,这里有一个非常基本的概述:
- 电量查询和 M
- DAX
- 计算列和度量
- Power Query vs. DAX
电源查询和 M
这到底是什么?这是一切的开始。Power Query 是将数据导入 Power BI 的地方。m 是 Powery Query 使用的编码语言。您可以通过点击来使用 Power Query,M 中的代码将会自动生成。也可以直接用 M 写自己的代码。
我什么时候使用它?清理和格式化你的数据。你可以做诸如删除和添加列、过滤数据、改变列格式等事情。
我一定要用 M 吗?:简而言之,没有,你可以通过指向和点击来完成 Power Query 中的大部分事情,完全不需要使用 M。然而,了解 M 确实有助于使您的过程更加灵活,并且在将来更容易复制。例如,当使用 M 时,您可以复制并粘贴想要重用的代码,并且可以对您的步骤进行注释。
学习 提示:点击 打开 高级编辑器,在电力查询中做你需要做的事情。M 代码将出现在您刚刚完成的操作中。通过这种方式,您可以开始熟悉这种语言,并在尝试从头开始编写自己的 M 代码之前做一些小的调整。
足以让你变得危险。酷毙了。
towardsdatascience.com](/power-bi-understanding-m-5a3eb9e6c2da)
指数
这到底是什么? DAX 是数据分析表达式的缩写,一旦使用 Power Query/M 将您的数据提取到 Power BI 中,就可以使用它来创建度量和计算列。
我什么时候使用它?:使用 DAX 本质上就像在 Excel 中使用公式——它允许你根据你的数据进行计算。您可以使用 DAX 创建计算列或度量值。
计算列和度量
这到底是什么?计算列和度量是 DAX 中编写表达式的两种方式。计算列将为表中的每一行创建一个包含值的附加列。度量是基于一个表或多个表中的多行的聚合表达式。
什么时候应该对计算列进行度量?我很高兴你问了,因为我真的很纠结这个问题。这是一个棘手的问题,因为您通常可以使用度量值或计算列(但这并不意味着您应该这样做)。
关于度量和计算列要记住的事情:
- 当你可以使用任何一个时,使用测量
- 当您希望将计算列用作筛选器或切片器时,或者如果您希望创建类别(例如,添加一个根据任期包含“新员工”、“员工”或“高级员工”的列),通常会使用该列。
- 如果您想根据用户选择的内容进行计算(例如,计算切片器中所选部门的总收入),您需要使用度量值
如果计算列和度量之间的区别现在还不完全有意义,那也没关系。 尝试创建一个度量和一个计算列,看看它们是否都符合您的要求。如果是的话,很好,用这个方法。如果只有计算列有效,就用它吧!
幂查询(M)还是DAX?
这里的事情也让我感到困惑,因为似乎我在 Power Query/M 中可以做的大部分事情,在 DAX 中也可以做。我应该在什么时候使用哪一个?
简答:在可能的情况下使用 Power Query/M。(这里很少使用的一个大例外是,如果您试图创建一个引用不同表中的列的计算列。在这种情况下,使用 DAX 创建一个计算列)
长回答: 看这个。
就这样,你做到了!您通过对幂查询、M、DAX、measures、和计算列的基本概念化完成了它。如果你现在不明白所有的区别和用途,那也没关系!你已经奠定了基础,这是朝着正确方向迈出的一大步。
要记住的事情:
- 超级查询是一切开始引入和清理您的数据的地方。
- M 是 Power Query 中使用的语言(不一定要直接使用 M,但是从长远来看让你的生活更轻松)。
- DAX 是在 Power BI 中创建计算列和度量时使用的语言。
- 如果您 可以在 Power Query/M 中 做到,您 应该 (除了当您向引用不同表中的列的表添加列时)。
- 如果一个计算列或一个度量可用, 使用一个度量。
后续步骤:
让这些概念在你的大脑中扎根的最简单、最快的方法就是接触和练习。以下是一些很好的入门资源:
[## 2021 年新品:通过每周挑战学习 Power BI
最后,Power BI 用户的每周挑战。以下是我如何完成第一次每周挑战的分步指南…
jeagleson.medium.com](https://jeagleson.medium.com/new-in-2021-learn-power-bi-with-weekly-challenges-8742db48a52)
虽然我非常鼓励参与所有精彩的资源,但没有什么比自己尝试一些事情并看看会发生什么更能帮助你了。
继续用你的头撞墙。会变得更好。
功率 BI 建模
一些提示。但愿我以前认识他们。
当你想到模特,你会想到什么?很多复杂的连接,查找,或者仅仅是挫折?
你以前经历过这种情况吗?你有一个度量,但它并没有给你正确的答案。你想知道为什么。您不确定原因,所以您调整了度量。也许是表中的某个东西,也许是数据问题,所以您也可以在 Power Query 中调整它。然后你会一无所有…
作者图片
嗯,我经历过。我已经尝试了几种解决问题的方法,但实际上这些方法并没有什么特别之处。
更确切地说,大多数时候解决方案是模型本身。
我能想到为什么建模很重要的三个原因。
- 它简化了你的 DAX 公式。
- 它让你明白了为什么权力查询很重要。
- 它给你谈判的权力
它简化了你的 DAX 公式
…怎么做?这里有一个我以前遇到过的模型。
作者图片
在这里,城市以多对一的关系连接到县表。然后是县与地区的多对一关系。
该日期以多对一关系联接到月表。在多对一的关系中也是几个月到几年。
如果我想获得某个特定地区的销售额,我可以写 CALCULATE(SUM(FACT[Sales]),FILTER(REGION,REGION[Region] == "North "))。
现在,为什么区域表离它那么远?在这里,权力 BI 必须通过市、县并最终到达地区。
如果我想按月份和年份获取特定的销售额,我可以编写 CALCULATE(SUM(FACT[Sales]),FILTER(YEARS,YEARS[Year]==2000),FILTER(MONTH,MONTHS[month]==12
这不是完全错误的,你可能会得到结果。(想象一下,放置一个矩阵视图,向下拖动一个简单的 SUM(FACT[Sales])度量,其中的行是年、月或地区等)。
问题是功率 BI 必须经过两个独立的表才能得到测量值。如果是一个小表,这没什么大不了的,但是当你在处理一个大的数据集时,你自己去读和 Power BI 去过滤这些表以得到你的答案将是非常困难的。
对于 Power BI 类型的报告,最好将维度表放在一起。
考虑维度主题。
作者图片
我们现在使用的是星型模式,
蓝色=日期主题 —假期等应添加到此表中,而不是其他地方。
绿色=员工数据主题 —个人信息和其他新字段应该在这里。
橙色=位置主题 —任何新位置都应添加到此处。
如果您心中已经有了主题,那么您就可以确定哪些表应该属于彼此。
这种设置有助于您整理多个表,并帮助您理解模型。将来可能会添加其他维度表,但是现在您已经知道它们应该放在哪里了。
一个更简单的模型让你欣赏权力查询
现在您已经有了一个模型,是时候决定如何正确地连接这些表了。
是的,你可以在 DAX 中做一些映射,你可以写-RELATED(REGION[REGION])来引入列并隐藏区域表。会有用的,但为什么要这么做?
这就是微软所说的 Power Query 可以用来“准备”或“塑造”数据的意思。
在 Power Query 中,您可以执行这些连接。
作者图片
Power Query 中的 Shaping 也有一些优点,您可以轻松地进行反连接双重检查,查看是否有月份没有反映在 Years 表中。
这里有一篇文章,如果你想知道如何做这些加入权力查询。我个人希望之前有人告诉我这些。这将使我从许多令人头痛的数据中解脱出来。
它给你谈判的权力
建模可以帮助你马上找出你能回答什么样的问题。(您的度量可以基于事实表构建,并根据维度或“主题”进行切割)。
这是你的底线。如果有人问你一个商业问题,你已经可以从你的模型中判断出你是否能为他们得到这个问题,与查看表格并计算出这个问题相比,你将对你能回答什么和不能回答什么有很好的感觉。
如果需要额外的见解,那么,您现在可以根据模型从其他单位获得更多的数据。如果需要其他维度,您已经知道如何在您的模型中连接它们。
这是你应该追求的目标,它从未让我误入歧途。
- 明星模式 —爱明星
- 目标 1:每个维度表到事实表的多种关系
- 思考空间主题
- 不同级别的详细信息—事实表中的天数与预算表中的月份?使用日期表格
- 杠杆力量查询,值得等待。做连接以达到“主题”
我明白,有时候工作没那么简单。有时候你只需要尽快得到答案。做模特是你最不可能想到的事情。
但是请这样想——您需要花费大量的时间来制定措施和进行故障排除,您还不如一开始就投资一个合适的数据模型呢!😃
功率 BI 建模误差
当一个模型没有加载时,应该怎么做
里克·梅森在 Unsplash 上的照片
当你使用 Power BI 工作时,你不可避免地会经历这样的事情。
作者图片
那些话。“模型无法加载”——这让我…畏缩。
如果你的模型没有加载,那是因为一个转换在幂查询中失败了。
如果你需要了解如何建立一个模型,看看这篇文章。谢谢大家看完。
如果你需要复习连接——这里有第 1 条和第 2 条。是的,它们也会导致错误,而且更微妙,代价更大。
让我们来看看这些错误信息。
其中一个表出现故障。
作者图片
在上图中,Power BI 表示它想要加载模型,但是由于“previous”表,它无法加载模型。
该错误由[表达式描述。Error]部分,这个错误所在的表就是您在 Power Query 中需要解决的问题。
【表情。错误]—错误的数据类型。
上面的错误消息表明我有一个空值,但是 Power Query 无法将其转换为逻辑值。
这里是如何修复它,并考虑它
- 缺少值 —如果您正在使用的列需要转换为逻辑列,首先询问它们为什么缺少。在我的情况下,这是一个数据错误的来源。源中缺少的值突出显示了查询中的某些问题。
- 删除错误或替换错误。这些选项可以通过右击该栏上的找到。由于某种原因,空值或缺失值没有正确加载,但我知道它们都应该是 0,所以我使用了
- 替换错误,它加载得很好。
【表情。错误] —数据类型再次出错
我试图做一个单位 x 价格,但价格栏是文本。因此出现了错误。
作者图片
错误消息非常清楚——不能将运算符*应用于数字和文本。
您可以通过在包含文本的列上右键单击>更改类型>整数来修复此错误。
【表情。错误]-缺少列
由于转换步骤失败,Power Query 无法加载此表。这种类型的误差被认为是步级误差。这里有一个很好的例子。
作者图片
我已经从前面的步骤中删除了列,然后在接下来的步骤中,我开始引用以前删除的列。这将导致错误。
这种类型的错误很可能是由于在完成查询后对前面的步骤进行了更改而导致的。记住 M 使用逐步转换,所以如果您对一个步骤进行了更改,您将会影响另一个步骤。
以下是你可以修复它的方法。
- 您可以通过再次加载缺少的列来修复此错误。Power Query 需要这个专栏来完成它的转换。
- 您也可以选择添加一个[MissingField。我不确定最后一个参数,有时标记一个错误是为了让你看看需要修复什么。无论如何,我想我应该让你知道这个参数是存在的。
以下是在[missing]字段中添加内容时发生的情况。忽略]参数。
作者图片
它装载得很好。
如果你想知道更多关于这个参数的信息,这里有一个链接。我最近发现了这个博客,它很棒。
数据格式。错误
这是一个转换错误。Power Query 希望为您加载表,但是有一个值无法转换为您指定的数据类型。
作者图片
这个错误有点令人困惑,因为列数据类型是 number,所以您会认为它已经成功地将列转换成了 number。
Power Query 通过前 1000 行检测列的数据类型。此错误表明在您的源中的某个地方,在 1000 行之后,有一个值“11A11”,而 Power Query 不知道如何将它转换成数字。
这里是如何解决和思考它
- 用源代码中的正确数字替换错误。如果它在二进制文件中,你可以在你的文件中替换它。
- 先问问为什么会发生。也许是更大的事情?这些数据错误有多少?请记住,您正在创建一个模型,度量和指标将建立在这个模型之上。越早抓越好。
- 如果您选择排除这些行,您也应该能够解释为什么。(如果您建立了指标,有人问为什么某些指标不等于总人口)
- 如果您知道这是一个奇怪的现象,并且您没有足够的时间加载二进制文件(太大了!)并对其进行更改,您可以利用 Power Query 的过滤器过滤掉这些值。(这是一个奇怪的现象,不要在意这种情况)。
数据源。错误
超级查询指示无法加载数据源,因为它找不到文件。如果表无法加载,模型也无法加载。
用户拥有不同的驱动器访问权限可能会导致 It 错误。例如,您可以访问驱动器“A:”并且源代码保存在那里。您的同事无权访问此驱动器,因此他们无法加载它。
以下是你可以修复它的方法。
- 您可以选择编辑设置来改变电源查询窗口中的源位置。如果只有你在使用 PBI 文件,这是一个快速的解决方法。
2.您还可以为数据源设置一个参数。
作者图片
在这里,我创建了一个可以访问源文件的用户名列表。
作者图片
我可以去数据源设置>高级>选择目录中用户名类别上的参数。
文件路径将根据您选择的用户名而改变。
如果你的文件路径因为任何原因而改变,你可以选择你的参数,你的文件路径也会随之改变。如果你需要,这里有更多关于 Curbal 的细节。这是一个很好的渠道。
防火墙。错误
这种事不常发生在我身上,但一旦发生了,我花了很长时间才弄明白。基本上跟隐私设置不同有关。
例如,查询 A 的隐私级别设置为 Private,查询 B 的隐私级别设置为 Public。这可能会导致错误。
如果您合并 A 和 B 的结果,观众现在将能够看到什么是私人的。
你有两个选择来解决这个问题
- 忽略选项和设置下的所有隐私设置
- 将查询分成两个不同的查询
你可以在这里获得更多信息
连接错误
这个错误可能是代价最大的。
如果你之前没有读过任何内容,请阅读下面的内容。
这很重要,因为您的查询将会运行,您的模型将会加载,但是数据不正确。
让我展示给你看,
我有表 A 和表 B,它们都有相同的 ID 列。我正在做一个简单的内部连接。
作者图片
返回了不正确的连接结果,Power Query 也没有抛出任何错误。内部连接只匹配 5 行中的 3 行,尽管我们知道它应该返回 5 行。(所有 ID,1-5 都在两个表中)
很难发现这样的错误。您可能认为您的模型运行良好,但是经过进一步的检查,您意识到您实际上丢失了记录,这都是因为连接列中有一个空格。(这是 5 条记录,想象一下你有几千条?)
表连接但返回错误结果的原因是因为一些 ID 实际上在值后包含一个空格,所以 Power Query 将其作为一个全新的 ID。
如果我正在连接文本到文本,我会养成一个习惯,做一个修剪和清理,并确保所有的字符都降低。
在这个清洁过程之后,连接加载正常。
作者图片
我希望这篇文章能帮助你,错误是可以发生的。
我听过的最好的名言之一来自比利·穆雷。这也适用于工作。
“你越放松,你在所有事情上都做得越好——你和你爱的人相处得越好,你和敌人相处得越好,你的工作越好,你和自己相处得越好。”
错误时有发生,有时模型无法加载。这只是数据之旅的一部分。
保持放松。注意安全,玩得开心。😃
希望你喜欢这篇文章。
权力 BI:理解 M
足以让你变得危险。
酷毙了。来自突发的 Samantha Hurley 摄影。
当开始使用 Power BI 时,我很难理解 M 和 DAX 以及 measures 和 calculated 列之间的区别(如果你也是这种情况,这篇概述可能会有所帮助)。
TL;DR: Power Query 是您在 Power BI 中用来加载数据集并清理和操作数据的工具。m 是幂查询中使用的语言。你和我在一起吗?Power Query 和 M 令人惊叹,是 Power BI 与其他商业智能工具的重要区别。然而,也可能有一点学习曲线,这可能会阻止新用户在接触到好东西之前采用 Power BI。
为了帮助你跳过这个常见的障碍,我想和你分享一下我到目前为止学到的东西。这绝不是 M 或幂查询的详尽指南,但它会给你一切你需要知道的东西,让你度过难关,然后继续有趣的事情。
- 概念理解
- 开始学习的步骤
- 如何开始使用
对于那些想跟进的人,我将使用来自周一改造第 43 周的数据集。对于任何想在数据可视化方面有所发展的人来说,改造星期一是一个可怕的免费数据集每周挑战。
概念理解
当试图建立一个概念性的理解时,它帮助我思考 Power Query 和 M like 宏和 Excel 中的 VBA。
在 Excel 中,创建宏时,可以通过以下方式完成:
- 使用“记录宏”功能,方法是在整个过程中点击鼠标
- 使用 VBA 并自己编写代码
同样,在 Power Query 中,您可以通过点击来完成您想要完成的任何数据操作,或者您可以使用语言 M 为该过程编写代码。同样,M 是一种语言,在 Power Query 中用于加载和清理数据集。
侧边栏:M 与 DAX 完全分离。 DAX 是您在使用 Power Query 完成诸如创建一个给定年份总销售额的度量值之类的事情之后使用的。好了,言归正传。
我什么时候用 M?
当您将新的数据源加载到 Power BI 中时,步骤#1 应该总是进入 Power Query。总。即使您的数据是绝对完美的,并且您不必做任何清理或操作(必须很好),您仍然应该在 Power Query 中启动,以确保一切都按预期加载。
有两种方法可以访问电源查询。加载新数据源时,您可以单击“转换数据”而不是“加载”,也可以随时单击主页功能区中的“转换数据”。
在这个视图中,您将在左侧看到针对您添加的每个数据源的查询,在中间看到数据预览,然后在右侧看到应用的步骤。在您执行任何操作之前,您会看到 Power Query 已经为您完成了许多步骤:
您会注意到,每次您在 Power Query 中做一些事情(例如,过滤数据、删除列等。)您会注意到会自动为您添加一个步骤。非常漂亮,但是这里到底发生了什么呢?
每当你点击完成一个步骤,Power BI 就在后端用 M 语言为你编写命令。同样,这就像我们在 Excel 中记录一个宏,而 VBA 是为我们编写的。
需要明确的是,在大多数情况下,您不需要使用 M 也可以很好地工作。但是,了解一些 M 的基本原理会有很大的帮助,并在将来为你省去很多麻烦。下面找出具体方法。
学习 M
作为一个没有耐心的人,当我可以很快地用鼠标点击东西的时候,我并没有打算学习一门全新的语言。
我不能坐下来用 M 从头开始写一个完整的查询。你知道吗?我永远不需要。我发现只要知道得足够多,我就可以快速有效地做我需要的任何事情。我跟大家分享一下我是怎么走到这一步的。
免责声明:对于那些想要深入探究本质并独立掌握这门语言的人来说,我保证你在这里找不到。你是一个比我更好的人,我祝你一切顺利。
学习 M 的 3 个步骤:
- 点击(没错,你听到了!)
- 注释这些步骤
- 进行调整
当学习 M 时,你也可以利用所有自动为你做的工作。所以从做一些指向和点击开始,只需几步。
我将筛选到 2020 年的数据,并删除月列。您将看到右边的 Applied Steps 面板中添加了两个步骤。
现在,我想看看引擎盖下面,看看 Power BI 为我创建的 M 代码。为此,我将从主页功能区中单击“高级编辑器”。触发警告:这将会看起来很恶心,让人不知所措,但请跟着我。
你会看到这样的东西:
let
Source = Excel.Workbook(File.Contents("C:\Users\jeagleson\Downloads\Week 43.xlsx"), null, true),
#"Week 43_Sheet" = Source{[Item="Week 43",Kind="Sheet"]}[Data],
#"Promoted Headers" = Table.PromoteHeaders(#"Week 43_Sheet", [PromoteAllScalars=true]),
#"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"Country", type text}, {"Year", Int64.Type}, {"Month", type text}, {"Exports (USD Millions)", Int64.Type}}),
#"Filtered Rows" = Table.SelectRows(#"Changed Type", each ([Year] = 2020)),
#"Removed Columns" = Table.RemoveColumns(#"Filtered Rows",{"Month"})
in
#"Removed Columns"
我到底在看什么?欢迎来到 m 是的。看起来很恶心。但是,请听我说,我将向您展示如何快速使它更具可读性,更容易理解。
首先,我建议您在显示选项下启用自动换行。这将使你可以一次看到所有的文本,而不必从左向右滚动。
关于 M 需要注意的一点是,你会看到每一步都有一个#并且在引号中。我也花了一段时间才意识到,你在每一步输入的第一件事就是前一步的名称。让我告诉你我的意思。我将从#“提升的标题”开始更改每个步骤的名称同样重要的是要注意,如果您的步骤名称中有空格,那么您只需要#"。我发现如果我把每一步的名字都写成一个单词,阅读起来会容易 547 倍。
现在,您可能希望将每个步骤命名为比步骤 2 更有意义的东西(例如,ChangeDataTypes),但希望这有助于说明我所说的每个步骤引用前一个步骤的意思。
一旦我在高级编辑器中点击完成,有趣的事情发生了。我们有相同的应用步骤,但它们现在反映了我们的新名称。
很酷吧。
现在,让我们花更多的时间在 M 上,仔细思考每一个步骤在做什么。再说一次,我们并不试图去记忆任何公式,只是试图去理解每一步发生了什么,以防我们以后需要做出改变。
我在每个步骤上面添加了一个注释,简要说明该步骤在做什么。在注释的开头添加一个“//”,这样 Power Query 就知道您不会试图在 M 中键入某些内容并忽略它。“//”告诉编辑,你只是在自言自语,而不是试图用 m 告诉它什么。
您可以在高级编辑器和点击之间来回切换,这样您就可以在进行的过程中为每个步骤添加注释。但是现在,当我再次点击完成,你会看到另一件很酷的事情发生了。现在每个步骤都有一个信息图标,我可以将鼠标悬停在上面查看我的评论。我可以将鼠标悬停在每个步骤的图标上,查看它在做什么,而不必再次打开高级编辑器。
这越来越令人兴奋了,你说呢?
使用 M
现在我们已经了解了 M 是什么,并且我们已经习惯了在高级编辑器中导航,我们准备开始使用一些 M 来使我们的生活变得更加容易。再说一次,我支持从点击开始,然后在高级编辑器中做一些小的调整。以下是一些例子:
- 更新源文件位置 假设我想用第 44 周的数据更新我的 Power BI 文件。我简单地打开我的高级编辑器,在第一个 Source =步骤中,我把我的文件路径从“C:\ Users \ jea gleson \ Downloads *Week 43*。xlsx " to " C:\ Users \ jea gleson \ Downloads *第 44 周*。xlsx "
- 处理源文件结构的更改 我经常遇到的情况是,我想更新我的 Power BI 文件,但我的源文件已被更改。例如,更改了列名,或者添加或删除了列。Power BI 真的很不喜欢出现这种情况。没有办法通过指向和单击来处理这一点,但是在 m 中进行调整是轻而易举的。假设我的源文件现在在“国家”列之后有一个“地区”列。我需要做的就是进入我的高级编辑器,使用与其他列相同的格式添加区域列:
Step2 = Table。TransformColumnTypes(Step1,{{"Country ",type text}, {"Region ",type text} ,{"Year ",Int64。Type}、{"Month “,type text}、{ " Exports(USD million)”,Int64。Type}}),
现在,我想说清楚,M 可以做很多很酷的东西。尤其是当你想开始创建和重用函数的时候。但是,当你开始的时候,过分沉迷于 M 的杂草中是有害的,它会不必要地减慢你的进度。我鼓励你首先在 Power Query 中点击鼠标,然后查看高级编辑器并做一些小的调整,以适应 m。然后,一旦你适应了,天空就是极限!
如果您想了解更多关于 Power Query 和 M 如何适应 DAX 和其他 Power BI 概念的信息,您可能会发现这很有帮助:
[## Power BI: M 与 DAX 以及测量值与计算值列
我希望我刚开始时就知道的基础知识。
towardsdatascience.com](/power-bi-m-vs-dax-vs-measures-4c77ae270790)
其他一些有用的 M 技巧:
- 每个查询都以“let”开头
- 每个查询都以“in”和 LastStepName 结尾
- 每一步后面都有一个逗号,除了最后一步,最后一步没有逗号
- 我通常是这样想每个步骤的:
NameOfStep = Function(NameOfPreviousStep,Function stuff), - 如果您的列包含数字,您很可能会使用数据类型“Int64”。类型”——我不明白他们为什么不能制造这个“数字”
准备好测试你学到的东西了吗?请查看这一每周一次的 Power BI 挑战赛:
[## 2021 年新品:通过每周挑战学习 Power BI
最后,Power BI 用户的每周挑战。以下是我如何完成第一次每周挑战的分步指南…
jeagleson.medium.com](https://jeagleson.medium.com/new-in-2021-learn-power-bi-with-weekly-challenges-8742db48a52)
继续用你的头撞墙,这样会好很多!
詹娜·伊格尔森我的背景是工业组织心理学,我在人物分析中找到了自己的家。数据使我的作品变得生动。我主要使用 Power BI,但偶尔也会使用 Tableau 和其他工具。我很想听到更多关于你的旅程!在此评论或在Linkedin或Twitter上留言联系我。
权力 BI vs 画面 vs 知识 I
比较三种功能强大的 BI 工具的特性和使用案例
由 Unsplash 上的 Max Leveridge 拍摄的照片
在当今围绕数据科学和机器学习的所有讨论中,人们可能会认为商业智能(BI)已经失去了它的重要性。但他们大错特错,因为大企业实际上比以往任何时候都更依赖商业智能和数据科学来增强决策。许多采用传统商业模式的公司正在向数字化转型迈进。根据的一份报告,2019 年商业智能市场规模为 205 亿美元,预计到 2025 年将增长至 405 亿美元,CAGR 为 12%。
Tableau 仍然是商业智能工具的市场领导者,而微软也通过几年前推出的 Power 阿碧扩展到了商业智能工具领域。我们也有像 Knowi 这样相对较新的初创公司,它们正试图拓展传统商业智能的边界。所有这些也表明,商业智能仍然是一个活跃的领域,在未来几年只会增长。
在 BI 工具中,由于 Power BI 和 Tableau 的广泛流行,我们看到了它们之间的许多比较。但是我们认为写一篇关于 Tableau 与 Power BI 与 Knowi 之间的三方面比较的文章会很有趣,并看看它们之间的关系。在开始比较之前,让我们先对它们进行一个介绍性的概述。
(舞台上由人扮的)静态画面
Tableau 徽标
Tableau 软件于 2003 年推出,从那以后经受住了时间的考验。如果我们纯粹从用户群的规模来判断,它显然是目前市场上所有 BI 工具中的赢家。在业务分析、报告和可视化功能中,Tableau 光鲜亮丽、极具吸引力的数据可视化在商业智能用户中赢得了最积极的反响,并帮助 Tableau 成为商业智能数据可视化工具的市场领导者。
2019 年 6 月 10 日,Salesforce 以价值超过 150 亿美元的纯股票交易收购了 Tableau。
功率 BI
Power BI 徽标
微软在 2015 面向大众推出了其专有的商业智能工具 Power BI,作为一款独立产品。但在此之前几年,微软已经将 Power BI 的一些分析和可视化功能作为插件捆绑到 Excel 中。Power BI 与 Microsoft Office 生态系统无缝集成,并在 Office 用户群中迅速流行起来。事实上,Power BI 的一大卖点是,将顽固的 Excel 用户转移到真正的商业智能环境中是很自然的下一步。
Knowi
Knowi 徽标
Knowi 是一个现代商业智能工具,它试图通过使用数据虚拟化来消除对 ETL 的需求,从而将自己与传统的 BI 工具区分开来。Knowi 还通过支持与 NoSQL 数据库的本地连接而脱颖而出,允许用户直接对非结构化数据进行分析——这在传统上是不可能的。它拥有任何传统 BI 工具的所有常规功能,但它最受欢迎的功能之一是由自然语言 BI 平台支持的搜索驱动的分析。虽然 knowi 是在 2015 年推出的(与 Power BI 同年),但在最初几年,他们一直处于相对隐形的模式,因为他们将所有精力集中在构建一个可以与一些大牌竞争对手正面交锋的 BI 工具上。早期的尽职调查得到了回报,正如 Knowi 吹嘘的那样,它的客户群中有一些大企业。
权力 vs 画面 vs 知识
在本文的剩余部分,我们将在 8 个核心领域对三者进行比较:
- 设置和产品
- 数据源
- 支持的数据
- 形象化
- 分析学
- 人工智能
- 定价
- 方便用户
设置和产品
Tableau 为用户提供了桌面客户端和在线云访问工具。桌面用户可以从 *Tableau 桌面、Tableau 桌面个人版、Tableau 桌面专业版的不同产品中进行选择。*云用户可以使用 T ableau Public(免费)或 Tableau Online 。企业公司也可以在内部安装 Tableau 服务器,但他们也需要桌面客户端来访问 Tableau 服务器上的报告。最后, Tableau Mobile 支持移动设备用户在移动中无缝访问 Tableau 服务器或 Tableau Online 上的报告。
Power BI 还分别通过其 Power BI 桌面和 Power BI 服务为桌面和云用户提供产品。可以使用 Power BI 服务器和 Power BI 数据网关为公司进行现场安装。 Power BI Mobile 允许用户在移动设备上访问云端报告。
Knowi 提供了支持云的平台和本地版本。根据设计,Knowi 不支持桌面安装,因为它已经过优化,可以作为 SAAS BI 平台在 web 浏览器中运行。对于企业用户,Knowi 提供了云/本地/混合部署的选项。Knowi 仪表盘和分析可以与移动用户共享,其嵌入式分析引擎可以添加到移动应用程序中。但 Knowi 平台本身没有移动应用程序版本,通常不允许用户从手机或平板电脑上进行新的分析查询。
就产品范围而言,Tableau 和 Power BI 都有类似的产品,两者之间几乎没有什么区别。另一方面,虽然桌面用户仍然是一个很大的细分市场,但 Knowi 只关注云用户,押注于整个软件市场的未来,继续朝着 SaaS 第一的生态系统发展。
动力 BI 的手机 app 流量(来源:microsoft.com)
数据源
Tableau 和 Power BI 基本上都可以连接到任何结构化或基于 SQL 的数据源。对于不基于 SQL 的数据源,Tableau 和 PowerBI 用户仍然可以连接到它们,但是需要使用像 ODBC(开放式数据库连接)驱动程序这样的中介来翻译 SQL。他们也可以使用 ETL 过程将所有数据转移到基于 SQL 的数据仓库中,并应用模式。
Knowi 支持超过 36 个数据源,从结构化数据到非结构化数据(如 MongoDB、Couchbase、Apache Cassandra 和 Elasticsearch)。在商业智能工具中,Knowi 与众不同,它能够本地连接到 NoSQL 数据源。Knowi 最常用于涉及 MongoDB 分析或 Elasticsearch 分析的用例。
Tableau、Power BI 和 Knowi 的另一个常见功能是支持 REST API 和 REST API 分析。这为将第三方应用与这些 BI 工具无缝集成提供了更多可能性。
很明显,在连接基于 SQL 的数据源方面,Tableau 和 Power BI 并驾齐驱。尽管 Knowi 在其网站上明确列出了更少的数据源,但最终,它实际上可能会连接到更多的数据源,因为它对 NoSQL 数据的开放支持以及更灵活的 REST API 集成。也就是说,他们不同的关注点使得在数据源/集成上进行比较变得棘手。
支持的数据
虽然 Tableau 和 Power BI 都以用于分析大数据而闻名,但用户对 Power BI 大数据支持的反馈不如 Tableau。他们处理非结构化数据的能力有限,这也是在一些更复杂的用例中产生摩擦的原因。
Knowi 可以无缝处理任何类型的结构化、非结构化、大数据或小数据。这主要是因为它提供了一个数据虚拟化层。这种数据虚拟化使 it 能够处理任何类型的数据,而不必担心底层数据结构和任何 ETL 过程的需要。它还创建了一个灵活的环境,用户可以在其中执行跨数据库连接,甚至可以将 MySQL 等结构化数据库中的数据与 MongoDB 等非结构化数据库中的数据连接起来。
显然,这 3 个工具支持所有类型的数据,但是,由于内置的数据虚拟化,Knowi 确实带来了其他 BI 工具无法带来的额外和独特的东西。
Knowi 仪表板示例(来源:Knowi)
形象化
Tableau 因其制作商业智能世界中最令人惊叹和最复杂的可视化的能力而广受欢迎。您可以创建功能强大的图表、图形、地图、信息图和仪表盘,并根据您的创造力进行大量设置。
Power BI 还提供了您期望从微软产品中获得的大量数据可视化选择。你会发现几乎所有的标准和高级可视化类似于 Tableau。它还可以让你创建自己的自定义可视化,并把它们放在他们的应用源市场上。
Knowi 也不落后于上述大男孩,并提供丰富和高度可定制的可视化和仪表板选项。它支持 30+不同类型的简单和先进的可视化,应该照顾最常见的数据即需求。此外,Knowi 允许用户创建定制的可视化,以满足他们特定的数据需求。
毫无疑问,Tableau 是市场上数据可视化工具的黄金标准。另一方面,我们会说 Power BI 和 Knowi 都为您提供了所有标准的数据可视化,以及您需要的所有定制。但是,如果你正在寻找一个仅基于视觉美学的 BI 工具,并且你不需要连接到各种各样的复杂数据源,Tableau 可能是你的最佳选择。
Tableau 可视化示例(来源:维基百科)
分析学
尽管 Tableau 通常被视为数据可视化工具,但它也是执行高级分析的强大平台。它最近还推出了一个新功能 Ask Data ,非技术用户可以简单地在搜索栏上提出一个问题,Tableau 将解释自然语言输入并给出问题的输出。
Power BI 提供了针对高级和初级用户的良好分析功能。与 Tableau 类似,它也支持自然语言查询,用于对对话问题进行分析。
最后,Knowi 还因其由数据虚拟化支持的下一代分析平台而闻名,该平台使查询结构化和非结构化数据更加方便。它还支持由自然语言查询实现的搜索驱动的分析,就像上面两个工具一样。
最近,Knowi 在 Slack 中推出了基于搜索的分析。一个新功能,你可以在 Slack 中用简单的英语问你的 Knowi instance 问题,然后得到答案、图表和数据。
Knowi 基于搜索的 Slack 分析功能(来源:Knowi 基于搜索的分析)
人工智能
在上一节中,我们看到了所有三个工具如何利用自然语言处理来提供自然语言搜索驱动的分析。但这还不是全部,它们都提供了一些现成的集成机器学习功能。
Tableau 提供各种机器学习功能,如聚类、预测分析、预测、智能推荐和模糊匹配。
由于与 Azure 平台的集成,Power BI 还提供了各种机器学习模型的创建。除此之外,它还通过认知服务 API 支持文本分析和计算机视觉。
Knowi 也内置了许多用于分类、回归、时序异常检测的机器学习算法。它还计划很快将集群和深度学习功能引入其平台。
定价
众所周知,Tableau 价格昂贵,对于个人或小团队来说不是一个口袋友好的选择。相比之下,Power BI 的起点价格较低,但如果你扩大许可证和插件的规模,价格将大幅上涨。尽管如此,Power BI 的起始价格较低,对于寻求因果数据可视化或分析的人来说是一个不错的选择。这与 Power BI 的起源如出一辙,它是微软 Office 的扩展,旨在供个人或企业用户使用。
像 Tableau 一样,Knowi 的定价点也是以中型公司或大型企业公司为目标,而不是针对个人的产品。然而,Knowi 定价保持灵活,以满足公司的特定需求,并根据需求和使用情况而变化。无论是部署在云上还是内部,这种灵活的定价模式都是根据每个客户的特定需求量身定制的。
随着规模的扩大,Tableau 和 Knowi 之间的价格差异变得更加明显。Tableau 的线性定价模式意味着每个新用户的额外费用,这些费用可能会很快增加。另一方面,Knowi 的定价基于大量用户。这意味着,随着用户群的增长,定价逐渐降低,实际上变得更具成本效益。
另一个要考虑的事情是,使用 Tableau 或 PowerBI 进行企业分析可能会带来无形的成本,即必须构建数据仓库基础设施,以将所有数据源纳入到绑定到模式的数据结构中。Knowi 的非 ETL 解决方案在大多数情况下可以避免这种成本。
在 Power BI 与 Tableau 和 Knowi 之间选择工具时,价格实际上是一个很大的区分因素,因为不同的应用程序会重视不同的功能。一家希望迅速扩大规模的初创公司可能会选择 Knowi,因为其早期的灵活启动定价和随规模扩大的分桶用户定价模型。需要廉价 BI 解决方案的小公司可能会选择 PowerBI,因为它的入门价格门槛较低。
用户友好性
这三个工具都有直观的界面,但如果我们对这三个工具进行比较,普通用户可能会发现 Tableau 的高级选项有点难用。非技术或不太高级的用户通常使用案例有限,他们会发现 Power BI 更容易使用——特别是如果他们有很强的 Microsoft Excel 背景的话。Knowi 使用了一个基于浏览器的 web 应用程序界面,这对于大多数用户来说是熟悉和有意义的,但与其他两个相比,他们的 UI 可能需要一点改进。
画面 vs 权力 BI vs 知识——最后的想法
正如我们看到的,在几乎所有的比较参数中,这三种工具都表现得相当不错。每种工具不仅有自己的优点和缺点,还带来了自己独特的产品。
如果你是个人,那么毫无疑问,你可能会选择 Power BI,因为其他任何东西都非常昂贵。
对于公司而言,如果您关注的是价格点,那么 Power BI 也是一个不错的选择,前提是您的团队未来不会扩大规模,或者您不需要高级选项。如果不是这样,那么 Tableau 可能是一个物有所值的好选择。如果你正在寻找灵活的定价选择,或者你是一家初创公司,那么你可能也想去 Knowi,因为他们也有针对小型初创公司的特殊定价选择。
如果您的组织正在处理大数据,那么与 Power BI 相比,Tableau 将是一个不错的选择,前提是您的预算允许。但是,如果您没有一个定义良好的 ETL 流程的大数据仓库,那么您也可以考虑 Knowi,因为由于它的数据虚拟化,它不需要您拥有所有这些基础设施,并且不需要从源移动。
在权力 BI、画面和知识之间做一个比较是很有趣的。由于大数据、人工智能的出现,以及企业越来越多地使用非结构化 NoSQL 数据,商业智能的前景在过去几年中发生了很大的变化。PowerBI 和 Tableau 都试图通过加入机器学习功能,从现在的商业分析工具转变为增强的分析工具。在这一点上,Knowi 与这两位有些不同。作为第三代商业智能平台,它从机器学习功能开始。但作为一家规模较小的初创公司,它仍有很大的增长空间,在市场的一些领域,它需要赶上其他两种解决方案。
看看这三个平台在接下来的几年里会有什么样的新特性会很有趣。
没有控制,权力什么都不是
不要和 Jupyter 笔记本分手。也用 Kedro 就好!
这篇文章适合那些发现自己被 Jupyter 笔记本的易用性所吸引的人。虽然它针对的是数据科学相对较新的读者,但它同样适用于更有经验的数据科学家&工程师,他们正在考虑如何改进他们的日常工作流程。
Jupyter 笔记本的便利性与 Kedro 的软件最佳实践相结合
我将简要介绍一下我们喜欢和不喜欢 Jupyter 笔记本的原因,并描述一下开源 Kedro 框架如何帮助您解决令众多数据专业人士头疼和心痛的一些问题。而且不涉及分手!如果你不能完全放弃,你仍然可以在 Kedro 旁边使用笔记本。
如果你对笔记本不熟悉,或者想了解更多,这里有一个简短的历史题外话,总结自一篇名为数据科学家喜欢 Jupyter 笔记本的 10 个原因的精彩文章。如果你已经知道所有你需要(或想要)的他们的历史,就跳到下一节“ 为什么要用 Jupyter 笔记本 ”。
早在 2011 年,IPython Notebook 作为交互式 Python 控制台的基于 web 的接口发布。它允许 Python 开发者在本地网页上操作代码、文本、数据图等等。IPython 笔记本迅速变得如此受欢迎,以至于它被扩展到包括其他编程语言,如 R 和 Julia。
2014 年,Jupyter 项目宣布以新的名称管理多种语言的 IPython 笔记本,而 IPython 继续作为 Python shell。
维基百科解释了该项目的名称选择:
“Project Jupyter 的名字是对 Jupyter 支持的三种核心编程语言的引用,这三种语言是 Julia 、 Python 和 R ,也是对伽利略记录木星卫星发现的笔记本的致敬。”
Project Jupyter 网站将自己描述为“一个非盈利、开源的项目……旨在支持跨所有编程语言的交互式数据科学和科学计算”。该项目自开始以来一直蓬勃发展,并于 2017 年获得了 2017 ACM 软件系统奖。
可以说,Jupyter 笔记本已经成为数据科学家工具箱中必不可少的一部分。
为什么要用 Jupyter 笔记本?
❤️我们爱笔记本❤️ 这是可以理解的
当你开始从事数据科学或数据工程时,有很多东西需要学习。有很多资源可以帮助你,包括在线课程。大多数都提供了示例项目,这些项目最有可能出现在笔记本中,因为它们对于初学者来说非常简单。它们使得获取代码、单步执行代码、绘制数据和实验变得特别容易。你一定会发现在笔记本上开始比设置一个 IDE 并通过脚本来使用它要简单得多。你只需要拿一个笔记本,只要你跑了pip install Jupyter
就可以开始了。每次运行笔记本单元时,您都会立即看到代码的结果。不喜欢什么?
不可否认的是,无论你多么有经验,当你开始一个项目时,笔记本对于实验和想象都是有用的。随着你扩大生产规模或需要与他人合作,蜜月期会逐渐消失。即便如此,也有使用笔记本的方法:例如,网飞数据团队已经描述了如何扩大笔记本的使用。但是,对许多人来说,一句谚语“没有控制,权力什么都不是”跃入脑海。
没有控制,权力什么都不是:来自倍耐力的视频
为什么不用 Jupyter 笔记本?
💔这也可以理解为什么我们不再喜欢笔记本了💔
在整个数据科学网站上,甚至仅在这个博客上,就有一系列的 的 文章详细介绍了 Jupyter 笔记本电脑在大型项目中成为问题的原因。一旦你到了需要使用软件最佳实践来控制你的复杂性的时候,很明显笔记本不支持那些理想。
作为一名前 C 程序员,我认识到这些缺陷来自一个强大而自由的开发环境。例如,随着代码变得越来越大,很难在单个笔记本中进行管理。大量的代码变得错综复杂。有时候,一个笔记本是不够的。假设您想一起运行多个模型,并比较结果?每个人都需要一个单独的笔记本。如何用相同的配置来设置它们,并随着实验的进展不断地改变它们呢?
假设您想要使用一组新数据进行测试,或者使用不同的方法处理现有数据,或者向您的算法输入不同的参数。你可以改变你的笔记本,但是你不能轻易地跟踪那些改变并回滚它们,如果你在你的笔记本中引入一个错误源,那就不简单了。笔记本格式不太适合源代码控制,调试也很棘手。
团队中的数据科学家遇到的另一个问题是环境再现性。假设您想与同事协作并共享您的笔记本。但是如果他们使用的是一个特定包的不同版本,比如已经随时间改变的sklearn
,该怎么办呢?您如何向您的同事指定要设置什么环境,以便他们可以像您在自己的机器上一样运行笔记本电脑?你如何自动设置?更进一步:您希望将代码作为演示的一部分部署给团队中的许多人。但是如何管理配置和更新呢?甚至不要考虑如何发布和产品化您的笔记本电脑!
最佳实践:如何将 Jupyter 笔记本与优秀的工程技术相结合
与其完全扔掉你的笔记本,为什么不考虑用它们来做实验(例如探索性的数据分析),同时在一个框架内构建你的项目呢?
早在 2019 年,我曾在这个博客的帖子中介绍过 Kedro ,尽管从那以后我们在 readthedocs.io 上创造了一些更简单的了解 Kedro 的方式。
Kedro 由高级分析公司 QuantumBlack 创建,并于 2019 年开源,以扩展其对第三方数据专业人士的使用。它是一个开发工作流工具,将软件工程最佳实践应用于您的数据科学代码,因此它是可复制的、模块化的和有良好文档记录的。如果你使用 Kedro,你可以少担心学习如何写生产就绪的代码(Kedro 为你做了繁重的工作),你将标准化你的团队合作的方式,让你们所有人更有效地工作。
虽然 Kedro 有一个学习曲线,因为您将使用 Python 脚本和命令行界面,但随着您获得有组织的代码和数据的好处,它会很快得到回报。当你开始一个新的项目时,这是一个很好的时机,但是你也可以将一个现有的笔记本转化为一个 Kedro 项目,正如最近来自 DataEngineerOne 的一个视频所展示的那样。
一旦你建立了一个 Kedro 项目,你可以使用一个 Jupyter 笔记本来开发你的代码,如果你喜欢这种工作方式的话,然后把它转换成一个 Kedro node
,这是一个 Python 函数,由 Kedro 框架在它管理pipeline
的角色中调用。(该术语在文档中的 Hello World 示例中有进一步的解释,您将在设置 Kedro 安装的过程中学习该术语)。有一些简洁的扩展允许你在开发你的 Kedro 项目时在笔记本上工作,你可以找到一个视频如何使用两个技巧使 Jupyter 笔记本在 Kedro 上更有用。
总之
阻力最小的道路可能很吸引人,但是一个训练有素的发展方法从长远来看是值得的。
虽然笔记本可以帮助您快速启动和运行,但当您尝试扩展项目时,可能会遇到问题,因为它们缺乏对版本、可再现性和模块化的支持。
Kedro 是一个构建代码的框架,它借鉴了大量数据科学家在一系列工业项目中的经验。它坚持让您与软件最佳实践保持一致,但它也允许您选择使用 Jupyter 笔记本进行实验,并简化代码从笔记本到 Kedro 项目的转移。
但是不要相信我的话。查看团队使用它的原因,如果你想了解更多,请前往 kedro.readthedocs.io 或查看不断增长的关于 kedro 的文章、播客和讲座列表!
衷心感谢 QuantumBlack Labs 的 Yetunde Dada 和 Lais Carvalho 在我写这篇文章时提供的宝贵见解,并感谢整个 Kedro 团队愿意分享他们所知道的东西💚
数据科学中并行处理的力量。
知道何时进入并行模式以及如何充分利用并行模式的艺术。
我们大多数人都有平行做事的习惯。想象一下,你去杂货店,接到一个朋友的电话,于是你们开始聊天,同时买东西。单词“**同时”**暗示了我们将注意力分配到不同任务的能力。但是注意力的分散经常会降低效率和表现,因为我们的大脑一次只能专注于一件事。
同样的概念是否适用于并行解决数据科学的问题?
答案是: 取决于手头的问题和可用的计算资源 。
因此,让我们打开构建并行解决方案所需的组件
划分问题空间
默认情况下,并行问题需要被分割成块,以便每个块可以被馈送到不同的计算节点。这样,我们可以将它们分为两种类型:
- 按任务:想到盖房子。您可以并行执行许多任务,例如,管道、电气、安装窗户等。
并行工作的工人
现在,在数据科学的背景下,考虑从相同的人口数据中导出的两个模型,一个用于理解出生因素,另一个用于推理死亡。
- 按数据:相同的任务,但在不同的数据块上。例如,在同一栋房子里,所有的窗户都可以平行安装。在数据科学场景中,我们会遇到需要对不同的数据集/数据子集应用相同的建模函数的情况。例如,使用直方图绘制全球不同国家的温度分布。
了解划分技术只是解决并行问题的第一步。最重要的方面是了解您想要在其上训练或部署模型的系统。无论是在台式机、网络系统还是超级计算机上完成的工作都很重要,因为它构成了执行计算的骨干处理器。所以让我们解开它的建筑概念。
并行计算的标准
- 需要至少两个处理器(核心)或通过网络连接的单核/多核计算机集群。例如, kaggle 内核提供了四核功能,现在几乎所有系统都具备这种功能,甚至我们的手机也不例外。
- 共享内存模型帮助进程共享相同的数据,从而节省时间。
- 分布式内存:进程不能访问另一个进程的内存。称为消息传递系统,因为进程通过相互发送消息来进行通信。
共享内存和分布式内存
因此,为了使用编程语言构建模型,它们的大多数实例(会话)利用系统的单核。R 和 Python就是这样的例子。默认情况下,它们运行在单核上,除非您明确指定和构建代码以适应并行环境。
将并行问题融入编程环境
当构建并行代码时,主从模型用于描述并行工作场景
- 它用于主创建工人并在他们之间分配任务的情况。工作进程执行它们任务并将结果返回给主进程,主进程反过来执行
主工人模型
- 对于需要综合解决方案的问题,master 向工人交付第一批任务,然后等待结果。在收集完所有结果后,它发送第二批任务,再次等待结果,以此类推。
- 虽然主工人模式看起来很有益,但它缺乏处理负载平衡问题的能力。例如,假设有 4 个工人,主人给他们第一批任务。其中 2 名工人完成了任务,2 名工人仍在工作。现在,主人需要等待所有 4 名工人的结果,才能给第二批任务。因此,增加了两个空闲工人的等待时间。
令人尴尬的平行问题
通常情况下,并行任务之间不存在依赖关系,因此使用术语“令人尴尬的并行问题”。例如,从目录中读取不同的文件。
这种并行问题倾向于很少或不需要任务之间的中间结果的通信,因此不同于需要任务之间通信的分布式计算问题。
结束注释
在这篇博客中,主要目标是理解并行处理的领域。不是所有的问题都可以用并行处理来解决,也不是所有的并行问题都可以节省时间。
对于较小的任务,使用并行任务的计算效果可能不那么富有成效,但是当处理依赖于多个数据源的复杂问题集时,将并行处理集成到解决方案中的能力可能是有益的。
要在编程环境中实现并行问题,请尝试浏览以下博客:
[## 加速您的代码:使用 multidplyr 进行并行处理
没有什么比等待长时间运行的 R 脚本迭代运行更令人沮丧的了。我最近遇到了…
www .商业科学. io](https://www.business-science.io/code-tools/2016/12/18/multidplyr.html) [## 使用 R 和 Python 的多核数据科学
本文摘自 R 和 Python 中多核数据科学的完整视频。观看完整视频了解…
blog.dominodatalab.com](https://blog.dominodatalab.com/multicore-data-science-r-python/) [## R 语言并行编程简介
使用 Kaggle 笔记本探索和运行机器学习代码|使用来自非数据源的数据
www.kaggle.com](https://www.kaggle.com/gravc91/introduction-to-parallel-programming-in-r)
面向每位 Power BI 开发人员的 Power 查询技巧
使用这些简单而强大的技术来加速您的 Power BI 开发
如果有人让你定义幂查询,你该怎么说?如果您曾经使用过 Power BI,那么即使您没有意识到,也不可能没有使用过 Power Query。因此,可以很容易地说,权力质询是权力 BI 的
照片由 Amar Yashlaha 在 Unsplash 上拍摄
在更官方的措辞中,Power Query 是微软用于连接和转换来自多个来源的数据的技术。正如微软的官方文档所述,你可以连接到数百个不同的数据源,并对你的数据进行 300 多次转换。
Power Query 的关键优势在于,您只需很少或不需要任何编码技能就可以执行复杂的数据转换!此外,您在数据转换过程中应用的所有步骤都将被保存,因此每次刷新数据集时,这些步骤都将自动应用于形成您的数据,这是一种真正的时间节省。
在这 300 多种转换中,很难选择最有用的,但是我将分享我的与 Power Query(及其强大的 M 语言)相关的 3 个技巧。您还应该学习与电源查询无关的技巧,以促进电源 BI 开发。
提示#1 —超级查询编辑器中的省时工具
我需要立即说明:通过巧妙使用 Power Query Editor,您可以执行大量节省时间的操作,因此我将把我的建议缩小到我最常用的几个。
我敢打赌,您几乎每次为 Power BI 报告准备数据时都会遇到这种情况。您导入了一个包含许多列的宽表,并且需要删除其中的一些列。您从左向右滚动,选择要保留的列和要删除的列。
但是,有一种更复杂的方法可以实现这一点:
正如你在上面的插图中看到的,不需要费力的滚动,只需要打开选择列下拉菜单,选择选择列,然后选择你想要保留的列!太方便了!
同一个下拉菜单下的另一个提示:选择 Go To Column,您将直接导航到该列,因此您可以对该特定列执行任何类型的转换,同样也不需要浪费时间试图在广泛的“30+列表”中找到它…
另一个隐藏的亮点是视图选项卡下的“查询依赖项”按钮。
这在处理复杂模型时非常有用,因为数据来自多个不同的来源,或者并非所有数据都加载到报表中。
使用查询依赖项将使您快速直观地了解数据模型:
不用点击数据模型中的每一个实体来检查其状态,您可以在一个地方得到所有这些,更好的是,它是可视化的!
想象一下,数据来自 CSV 文件、SQL Server 数据库和 Sharepoint 列表,而部分数据由于某种原因甚至没有加载到报告中。这是一个 huuuuge 时间节省!
技巧# 2——使用 M 语言执行频繁的计算
最常见的业务请求之一是计算不同事件之间的时差。例如,我想知道我的客户的年龄结构,所以我需要在每次数据刷新时计算他们的年龄。
或者,我需要检查客户延迟付款的天数。正如您所想的那样,这些数字需要动态计算,所以 M 语言来了!
让我们演示一下如何计算客户的年龄。基本上,在 Power Query 中有两种方法可以实现这一点:第一种不需要任何编码,但需要应用多个步骤。所以,我更倾向于第二种方案,当你把整个计算一步到位!
上述方法需要三个独立的步骤。首先,我们插入一个新列,并在日期下拉菜单中选择年龄选项。但是,Power Query 计算从出生日期到今天的天数。因此,我们需要将这个笨拙的数字转换为年,这是在 Duration 下拉菜单下选择 Total Years 来完成的。同样,我们得到了一个尴尬的结果,因为年龄显示为一个有多个小数位的十进制数(这是正确的,但不直观)。最后一步是向下舍入该数字,这是在舍入下执行的。
现在,这种方法没有任何问题,但是如果您正在进行多个计算,您的 Power Query Applied Steps 窗格将会被许多不必要的步骤所污染。
这就是为什么我更喜欢另一个选项:在“添加列”选项卡下,选择一个自定义列并输入以下公式:
*Number.RoundDown(Duration.TotalDays(Date.From(DateTime.LocalNow()) - [BirthDate])/365)*
这样,我们在一次运行中执行了先前版本的所有迭代,并且我们只应用了一个步骤!以更优雅的方式完成任务…
提示#3 —自定义弹性日期维度
这张是我最喜欢的!首先,我想为此写一个单独的帖子,但最终,我决定把它放在这里,因为我已经写了关于正确处理日期维度的整个系列。
我不会花太多时间来解释拥有单独的日期维度的重要性(那是另一篇文章的主题)——我只会简单地说:从技术上讲,Power BI 允许您在没有单独的日期维度的情况下“生存”,但不要这样做!只是不要…
在您的数据模型中创建单独的日期维度有多种解决方案,但是这里我将重点介绍使用 M 语言来实现这一点。
网上有很多现成的脚本来创建一个全功能的日期维度,但是我选择了来自雷扎·拉德的这个解决方案(顺便说一下,在他的博客上你可以学到很多有用的东西)。
打开新的 Power BI 文件,并选择“获取数据”下的“空白查询”:
这将引导您进入超级查询编辑器。为了获得高度定制的日期维度,下一步至关重要。
在“管理参数”下,选择“新参数”并将其格式化,如下图所示:
这样,您就可以定义日期维度从哪一年开始。对年末做完全相同的操作:
现在我们已经定义了两个参数,我们可以切换到高级编辑器并粘贴整个 Reza 脚本来创建日期维度的特定列(当然,可以根据您的需要随意包含/排除更多的列)。
这是整个脚本:
*let
StartDate = #date(StartYear,1,1),
EndDate = #date(EndYear,12,31),
NumberOfDays = Duration.Days( EndDate - StartDate ),
Dates = List.Dates(StartDate, NumberOfDays+1, #duration(1,0,0,0)),
#"Converted to Table" = Table.FromList(Dates, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Renamed Columns" = Table.RenameColumns(#"Converted to Table",{{"Column1", "FullDateAlternateKey"}}),
#"Changed Type" = Table.TransformColumnTypes(#"Renamed Columns",{{"FullDateAlternateKey", type date}}),
#"Inserted Year" = Table.AddColumn(#"Changed Type", "Year", each Date.Year([FullDateAlternateKey]), type number),
#"Inserted Month" = Table.AddColumn(#"Inserted Year", "Month", each Date.Month([FullDateAlternateKey]), type number),
#"Inserted Month Name" = Table.AddColumn(#"Inserted Month", "Month Name", each Date.MonthName([FullDateAlternateKey]), type text),
#"Inserted Quarter" = Table.AddColumn(#"Inserted Month Name", "Quarter", each Date.QuarterOfYear([FullDateAlternateKey]), type number),
#"Inserted Week of Year" = Table.AddColumn(#"Inserted Quarter", "Week of Year", each Date.WeekOfYear([FullDateAlternateKey]), type number),
#"Inserted Week of Month" = Table.AddColumn(#"Inserted Week of Year", "Week of Month", each Date.WeekOfMonth([FullDateAlternateKey]), type number),
#"Inserted Day" = Table.AddColumn(#"Inserted Week of Month", "Day", each Date.Day([FullDateAlternateKey]), type number),
#"Inserted Day of Week" = Table.AddColumn(#"Inserted Day", "Day of Week", each Date.DayOfWeek([FullDateAlternateKey]), type number),
#"Inserted Day of Year" = Table.AddColumn(#"Inserted Day of Week", "Day of Year", each Date.DayOfYear([FullDateAlternateKey]), type number),
#"Inserted Day Name" = Table.AddColumn(#"Inserted Day of Year", "Day Name", each Date.DayOfWeekName([FullDateAlternateKey]), type text)
in
#"Inserted Day Name"*
点击 Close & Apply,现在我们的数据模型中就有了全功能的日期维度!
我们可以通过管理参数和切换年份值来轻松改变时间框架。
现在蛋糕上有冰块,作为额外的提示:把你的文件保存为。pbit (Power BI 模板文件)。这样,当您开始 Power BI 项目时,您不需要从头开始创建日期维度,浪费您的时间和精力—它已经为您准备好了!
你还要吗?就在那里。打开模板文件后,系统会提示您输入起始年和结束年的值,这意味着您可以自定义报告之间的时间范围!多酷啊!
一旦您输入值,Power BI 将根据您定义的值自动为您创建日期维度!
结论
当涉及到数据检索,尤其是数据转换时,Power Query 提供了一系列的特性。描述它们需要一两本书,所以我想摘录其中几个,我认为它们在我日常使用 Power BI 的工作中最有用。
你最喜欢的电量查询功能有哪些?欢迎在评论区分享它们。
订阅这里获取更多有见地的数据文章!
用人工智能增强 Windows 应用:用 Python 模型连接 C#应用
软件体系结构
Windows 窗体界面与人工智能管道的共生
马里乌斯·马萨拉尔在 Unsplash 上的照片
这里不再介绍:
a)我们可能总是在控制台中运行我们的 ML 模型或神经网络管道;
b)我们没有理由不能在 Windows 上运行它,并添加一些点击按钮。
不过,这里我们面临一个问题。我们可以轻松地开发一些 Python 模型或 C# Windows 窗体应用程序。但在人工智能驱动的应用程序开发过程中,它们的连接可能是一个真正的痛苦。这就是为什么这篇文章关注项目的 C#和 Python 部分之间的中间通信的解决方案。
对于该项目,我们将使用来自 Kaggle 的 loan lending club 数据集。
1.假设我们已经有了一个很酷的模型
Loan lending club 数据集肯定是众所周知的数据积累,所以我们将跳过数据集准备、清理、特性选择、分析和其他工作人员的代码(因为这不是本文的主题)。如果你愿意,可以在我的 GitHub 上的例子中查看。让我们用 Keras 库创建一个非常简单的神经网络,并训练它具有或多或少合适的精度:
因此,我们有最终准确率为 70%的 4 层神经网络。确实不是最好的,但对我们的目的来说已经足够了。顺便说一下,我们还从 sk-learn 创建了标签编码器和定标器的转储。我们使用了一个非常方便的 泡菜模块:
from **pickle** import dump
dump(scaler, open(‘scaler.pkl’, ‘wb’))
dump(grade_encoder, open(‘grade_encoder.pkl’, ‘wb’))
dump(ownership_encoder, open('ownership_encoder.pkl', 'wb'))
dump(purpose_encoder, open('purpose_encoder.pkl', 'wb'))
现在我们的任务是:
- 编写模型加载和预测的代码;
- 将这段代码包装在一个简单的类中;
- 添加接收 json 格式的输入参数的代码;
- 添加以 JSON 格式返回输出的代码。
所以,第一步是我们需要模型的目的,第二步只是为了方便。但是最后两个是我们的应用程序到模型连接的中间阶段:JSON 是在解决方案的不同层之间进行交换的一种非常方便的格式。嗯,空谈是廉价的,下面是我们的课:
2.添加一些按钮
Windows 窗体的 C#开发的好处是界面创建的速度:拖放一些元素,填充一些回调,检查编辑框是否被正确验证,瞧——原始应用程序已经准备好了。真的没有理由展示所有代码——它是 Visual Studio 2019 中的一个标准 Windows 窗体项目。不过,你可以在我的 GitHub 里查看。看起来是这样的:
没什么特别的,但是我们可以输入上一步的神经网络的输入参数,然后得到结果。棘手的部分来了。
3.如何将信息传入 Python 脚本?
因此,我们需要一个 C#到 Python 通信的中间层解决方案。它由两部分组成:PythonCaller
应用程序中的类和 Python 聚合器脚本。正如我们从名称中看到的,C#类收集应该传递给模型的参数,获取模型名称和位置,并将所有这些信息传递给调用聚合器脚本。聚合器脚本处理与模型相关的所有作业。
先说 C#部分。
正如我们所说的,所有的信息交换都是以 json 格式进行的。这就是为什么我们需要做的第一件事是连接 Newtonsoft JSON 解析器库。它是免费的,可以很容易地通过市场添加到 Visual Studio 中。下载后将其包含到项目中:
using Newtonsoft.Json;
在备课之前,我们要想好从类内部的 GUI 部分传递输入参数的方式。因为我们决定将参数打包到 JSON 对象中,所以我们将准备参数容器类。你可能知道我对容器设计充满热情,所以你可以查看我关于构造它们的文章。
所以,回到容器:这是一个简单的字典包装,它收集参数并可以将它们作为包含一些元信息的 JSON 对象返回。当然,它会被传入调用者类本身。
现在是主要部分。首先,PythonCaller
类的每个实例都将连接到具体的模型脚本。其次,它将使用ProcessStartInfo
对象通过 Python 解释器调用聚合器脚本。之前创建的带有输入参数的 JSON 对象将作为聚合器脚本的参数。实现很简单:
-
创建一个连接到具体模型类的对象:
-
将对所选模型的类方法的调用(当然,准备了
PythonCallerArgs
容器)转移到聚合器脚本:
您可能会注意到,我们已经控制了脚本调用的输入输出流。这是我们从脚本中获得结果的方式。
仅此而已,解决方案真的很简单。稍后我们将把这个类集成到应用程序中。
4.脚本之间的对话
解决方案的最后一部分是呼叫聚合器本身。它被表示为 Python 脚本,该脚本从 Windows 应用程序获取所有 JSON 打包的信息,并联系所需的 AI 模型脚本。
实现很简单——从 Windows 应用程序中获取参数,并通过特定的方法调用将它们传递给模型。这里有两个技巧性的地方。第一个是将模型的类导入到脚本中,这样我们就可以访问所需的方法。我们将使用 importlib 包来实现这些目的:它可以通过代码路径导入模块。
第二个技巧是将调用的结果返回给应用程序。但是,正如您所记得的,我们强迫ProcessStartInfo
对象获得对标准输出的控制。这就是为什么我们只是在脚本的最后一行将结果打印到流中。
5.使其工作
最后一步是将设计的类集成到我们的应用程序中:
现在我们可以检查整个应用程序,并从人工智能模块获得结果
是的,这个解决方案并不完美,但一旦调整,它将把人工智能的力量连接到你的应用程序。这就是为什么你可以提出自己的工作替代方案。和往常一样,您可以在我的 GitHub 存储库中找到完整的工作示例:
C#和 Python 项目的连接。WindowsForms 应用和 Python AI 模型共生的例子。二手贷款…
github.com](https://github.com/Midvel/WindowsToPythonAI)
PowerBI 与 R Shiny:两种流行的 Excel 替代品的比较
R Shiny 和 PowerBI 之类的拖拽可视化工具相比如何?
在 Unsplash 上由 Carlos Muza 拍摄的照片
选择合适的 dashboard/reporting/BI 工具从未像现在这样困难,因为有许多真正伟大的选项,如 R Shiny、PowerBI 和 Tableau。今天,我们将比较财富 500 强公司广泛使用的两种工具:
- power bi——一个软件服务、应用和连接器的集合,它们协同工作,将不相关的来源转化为连贯的、视觉上身临其境的交互式见解(来源: 微软 )
- R Shiny——用 R 编写的 web 框架,广泛用于制作仪表板和交互式 web 应用程序
有一点要记住: R Shiny 不是一个报告/仪表板工具。相反,它是一个完整的 web 框架。由于大多数人使用它来制作仪表板,并且我们的许多客户在投资分析解决方案时会将 R Shiny 与 PowerBI 进行比较,我们可以认为这种比较是公平的。我们将从 PowerBI 的基本概述开始,然后在各个方面比较这两个工具,例如:
- 连通性
- 图表类型
- 易用性:简单的图表
- 易用性:简单的仪表盘
- 用户输入和交互性
- 视觉造型
- 结论
PowerBI 概述
如前所述,PowerBI 用于可视化地表示来自各种数据源的交互式见解。它是一个完美的报告工具,这是一个只读操作,相对容易构建和维护。
PowerBI 也是最容易上手的工具之一,因为只需几门速成课程就能让你迅速上手。我们并不是说 R 很难学,但是拖放式 GUI 界面被认为比 R 更容易学,至少对商业人士来说是这样。
但这里有一个最重要的卖点— PowerBI 开箱后看起来很好。使用 PowerBI,您不必成为专家也能制作出好看的可视化效果。Shiny 需要更多的体力劳动来生产漂亮的仪表板。手工工作不一定不好,因为如果你愿意付出努力,你可以做的事情没有限制,但是简单的拖放工具在大多数时候已经足够了。
每个职业都有缺点,PowerBI 也不例外。PowerBI 最大的缺点之一是它是只读的。作为用户,不能使用图表/表格进行决策,直接保存在数据库中。
此外,PowerBI 没有可访问的源代码。您只能在 WYSIWYG 模式下编辑字段,这使得 PowerBI 易于启动,但难以维护。没有源代码,几乎不可能有适当的版本控制、自动测试逻辑或在大型项目上合作。
PowerBI 有几种不同的风格,如下所示:
- PowerBI Desktop —您可以下载并安装在电脑上的应用程序。仅适用于的窗口。它具有强大的数据分析能力,可以连接许多数据源。它用于执行分析、创建可视化和创建报告。
- PowerBI Service (Pro) — web 应用。它用于创建可视化和报告。最大的卖点是仪表盘——而且很容易制作。此外,由于协作模式,共享结果更加容易。
- power bi Mobile—Android 和 iOS 的移动应用。它仅用于从任何地方访问您的数据,而不是执行分析。
我们今天的大部分注意力将集中在 PowerBI 桌面版本上。
连通性
PowerBI 附带了许多内置的连接类型,分为文件、数据库、 Power 平台、 Azure 和在线服务,毫无疑问,它比我们的最后一个竞争者——Tableau 更加通用。截至 2020 年末,您会发现以下连接选项:
作者图片
简而言之,PowerBI 在连接性方面并不欠缺。在等式的另一边,R Shiny 使用 R 作为编程语言的选择,所以 Shiny 可以连接到 R 可以连接的任何源。
一个简单的 Google 搜索将会产生一个预制的库或者任何数据源类型的 API 调用示例。R Shiny 有时对特定领域的源有优势。尽管如此,我们还是发现了多个 PowerBI 处理特定领域数据源的例子,比如 CAD 文件。
胜者(连通性):平局
图表类型
PowerBI 提供了基本的可视化选项——条形图、折线图、面积图、散点图和饼图,以及一些更好的类型,如地图、树状图、漏斗图和带状图。完整列表请参考下图:
作者图片
尽管如此,对于大多数用例来说,这可能已经足够了,因为更复杂的统计图表不会经常出现在生产仪表板中。此外,你可能已经注意到这些“R”和“Py”图标。这意味着您可以在 PowerBI 中使用 R 和 Python 图表,只有一点需要注意——这些图表的源代码不受版本控制。
在 R Shiny 中,您可以使用 R 中可用的任何可视化库,比如ggplot2
和plotly
。以下是您可以通过这两种方式实现的可视化类型的概述:
GGplot2 选项;来源:【https://www.r-graph-gallery.com】
**Plotly 选项;来源:https://plotly.com/r/
在这个部门宣布获胜者是显而易见的。当然,Shiny 可以做很多事情,但是 PowerBI 可以做所有的事情,甚至更多。PowerBI 可以处理自己的图表和 Python 生成的图表。
赢家(图表类型):PowerBI
易用性:简单的图表
现在,我们将尝试在 PowerBI 和 Shiny 中重新创建相同的可视化。出于演示的目的,我们将使用 Gapminder 数据集,因此如果您正在跟进,请确保下载它。目标是创建一个简单的折线图,比较各大洲的平均预期寿命。
先说 PowerBI。我们通过以下步骤导入了数据集并创建了可视化:
作者图片
PowerBI 旨在方便各种背景的人使用,使这个简单的图表易于实现。
在 R Shiny 中复制同样的东西是一个完全不同的故事,因为我们需要编写实际的代码。数据集可以通过gapminder
包在 R 中获得,所以不需要下载和导入提供的 CSV。Shiny 引入了一些样板代码——这对于这个简单的图表来说是一个明显的缺点,但是对于更大的真实项目来说可以忽略不计。
代码如下:
结果如下:
作者图片
总之,使用 R Shiny 来生成单图表和非交互式仪表板是没有意义的。这是 PowerBI 占优势的领域之一,因为它使用起来简单直观。此外,R 中的图表需要一点定制,以看起来体面和可解释,这是 PowerBI 自带的。
赢家(简单图表):PowerBI
易用性:简单的仪表盘
在 PowerBI 中制作一个简单的仪表板很容易——在这里和那里点击几下,几个过滤器,我们就可以开始了。目标是显示三个图表:
- 一段时间内的平均预期寿命-折线图
- 各大洲总人口—仅在最近一年(2007 年),以条形图表示
- 预期寿命与人均国内生产总值——简单散点图,按大陆着色
然后,可以通过选择一个或多个洲来过滤整个仪表板。以下是我们在 PowerBI 中成功创建的内容:
作者图片
为了在 R Shiny 中实现大致相同的仪表板,我们需要编写一些 R 代码。再说一次,R 是一种相对容易学习的语言,所以我们不认为它对更精通技术的用户来说是个问题。
以下代码重新创建了我们在 PowerBI 中拥有的仪表板:
这是仪表盘的样子:
作者图片
我们稍后会处理视觉外观,所以不要太担心这个。在这里很难宣布一个明确的赢家,但 R Shiny 的仪表板感觉更坚实。
正如我们所看到的,使用 PowerBI 可以更快地制作一个简单的仪表板。出于这个原因,我们将宣布 PowerBI 是简单仪表板的赢家,但仅仅是为了易用性。如果你需要一个复杂的仪表板,R Shiny 就更通用了。
获胜者(简单仪表板):以微弱优势领先的 power bi
用户输入和交互性
如概述部分所述,PowerBI 是只读的。当然,您可以点击各种过滤器来从图表中包含/排除一些数据,但这几乎是您所能做的全部。我们认为输入在创建交互式仪表板中是必不可少的,所以像 Shiny 这样的完整 web 框架消灭了它在这个部门的对手。
Shiny 有大量的输入——从文本字段和按钮到下拉菜单和模态。以下是 Shiny 提供的一切:
作者图片
有了所有这些选择,如果安排得当,对 Shiny 来说没有什么任务是难以解决的。如果你仍然不相信交互性的重要性,这里有几点会让你重新考虑:
- **文件输入组件允许我们上传自定义数据集并在浏览器中执行探索
- **文本输入和密码输入字段允许我们构建完整的 web 表单——想想认证
- **变量选择输入允许我们从数据集中快速选择感兴趣的列
赢家(用户输入和互动):R 闪亮
视觉造型
在 PowerBI 甚至 Tableau 这样的拖放工具中调整视觉效果从来都不是他们的强项。默认情况下,这些工具设计得很好看。尽管如此,并不是每个人都同意什么是好的,所以有选择是好事。
我们发现你可以在 PowerBI 中调整很多东西。这里有一个粗略的概述:
作者图片
有了 R Shiny,故事就大不一样了。你可以通过创建一个www
文件夹来嵌入定制的 CSS 样式。CSS 文件然后被存储在提到的文件夹中。
要连接两者,你必须将theme = main.css
放入闪亮应用的fluidPage
中。仅此而已。在使用 CSS 的短短几分钟内,我们已经成功地对我们的仪表板进行了一些改造:
作者图片
这里是完成的仪表板的源代码。这场战斗的赢家是显而易见的,再一次。当然,PowerBI 开箱后看起来很好,但你无法让它看起来完美。R Shiny 在视觉造型方面非常通用(在合适的开发人员手中)。
获胜者(视觉造型):R 闪亮
结论
最终结果如下:
- PowerBI — 3 分
- r 闪亮— 2 分
- 平局— 1 分
根据我们的统计,对于大多数一般用例,PowerBI 领先一个百分点。当然,选择合适的工具并不像数到 5 那么简单,所以需要进一步的澄清。当您需要相对简单的东西,并且不太担心仪表板的外观和整体感觉时,PowerBI 是非常好的。
对于任何更复杂的东西,R Shiny 推翻了 PowerBI。PowerBI 无法与 Shiny 提供的可定制性相比,尤其是当您需要创建企业应用程序时。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
* [## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)*
原载于 2020 年 10 月 29 日 https://appsilon.com。**
使用 Sweetviz,仅两行代码即可实现强大的 EDA(探索性数据分析)
借助这个新的 Python 库,更快地了解您的数据
仅用两行代码创建的 Sweetviz 报告
【2021 年 1 月更新:Sweetviz 现在支持笔记本集成(您可以内嵌插入报告)和新功能!
探索性数据分析(EDA)是大多数数据科学项目中必不可少的早期步骤,它通常包括采取相同的步骤来表征数据集(例如,找出数据类型、缺失信息、值的分布、相关性等)。).考虑到这些任务的重复性和相似性,有一些库可以自动化并帮助启动这个过程。
最新的一个是一个新的开源 Python 库,名为 Sweetviz ( GitHub ),是由一些贡献者和我自己为此目的创建的。它获取 pandas 数据帧并创建一个自包含的 HTML 报告。
**它具有强大的冲击力;**除了只用两行代码就能创建深刻而美丽的可视化效果,它还提供了手动生成需要更多时间的分析,包括其他库无法如此快速提供的分析,例如:
- 两个数据集的比较(例如训练与测试)
- 目标值相对于所有其他变量的可视化(例如,“男性与女性的存活率是多少”等)。)
此处链接到 Sweetviz 为著名的样本泰坦尼克号幸存者数据集生成的报告。我们将在本文中分析这份报告。
埃达制造了…乐趣?!
能够如此快速地获得关于目标值的如此多的信息,并比较数据集的不同区域,几乎可以立即将这一最初步骤从枯燥乏味转变为更快、更有趣,甚至在某种程度上…更有趣!(对这个数据怪胎来说,至少!)当然,EDA 是一个漫长得多的过程,但至少第一步要顺利得多。让我们看看它如何与众所周知的样本数据集一起工作。
分析泰坦尼克号数据集
在这篇文章中,我们将分析样本泰坦尼克号幸存者数据集,你可以在这里找到。
安装 Sweetviz(使用pip install sweetviz
)后,只需像平常一样加载熊猫数据帧,然后根据需要调用analyze()
、compare()
或compare_intra()
(更多内容见下文)。完整的文档可以在 GitHub 上找到。现在,让我们从手头的案例开始,按如下方式加载:
import sweetviz
import pandas as pd
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")
我们现在有 2 个数据框架(训练和测试),我们想分析目标值“存活”。我想指出的是,在这种情况下,我们预先知道目标列的名称,但是指定目标列总是可选的。我们可以用这行代码生成一个报告:
my_report = sweetviz.compare([train, "Train"], [test, "Test"], "Survived")
运行此命令将执行分析并创建报告对象。要获得输出,只需使用show_html()
命令:
my_report.show_html("Report.html") # Not providing a filename will default to SWEETVIZ_REPORT.html
生成文件后,它将通过您的默认浏览器打开它,看起来应该是这样的:
要解开的东西很多,还是一步一步来吧!
汇总显示
摘要向我们并排显示了两个数据帧的特征。我们可以立即识别出测试集的大小大约是训练集的一半,但是它包含相同的特性。底部的图例向我们展示了训练集确实包含“幸存”的目标变量,但是测试集不包含。
请注意,Sweetviz 将在确定每列的数据类型时做出最佳猜测,介于数字、类别/布尔和文本之间。这些可以被覆盖,下面会详细介绍。
联合
将鼠标悬停在摘要中的“Associations”按钮上,关联图将出现在右侧:
这张图是由来自Drazen Zaric:Python 中更好的热图和相关矩阵图的视觉效果和来自 Shaked Zychlinski:分类相关性搜索的概念合成的。
基本上,除了显示传统的数值相关性之外,它还将数值相关性以及不确定性系数(分类-分类)和相关比率(分类-数值)统一在一个图表中。正方形代表分类特征相关变量,圆圈代表数值-数值相关性。注意,为了清楚起见,平凡的对角线是空的。
重要提示:分类-分类关联(由不确定系数提供)是不对称的,这意味着每一行代表行标题(在左边)给出了每一列的多少信息。比如“性”、“Pclass”、“Fare”是给出“幸存”信息最多的元素。对于 Titanic 数据集,这些信息是相当对称的,但情况并非总是如此。
最后,值得注意的是,这些相关/关联方法不应该被视为真理,因为它们对数据和关系的底层分布做出了一些假设。然而,它们可能是一个非常有用的起点。
目标变量
当一个目标变量被指定时,它会首先出现在一个特殊的黑框中。
重要提示:目前只有数字和布尔特征可以作为目标。
我们可以从这个总结中推断出,“幸存”在训练集中没有缺失数据(891,100%),有 2 个不同的可能值(占所有值的不到 1%),并且从图中可以估计出大约 60%没有幸存。
详细区域(分类/布尔型)
当您移动鼠标悬停在任何变量上时,右侧的区域将显示详细信息。细节的内容取决于被分析变量的类型。在分类(或布尔)变量的情况下,与目标的情况一样,分析如下:
重要提示:此时需要一个“宽屏”显示器来看到整个细节区域。
在这里,我们可以看到每个班级的准确统计数据,其中 62%没有幸存,38%幸存。您还可以获得每个其他特性的关联细节。
数据
数字数据在其摘要中显示了更多信息。在这里,我们可以看到,在这种情况下大约有 20%的数据丢失(测试数据中有 21%,这是非常一致的)。
注意,目标值(在本例中为“幸存”)绘制成一条线,位于分布图的正上方。这使得能够针对其他变量对目标分布进行即时分析。
有趣的是,我们可以从右边的图表中看到,除了年龄最小的存活率较高之外,所有年龄段的存活率都相当一致。看起来“妇女和儿童优先”不只是说说而已。
详细区域(数字)
与分类数据类型一样,数值数据类型在其细节区域显示一些额外的信息。值得注意的是图表顶部的按钮。这些按钮改变图表中显示的“箱子”数量。您可以选择以下选项:
- 汽车
- 5
- 15
- 30
注:要使用这些按钮,您需要通过点击来“锁定”当前功能。然后,该特征会有一个红色轮廓,表示它已锁定到位,您可以访问详细信息区域。
例如,选择“30”会生成一个更加精细的图表:
文本数据
目前,系统不认为是数字或分类的任何内容都将被视为“文本”。文本功能目前仅将计数(百分比)显示为统计数据。
FeatureConfig:强制数据类型,跳过列
在许多情况下,您可能不想分析“标签”列(尽管目标分析可以基于标签提供关于目标值分布的见解)。在其他情况下,您可能希望强制将一些值标记为分类值,即使它们实际上是数值。
要做到这一切,只需创建一个 FeatureConfig 对象并将其传递给分析/比较函数。您可以为 kwargs skip
、force_cat
和force_text
指定一个字符串或一个列表:
feature_config = sweetviz.FeatureConfig(skip="PassengerId", force_cat=["Ticket"])my_report = sweetviz.compare([train, "Train"], [test, "Test"], "Survived", feature_config)
比较亚人群(例如男性和女性)
即使您只查看单个数据集,研究该数据集中不同亚群的特征也会非常有用。为此,Sweetviz 提供了compare_intra()
函数。要使用它,你需要提供一个布尔测试来分割人群(这里我们尝试train["Sex"] == 'male'
,来了解不同性别的人群),并给每个子人群起一个名字。例如:
my_report = sweetviz.compare_intra(train, train["Sex"] == 'male', ["Male", "Female"], 'Survived')my_report.show_html() # Not providing a filename will default to SWEETVIZ_REPORT.html
产生以下分析:(对于这个截图,我使用 feature_config 来跳过对“Sex”特性的分析,因为它是多余的)
注意,目标值(本例中为“存活”)现在绘制为单独的线条,每个对比数据集一条(例如,蓝色为男性,橙色为女性)。
把所有的放在一起
EDA 是一个流动的、艺术化的过程,必须针对每一组数据和情况进行独特的调整。然而,像 Sweetviz 这样的工具可以帮助启动这一过程,并消除表征数据集的许多初始细节,从而立即提供见解。让我们浏览一下泰坦尼克号数据集的所有特征,看看它会是什么样子。
单个字段
乘客 Id
- ID 和生存能力的分布是均匀有序的,正如你所希望的那样,所以这并不奇怪。
- 没有丢失数据
性
- 男性大约是女性的两倍,但是…
- 女性比男性更有可能存活
- 从相关性来看,性别与票价相关,这并不奇怪…
- 训练和测试之间的相似分布
- 没有丢失数据
年龄
- 20%的缺失数据、一致的缺失数据以及培训和测试之间的分布
- 以年轻人为中心的人口,但 0-70 岁的人口比例较高
- 出人意料的均匀分布的生存能力,除了在最年轻的年龄峰值
- 使用详细信息窗口直方图中的 30 个柱,您可以看到这个生存性峰值实际上是针对最小的(大约< = 5 岁),因为在大约 10 岁时,生存性非常低。
- 年龄似乎与兄弟姐妹、阶级和费用有关,更令人惊讶的是与上船有关
名称
- 没有丢失数据,数据看起来很干净
- 所有的名字都不同,这并不奇怪
Pclass
- 生存能力紧随职业之后(第一职业最有可能生存,第三职业最不可能)
- 训练和测试之间的相似分布
- 没有丢失数据
SibSp
- 在 1 处似乎有一个生存峰值,在某种程度上在 2 处也有,但是(查看这里没有显示的细节窗格)在 3 处和更大处有一个急剧下降。大家庭做不到或者更穷?
- 训练和测试之间的相似分布
- 没有丢失数据
炒制
- 训练和测试之间的相似分布
- 没有丢失数据
票
- 约 80%的不同值,因此平均约有五分之一的共享票证
- 最高频率的票是 7,这与兄弟姐妹的最大数量(8)基本一致
- 没有丢失数据,数据看起来很干净
票价
- 正如预期的那样,与 Pclass 一样,较高的票价更好地保留了下来(尽管样本量在较高的水平变得相当少)
- “存活”的相关比率为 0.26,相对较高,因此倾向于支持这一理论
- 大约 30%的不同值感觉有点高,因为你会期望更少的设定价格,但看起来有很多粒度,所以这没问题
- 测试集中只有 1 条记录缺失,训练和测试之间的数据相当一致
机舱
- 大量缺失数据(高达 78%),但是在训练和测试之间是一致的
- 最大频率为 4,这意味着一个客舱最多容纳 4 人
上船
- 3 个不同的值(S,C,Q)
- 列车数据中只有 2 行缺失。训练和测试之间的数据似乎相当一致
- C 时的生存能力稍高一些;这里会是富人聚集的地方吗?
- 无论哪种方式,“已上船”显示“幸存”的不确定系数仅为 0.03,因此可能不太显著
一般分析
- 总的来说,大部分数据是存在的,似乎是一致的,有意义的;没有重大异常或巨大的惊喜
测试对比训练数据
- 测试的行数减少了大约 50%
- 训练和测试在缺失数据的分布上非常接近
- 训练和测试数据值在所有方面都非常一致
关联/相关性分析
- 性别、费用和阶级提供了关于幸存者的最多信息
- 不出所料,Fare 和 Pclass 高度相关
- 年龄似乎告诉了我们很多关于阶级、兄弟姐妹和某种程度上的费用的信息,这在某种程度上是意料之中的。它似乎告诉了我们很多关于“上船”的事情,这有点令人惊讶。
缺失数据
- 除了年龄(20%)和客舱(77%)之外,没有重要的缺失数据(在其他特征上也有一些奇怪的数据)
结论
所有这些信息都来自两行代码!
当我开始查看一个新数据集时,使用 Sweetviz 很容易给我一个重要的启动。值得指出的是,我还发现在分析过程的后期,例如在特性生成期间,快速了解新特性是如何发挥作用的。我希望你会发现它在你自己的数据分析中是一个有用的工具。
增强探索性数据分析性能的强大软件包
熊猫简介,Sweetviz,数据浏览器
SpaceX 在 Unsplash 上拍摄的
数据探索或探索性数据分析(EDA)是进行数据科学项目的一个重要阶段。这一步的目标是通过数据获得有价值的见解,以便人们可以知道数据发生了什么,需要清理哪个部分,可以构建哪些新功能,在模型创建/验证阶段构建要测试的假设,甚至只是知道一些关于数据的有趣事实。
“一张高质量的图表抵得上一千条真知”
等等,什么是高质量的图表??是超高清画质的图表吗??—我所说的高质量图表是指从特定变量或 2 个或更多变量之间的相互作用中捕捉有趣故事的图表。问题是:
一个人怎么能制作出那种“超级”图表呢??
制作该图表听起来很难…即使已经制作了该图表,也会产生其他问题:
这张图表提供了足够的见解吗?有没有其他种类的图表提供完全不同的见解?我们必须生成图表才能从数据中获得洞察力吗?
在本文中,我将介绍 3 个非常棒的免费软件包,它们可以生成包含各种 EDA 的 HTML 报告,只需几行 Python 代码!
我将试着把重点放在每个包所提供的最佳特性上,以及它们是如何相互补充的。这里使用了 Titanic 数据集来做比较。
你可以在这里找到本文中使用的所有代码。
熊猫简介
这个软件包的主要卖点是在一个 HTML 报告中提供了广泛的分析和深入的单变量分析!
生成的报告有 5 个部分:概述,变量,交互,相关性,缺失值,样本
熊猫概况报告部分
生成报告的第一部分是概述部分。该部分有 3 个标签:概述、再现、警告。
概述 —该选项卡提供数据的概述,包括变量数量、样本数量、缺失单元格、重复行、内存总大小、内存平均记录大小,以及基于类型的变量分布。
熊猫概况选项卡
再现 —该选项卡提供了该软件包如何执行分析和生成报告的详细信息。
熊猫轮廓再现标签
警告 —如果数据中的每个变量有错误或需要处理,该选项卡提供非常有用的信息。人们可以很容易地首先看到这个选项卡,对数据进行数据清理或一些特征工程。
熊猫概况警告选项卡
神奇的事情发生在第二节:变量。根据变量类型,可以看到对每个变量的深入单变量分析,范围从数值分析、Unicode 分析、URL 分析,甚至是图像分析。
熊猫概况单变量数值分析示例
Pandas 评测单变量 Unicode 分析示例
在我看来,熊猫概况报告中的互动部分并不真正有见地。因此,我们将进入下一部分:**相关性。**本节提供了 5 种不同方法的相关性分析!其中一种方法可以计算分类变量、顺序变量和区间变量之间的相关性。
熊猫概况相关分析,可以计算不同类型的变量之间的相关性
同样,在我看来,缺失值部分并不真正有见地,因为该信息已经在变量部分中提供了。最后,熊猫概况报告的最后一部分是样本部分。这一部分提供了数据的前 10 行和后 10 行,这对于了解数据的真实情况非常有用。
熊猫概况样本部分
一份很有见地的报告,对吧?好消息是,只需 10 行代码就可以轻松生成这份熊猫概况 HTML 报告!
Sweetviz
这个包的主要卖点是目标分析,训练和测试集的比较,以及一个非常酷的用户界面,所有这些都在一个 HTML 报告中!
Sweetviz HTML 报告
Sweetviz 是一个新发布的包(2020 年 5 月),它提供了一个非常优雅的 HTML 报告。与 Pandas Profiling 不同的是,这个包生成的 HTML 报告不是按节划分的。在报告的顶部,可以看到列车和测试装置的对比总结。为了更深入地比较训练集和测试集,以及强大的目标分析,用户可以浏览每个变量“卡”。
Sweetviz 卡
在每张卡片上,人们还可以看到特定变量和其余变量之间的分类和数字关联。令人兴奋的是这个包可以处理不止一种类型的变量。例如,’ boat '变量在分类关联表和数字关联表中被赋值。
又一份很酷的报告,对吧?即使现在只有 3 行代码,也可以很容易地生成这个 HTML 报告。
数据浏览器
这个软件包的主要卖点是在一个 HTML 报告中的目标分析和主成分分析!
供您参考,DataExplorer 是一个 R 包。然而,在 RPy2 的帮助下,人们可以很容易地使用 Python 中的任何 R 包。如果你对这个更感兴趣,你可以查看这个奇库。
数据资源管理器 HTML 报表
与 Pandas Profiling 相同,使用这个包生成的报告也分为几个部分。在我看来,人们可以从这份报告中利用的最有用的特征是主成分分析和双变量分布部分。
DataExplorer PCA 分析
DataExplorer 二元分布分析示例
因为这是一个在 Python 中使用的 R 包,所以需要更多行代码来生成这个报告。
摘要
综上所述,在我看来,应该考虑使用所有这 3 个强大的软件包来提高 EDA 在时间效率和分析质量方面的性能。这些产品包各有千秋:
- Pandas Profiling —分析的广度和单变量分析的深度。
- Sweetviz —目标分析、训练和测试集的比较,以及非常酷的用户界面。
- DataExplorer —目标分析和主成分分析。
真正重要的是:所有的报告都可以很容易地生成,只需要几行代码!
额外片段
以下是熊猫概况报告中图像和 URL 分析生成的片段。
熊猫轮廓图像分析
熊猫概况 URL 分析
关于作者
Louis Owen 是一名数据科学爱好者,他总是渴望获得新知识。他在印度尼西亚顶尖大学Institut Teknologi Bandung攻读数学专业,并获得了最后一年的全额奖学金。
Louis 曾在多个行业领域担任分析/机器学习实习生,包括 OTA()、电子商务( Tokopedia )、FinTech ( Do-it )、智慧城市 App ( Qlue 智慧城市 ),目前在 世界银行 担任数据科学顾问。
去路易斯的网站了解更多关于他的信息吧!最后,如果您有任何疑问或需要讨论的话题,请通过 LinkedIn 联系 Louis。
参考
从熊猫生成档案报告。熊猫的 df.describe()函数很棒,但是对于严肃的……
pandas-profiling.github.io](https://pandas-profiling.github.io/pandas-profiling/docs/master/rtd/) [## fbdesignpro/sweetviz
Sweetviz 是一个开源 Python 库,可以为 kickstart EDA 生成漂亮的高密度可视化效果…
github.com](https://github.com/fbdesignpro/sweetviz) [## DataExplorer 简介
这个文档介绍了 DataExplorer 包,并展示了它如何帮助你完成不同的任务…
cran.r-project.org](https://cran.r-project.org/web/packages/DataExplorer/vignettes/dataexplorer-intro.html)*
强大的终极二分搜索法模板和许多 LeetCode 问题
在几分钟内编写无 python 解决方案的伟大工具
介绍
二分搜索法在概念上很容易理解。基本上,它将搜索空间分成两半,只保留可能有搜索目标的一半,而丢弃可能没有答案的另一半。这样,我们在每一步都将搜索空间缩小一半,直到找到目标。二分搜索法帮助我们将搜索时间从线性 O(n)减少到对数 O(log n)。但是说到实现,要在几分钟内写出一个没有错误的代码是相当困难的。一些最常见的问题包括:
- 何时退出循环?应该用
left < right
还是left <= right
作为 while 循环条件? - 如何初始化边界变量
left
和right
? - 如何更新边界?如何从
left = mid
、left = mid + 1
和right = mid
、right = mid — 1
中选择合适的组合?
对二分搜索法的一个相当普遍的误解是,人们通常认为这种技术只能用在简单的场景中,比如“给定一个排序的数组,从中找出一个特定的值”。事实上,它可以应用于更复杂的情况。
在 LeetCode 中做了大量的练习后,我制作了一个强大的二分搜索法模板,并通过稍微扭曲这个模板解决了许多难题。我会在这篇文章中与你们分享这个模板。我不想只是炫耀代码就离开。最重要的是,我想分享逻辑思维:如何将这个通用模板应用于各种问题。希望看完这篇文章后,人们不会再因为听到“神圣的 sh*t!这个问题可以用二分搜索法来解决!我以前怎么没想到呢!”
最广义的二分搜索法
假设我们有一个搜索空间。它可以是数组、范围等。通常是按升序排序的。对于大多数任务,我们可以将需求转换为以下通用形式:
最小化 k,s.t .条件(k)为真
以下代码是最通用的二分搜索法模板:
这个模板真正的好处是,对于大多数二分搜索法问题,我们只需要在复制粘贴这个模板后修改三个部分,再也不用担心代码中的死角和 bug 了:
- 正确初始化边界变量
left
和right
。只有一个规则:设置边界使包含所有可能的元素; - 决定返回值。是
return left
还是return left — 1
?记住这个:退出 while 循环后,**left**
是满足**condition**
函数的最小 k; - 设计
condition
功能。这是最难也是最美的部分。需要大量的练习。
下面我将向你们展示如何将这个强大的模板应用于许多 LeetCode 问题。
施基肥
你是一名产品经理,目前正带领一个团队开发新产品。不幸的是,最新版本的…
leetcode.com](https://leetcode.com/problems/first-bad-version/)
首先,我们初始化left = 1
和right = n
以包含所有可能的值。然后我们注意到我们甚至不需要设计condition
函数。它已经由isBadVersion
API 给出了。找到第一个坏版本就相当于找到满足isBadVersion(k) is True
的最小 k。我们的模板非常适合:
实现 int sqrt(int x)。计算并返回 x 的平方根,其中 x 保证为非负整数…
leetcode.com](https://leetcode.com/problems/sqrtx/)
相当简单的问题。我们需要搜索满足k^2 <= x
的最大 k,因此我们可以很容易地得出解决方案:
有一件事我想指出来。记得我说过我们通常寻找满足特定条件的最小 k 值吗?但是在这个问题中,我们寻找的是最大的 k 值。感到困惑?不要这样。实际上,满足isBadVersion(k) is False
的最大 k 正好等于满足isBadVersion(k) is True
的最小 k 减一。这就是为什么我之前提到我们需要决定返回哪个值,left
还是left — 1
。
给定一个排序数组和一个目标值,如果找到目标,则返回索引。如果没有,返回索引…
leetcode.com](https://leetcode.com/problems/search-insert-position/)
非常经典的二分搜索法应用。我们正在寻找满足nums[k] ≥ target
的最小 k,我们可以复制粘贴我们的模板。注意,不管输入数组nums
是否有重复,我们的解决方案都是正确的。还要注意,输入target
可能比nums
中的所有元素都大,因此需要放在数组的末尾。这就是为什么我们应该初始化right = len(nums)
而不是right = len(nums) — 1
。
高级应用
上述问题相当容易解决,因为它们已经给了我们要搜索的数组。乍一看,我们就知道应该用二分搜索法来解决这些问题。然而,更常见的情况是搜索空间和搜索目标不那么容易获得。有时我们甚至不会意识到问题应该用二分搜索法来解决——我们可能只是求助于动态编程或 DFS,然后陷入很长一段时间。
至于“什么时候可以用二分搜索法”这个问题,我的回答是,如果我们能发现某种单调性,例如,如果 **condition(k) is True**
那么 **condition(k + 1) is True**
,那么我们可以考虑二分搜索法。
传送带上的包裹必须在 D 天内从一个港口运送到另一个港口。第 I 个包裹在…
leetcode.com](https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/)
当我们第一次遇到这个问题时,可能不会想到二分搜索法。我们可能会自动将weights
视为搜索空间,然后意识到在浪费了大量时间后,我们进入了一个死胡同。事实上,我们正在寻找所有可行容量中最小的一个。我们挖掘出这个问题的单调性:如果我们能在D
天内用容量m
成功装运所有包裹,那么我们就一定能把任何大于m
的容量全部装运。现在我们可以设计一个condition
函数,姑且称之为feasible
,给定一个输入capacity
,它返回是否有可能在D
天内装运所有包裹。这可能以一种贪婪的方式运行:如果当前的包裹还有空间,我们将这个包裹放在传送带上,否则我们等待第二天放置这个包裹。如果需要的总天数超过了D
,我们返回False
,否则我们返回True
。
接下来,我们需要正确初始化我们的边界。显然capacity
至少应该是max(weights)
,否则传送带运不出最重的包裹。另一方面,capacity
不需要比sum(weights)
多,因为这样我们就可以在一天之内把所有的包裹都发货了。
现在,我们已经获得了应用二分搜索法模板所需的所有信息:
给定一个由非负整数和一个整数组成的数组,你可以把数组分成非空的…
leetcode.com](https://leetcode.com/problems/split-array-largest-sum/)
如果你仔细观察,你可能会发现这个问题与上面的 LC 1011 有多么相似。类似地,我们可以设计一个feasible
函数:给定一个输入threshold
,然后决定是否可以将数组分成几个子数组,使得每个子数组的和小于或等于threshold
。这样我们就发现了问题的单调性:如果feasible(m)
是True
,那么所有大于m
的输入都能满足feasible
函数。你可以看到解决方案代码与 LC 1011 完全相同。
但是我们很可能会有疑问:我们的解返回的left
确实是满足feasible
的最小值,但是我们怎么知道我们可以把原数组拆分为实际得到这个子数组和?比如说nums = [7,2,5,10,8]
和m = 2
。我们有 4 种不同的方法来分裂阵列,从而相应地得到 4 个不同的最大子阵列和:25:[[7], [2,5,10,8]]
、23:[[7,2], [5,10,8]]
、18:[[7,2,5], [10,8]]
、24:[[7,2,5,10], [8]]
。只有 4 个值。但是我们的搜索空间[max(nums),sum(nums)]=[10,32]
不仅仅只有 4 个值。也就是说,无论我们如何分割输入数组,我们都无法获得搜索空间中的大多数值。
假设k
是满足feasible
函数的最小值。我们可以用反证法证明我们解决方案的正确性。假设没有子阵列的和等于k
,即每个子阵列的和小于k
。feasible
函数中的变量total
记录当前负载的总重量。如果我们的假设是正确的,那么total
将总是小于k
。因此,feasible(k-1)
必须是True
,因为total
最多等于k-1
并且永远不会触发 if 子句if total > threshold
,因此feasible(k-1)
必须具有与feasible(k)
相同的输出,即True
。但是我们已经知道k
是满足feasible
函数的最小值,那么feasible(k-1)
就得是False
,这是一个矛盾。所以我们的假设是不正确的。现在我们已经证明了我们的算法是正确的。
科科喜欢吃香蕉。有 N 堆香蕉,第 I 堆有成堆的香蕉。警卫已经走了,而且…
leetcode.com](https://leetcode.com/problems/koko-eating-bananas/)
非常类似上面提到的 LC 1011 和 LC 410。让我们设计一个feasible
函数,给定一个输入speed
,确定科科是否能以每小时的进食速度speed
在H
小时内吃完所有香蕉。显然,搜索空间的下界是 1,上界是max(piles)
,因为科科每小时只能选择一堆香蕉吃。
给定一个整数数组 bloomDay,一个整数 m 和一个整数 k。我们需要做 m 个花束。要制作花束,你需要…
leetcode.com](https://leetcode.com/problems/minimum-number-of-days-to-make-m-bouquets/)
既然我们已经解决了上面的三个高级问题,这一个应该很容易做到。这个问题的单调性非常明显:如果我们能在等待d
天后制作m
花束,那么如果我们等待超过d
天,我们肯定也能完成。
几乎每个人都用过乘法表。但是你能从…中快速找出第 k 个最小的数字吗?
leetcode.com](https://leetcode.com/problems/kth-smallest-number-in-multiplication-table/description/)
对于像这样的最小问题,我们首先想到的是堆。通常,我们可以维护一个最小堆,并只弹出堆的顶部 k 次。然而,这在这个问题中是行不通的。我们没有整个乘法表中的每个数字,相反,我们只有表的高度和长度。如果我们要应用堆方法,我们需要显式地计算这些m*n
值并将它们保存到堆中。这个过程的时间复杂度和空间复杂度都是 O(mn),效率相当低。这是二分搜索法进来的时候。还记得我们说设计condition
功能是最难的部分吗?为了找到表中第 k 个最小值,我们可以设计一个enough
函数,给定一个输入num
,判断是否至少有 k 个值小于或等于num
。满足 **enough**
函数的最小 num 就是我们要找的答案。回想一下,二分搜索法的关键是发现单调性。在这个问题中,如果num
满足enough
,那么当然任何大于num
的值都可以满足。这种单调性是我们的二分搜索法算法的基础。
让我们考虑搜索空间。显然下界应该是 1,上界应该是乘法表中的最大值,也就是m * n
,那么我们就有了搜索空间[1, m * n]
。与堆解决方案相比,二分搜索法解决方案的压倒性优势在于,它不需要显式计算表中的所有数字,它只需要从搜索空间中选取一个值,并将enough
函数应用于该值,以确定我们应该保留搜索空间的左半部分还是右半部分。这样,二分搜索法方案只需要恒定的空间复杂度,比堆方案好得多。
接下来让我们考虑如何实现enough
功能。可以观察到,乘法表中的每一行都只是其索引的倍数。例如,第三行[3,6,9,12,15...]
中的所有数字都是 3 的倍数。因此,我们可以逐行计数小于或等于输入num
的条目总数。以下是完整的解决方案。
在上面的 LC 410 中,我们怀疑“二分搜索法的结果实际上是子阵列和吗?”。这里我们有一个类似的疑问:“二分搜索法的结果真的在乘法表里吗?”。答案是肯定的,我们也可以用矛盾来证明。将num
表示为满足enough
功能的最小输入。我们假设num
不在表中,也就是说num
不能被[1, m]
中的任何一个val
整除,也就是说num % val > 0
。因此,将输入从num
更改为num - 1
对表达式add = min(num // val, n)
没有任何影响。所以enough(num)
也会返回True
,就像enough(num)
一样。但是我们已经知道num
是满足enough
函数的最小输入,所以enough(num - 1)
必须是False
。矛盾!与我们最初的假设相反的是正确的:num
实际上在表中。
提高你的编码技能,迅速找到工作。这是扩展你的知识和做好准备的最好地方…
leetcode.com](https://leetcode.com/problems/find-k-th-smallest-pair-distance/)
非常类似于上面的 LC 668,两者都是关于寻找第 k 个最小的。就像 LC 668 一样,我们可以设计一个enough
函数,给定一个输入distance
,确定是否至少有 k 对的距离小于或等于distance
。我们可以对输入数组进行排序,并用两个指针(快指针和慢指针,指向一对)对其进行扫描。两个指针都从最左端开始。如果当前指向的指针对的距离小于或等于distance
,则这些指针之间的所有指针对都是有效的(因为数组已经排序),我们将快速指针向前移动。否则,我们将慢速指针向前移动。当两个指针都到达最右端时,我们完成扫描,并查看总计数是否超过 k。实现如下:
显然,我们的搜索空间应该是[0, max(nums) - min(nums)]
。现在我们准备复制粘贴我们的模板:
提高你的编码技能,迅速找到工作。这是扩展你的知识和做好准备的最好地方…
leetcode.com](https://leetcode.com/problems/ugly-number-iii/)
没什么特别的。仍然在寻找最小的。我们需要设计一个enough
函数,给定一个输入num
,确定是否有至少 n 个丑数小于或等于num
。由于a
可能是b
或c
的倍数,或者反过来,我们需要最大公约数的帮助来避免计算重复数。
给定一个整数数组 num 和一个整数阈值,我们将选择一个正整数除数,并将所有的
leetcode.com](https://leetcode.com/problems/find-the-smallest-divisor-given-a-threshold/)
上面介绍了这么多问题,这个应该是小菜一碟。我们甚至不需要费心去设计一个condition
函数,因为问题已经明确告诉我们需要满足什么条件。
结束
哇,非常感谢你坚持到最后,真的很感激。从上面的 python 代码中可以看出,它们看起来都非常相似。那是因为我一直在复制粘贴我的模板。没有例外。这是我的模板强大的有力证明。我相信每个人都可以获得这个二分搜索法模板来解决许多问题。我们所需要的只是更多的练习来建立我们发现问题单调性的能力,并设计一个漂亮的condition
函数。
希望这有所帮助。
参考
- 【c++/快速/非常清晰的解释/干净的代码】贪婪算法和二分搜索法的解决方案
- 使用“试错”算法解决问题
- 二分搜索法 101 终极二进制搜索手册——leet code
- 丑女三号二分搜索法配图&二分搜索法模板— LeetCode
“启动”撒哈拉以南非洲的卫生设施
使用开放存取数据的探索性方法& Python 中的空间分析
马丁·桑切斯在 Unsplash 上的照片
目录
动机
据估计,全球约有 7 . 89 亿人没有电力供应。绝大多数(约 75% )位于撒哈拉以南非洲。这是一个影响社会经济发展和人类福祉的关键服务差距,特别是在最不发达地区的贫困农村人口中。
与此同时,新冠肺炎突出强调了电力在卫生部门的重要性。在诊所和卫生站获得电力,使人们保持联系,便于信息管理、药品冷藏和其他服务,以保护弱势群体。因此,缺乏可靠的电力正在损害数百万人的医疗保健质量。
这就迫切需要“加强”最不发达地区的卫生设施,以便及时应对新冠肺炎危机。
本博客介绍了一种探索性的、基于 GIS 的方法,用于在缺乏这类详细数据的地区估算医疗机构的电力需求。它利用现有的开放访问数据集(和模型),以提供这些设施中年度电力需求的高水平画面,并随后指示如何作为最低成本电气化计划的一部分来满足这些需求。
下面的例子集中在莫桑比克的 Mecanhelas 区(任意选择)。然而,该代码可用于在任何行政级别(例如,国家和/或区域)扩大分析。
循序渐进的指南
第一步。设置 python 环境和导入数据集
导入必要的模块
作为 Jupyter 中任何建模练习的一部分,第一步需要导入必要的 python 模块。你可以参考 requirements.txt 来检查这个例子的依赖关系。
# Import python modules
import geopandas as gpd
import pandas as pd
import pyproj
import numpy as np
from functools import reduce
from shapely.geometry import Point, Polygon, MultiPoint
from shapely.ops import nearest_pointsimport datapane as dp
# !datapane login --token="yourpersonaltoken"import folium
from folium.features import GeoJsonTooltip
import branca.colormap as cm
import os
from IPython.display import display, Markdown, HTML
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
%matplotlib inline
导入数据集
在这里,我们导入将要使用的数据集。其中包括以下三种:
**1。行政边界(矢量多边形)😗*这定义了我们感兴趣区域的边界框。在这个例子中,我们使用的是莫桑比克西北部省份 Mecanhelas 的行政边界。你可以从 GADM 那里取回这个。
2。卫生设施的位置(向量点):在这种情况下,我们使用由 Maina 等人提供的卫生设施的空间数据库。该数据集包括 98,745 个公共卫生机构,所有这些机构都有地理位置。
3。人口集群(矢量多边形):这是指建成区的矢量化版本,如 Korkovelos 等人所述。撒哈拉以南非洲所有国家的人口集群都是开放的,可在 PopClusters 上获得。(在本练习中,我们使用 2020 年 9 月 1 日发布的版本 6)。
注 1 。出于本练习的目的,在导入笔记本之前,( 2)和(3)都基于(1)进行了剪裁。你可以使用 geopandas 或 Qgis 来完成这项工作。
注 2 。在导入之前,所有数据集都在 WGS84 坐标系中。请确保这是事实,否则请纠正。
将行政边界作为地理数据框架导入
# Define path and name of the file
admin_path = r"input_data\Testing_Sample"
admin_name = "mecanhelas_admin.gpkg"# Create a new geo-dataframe
admin_gdf = gpd.read_file(admin_path + "\\" + admin_name)# Create the axis first
fig, ax = plt.subplots(figsize=(10, 10))
admin_gdf.plot(ax=ax, edgecolor='black', alpha=0.2)
ax.set_aspect('equal', 'box')
txt = ax.set_title('Mecanhelas Administrative Boundary'.format(""))
莫桑比克 Mecanhelas 区的行政区域—图片由作者提供
进口卫生设施
注意为了让下面的代码正常工作,这应该是一个“点”层;如果几何特征为“多点”,您应该将其转换为“点”以继续。你可以使用 Qgis 来完成这项工作。
# Define path and name of the file
health_path = r"input_data\Testing_Sample"
health_name = "mec_health_index.gpkg"# Create a new geo-dataframe
health_gdf = gpd.read_file(health_path + "\\" + health_name)health_gdf.head(3)
…和可视化
fig, ax = plt.subplots(figsize=(10, 10))
admin_gdf.plot(ax=ax, edgecolor='brown', alpha=0.2)
health_gdf.plot(ax=ax, legend=True, markersize=3, figsize=(15, 15), alpha=0.5)
ax.set_aspect('equal', 'box')
txt = ax.set_title('Location of health facilities in Mecanhelas'.format(""))
莫桑比克 Mecanhelas 卫生机构的位置—图片由作者提供
导入人口聚类
# Define path and name of the file
clusters_path = r"input_data\Testing_Sample"
clusters_name = "mecanhelas_clusters.gpkg"clusters_gdf = gpd.read_file(clusters_path + "\\" + clusters_name)clusters_gdf.head(2)
…并使用每个聚类的质心创建新的地理数据框
clusters_centroid = gpd.GeoDataFrame(clusters_gdf, geometry=clusters_gdf.centroid)fig, ax = plt.subplots(figsize=(10, 10))
admin_gdf.plot(ax=ax, edgecolor='brown', alpha=0.2)
clusters_centroid.plot(ax=ax, legend=True, markersize=3, figsize=(15, 15), alpha=0.5)
ax.set_aspect('equal', 'box')
txt = ax.set_title('Population cluster centroids in Mecanhelas'.format(""))
莫桑比克 Mecanhelas 区的“矢量化”建筑——图片由作者提供
输入的数据表明,Mecanhelas 有 10,703 个人口集群(或定居点),由 19 个卫生设施提供服务。
第二步。数据集的空间处理
一旦数据集成功导入,我们就可以为医疗机构计算简单的空间统计数据。也就是说,我们使用它们的位置并从附近的人口聚类中提取值。这里我们有两个选择。
选项 1-最近枢纽分析
部署最近中心分析,并计算与每个医疗机构的“集水区”相关的统计数据。
注意下面的 NNA 代码是从 shakasom 中检索出来的。
# Simple function getting the nearest hub for a given set of points
def calculate_nearest(row, destination, val, col="geometry"):
dest_unary = destination["geometry"].unary_union
nearest_geom = nearest_points(row[col], dest_unary)
match_geom = destination.loc[destination.geometry == nearest_geom[1]]
match_value = match_geom[val].to_numpy()[0]
return match_value
为每个集群分配最近的医疗机构
clusters_centroid["index"] = clusters_centroid.apply(calculate_nearest, destination=health_gdf, val="index", axis=1)
基于医疗机构 id 分解聚类,并计算每个医疗机构的基本统计数据
stat_list = ['sum', 'mean', 'count']
HF_hub_stats = clusters_centroid.dissolve(by='index', aggfunc=stat_list)
**注意!**这会产生一个多点矢量层;每个多点包含由同一医疗机构提供服务的聚类(质心)的位置。
将结果与初始医疗设施点图层合并
这是为了在原始医疗机构数据帧中附加新检索的统计数据。
HF_hub = health_gdf.merge(HF_hub_stats, on="index")
整理结果后,选项 1 生成以下地理数据框,其中根据聚类的最近距离计算每个医疗机构的基本统计数据。
选项 2 —基于缓冲区的统计
将缓冲区应用于每个医疗机构,并计算落入其中的集群的统计数据。这种方法计算量较小。
首先,我们需要将图层投影到正确的 CRS 中
在这种情况下,我们使用 epsg.io 中为莫桑比克标识的“epsg:32737”。
admin_gdf_prj = admin_gdf.to_crs({'init': 'epsg:32737'})
health_gdf_prj = health_gdf.to_crs({'init': 'epsg:32737'})
clusters_gdf_prj = clusters_gdf.to_crs({'init': 'epsg:32737'})# Drop selected columns
clusters_gdf_prj.drop(["index"], axis=1, inplace=True)
clusters_gdf_prj.head(2)
…我们重新生成了群集质心层,只是这次使用了投影的群集
clusters_centroid_proj = gpd.GeoDataFrame(clusters_gdf_prj, geometry=clusters_gdf_prj.centroid)
为每个卫生设施增加一个缓冲区
health_gdf_prj['geometry'] = health_gdf_prj.geometry.buffer(1000) # in meters
应用空间连接
#Spatial join
health_gdf_prj_joined = gpd.sjoin(clusters_centroid_proj, health_gdf_prj, op='within', how='right')health_gdf_prj_joined.head(2)
基于索引对要素进行分组
# Basic statistics to calculate
stat_list = ['sum', 'mean', 'count']
# Apply groupby function
HF_buf_stats = health_gdf_prj_joined.dissolve(by='index', aggfunc=stat_list)
与初始医疗机构数据集合并
HF_buf = health_gdf_prj.merge(HF_buf_stats, on="index")
将结果转换为原始 CRS 中的地理数据框
## Creating a geo-dataframe - appointing geometry attribute
HF_buf['geometry'] = list(zip(HF_buf['Lon'], HF_buf['Lat']))
HF_buf['geometry'] = HF_buf['geometry'].apply(Point)
HF_buf_gdf = gpd.GeoDataFrame(HF_buf, geometry='geometry', crs={'init': 'epsg:4326'})
整理结果后,选项 2 生成以下地理数据框,其中基于缓冲区计算每个医疗机构的基本统计数据。
描述性分析
无论选择何种方法(选项 1 或选项 2 ),生成的地理数据框架都具有相似的格式。接下来,我们希望对结果进行描述性分析,以便了解数据类型和潜在的分类技术。
选项 1 的结果
HF_hub_gdf.pop_sum.describe()count 19.000000
mean 26882.061818
std 10771.348988
min 5685.042735
25% 21419.189453
50% 25469.963919
75% 30545.254864
max 59730.107002
Name: pop_sum, dtype: float64bin_values = np.arange(start=0, stop=HF_hub_gdf.pop_sum.sum())
HF_hub_gdf['pop_sum'].hist(figsize=[14,6])
plt.title("Population served by each health facility")
plt.show()
按作者分类的图表
# remove inconsistencies hospital type names
HF_hub_gdf["fctype"].replace("\?", 'u', regex=True, inplace=True)
# remove inconsistencies hospital type names
HF_hub_gdf["fcname"].replace("\?", 'u',regex=True, inplace=True)ls_of_hf = HF_hub_gdf.fctype.unique()
print('\nThis administrative area has {} different types of hospitals:\n'.format(len(ls_of_hf)))
print(*ls_of_hf, sep = '\n')**This administrative area has 2 different types of hospitals:**
Centro de Saude Rural II
Centro de Saude Rural I
选项 2 的结果
HF_buf_gdf.pop_sum.describe()count 19.000000
mean 4121.879924
std 6517.540750
min 253.035754
25% 819.507531
50% 991.796760
75% 2666.860946
max 20250.234550
Name: pop_sum, dtype: float64bin_values = np.arange(start=0, stop=HF_buf_gdf.pop_sum.sum())
HF_buf_gdf['pop_sum'].hist(figsize=[14,6])
plt.title("Population served by each health facility")
plt.show()
按作者分类的图表
ls_of_hf = HF_buf_gdf.fctype.unique()
print('\nThis administrative area has {} different types of hospitals:\n'.format(len(ls_of_hf)))
print(*ls_of_hf, sep = '\n')**This administrative area has 2 different types of hospitals:**
Centro de Saude Rural II
Centro de Saude Rural I
描述性统计提供了每个卫生机构(潜在)服务人数的概念。基于原始数据的属性,也可以检索其他特征(例如,我们在该区域确定的医疗机构的类型)。这些信息可用于帮助将健康诊所分类为不同的“能源使用”组(参见下面的步骤 3)。
第三步。描述卫生设施的类型并预测电力需求
您可以选择以上任何一种方法继续。
HF = HF_hub_gdf # you may change the input gdf here# Initialize a Health Facility Category column
HF['HF_Cat'] = 0
卫生设施的分类
下面介绍的分类过程是基于这样的想法,即卫生设施分为四个主要类别,即:
- 类型 4: 地区/转诊医院(> 145 张床位)
- 类型 3: 乡村医院(约 55 张床位)
- 类型 2: 小型急病门诊(约 14 张床位)
- 类型 1: 农村药房——无住院病人(约 4 张急诊床)
这种分类与文献中的类似方法一致(例如,参见 Franco 等人)。它还被采用并用于HOMER power Health Tool。
在本例中,我们使用三个值(我们在上一步中已经计算过)来帮助对医疗机构进行相应的分类。其中包括:
- “urban_mean” :这是与每个卫生设施相关的所有集群的平均城市状态{城市:1 或农村:0}。值>大于 0.5 表示医疗设施服务于更多的城市居民区,因此更有可能是更高级的类型。
- “pop_sum” :这是与每个医疗机构相关的所有集群中的人口总数(基于上一步中最近的中心或缓冲区分析)。更高的潜在服务人群可能表明更高的类型。
- “elecpop_sum” :这是与每个卫生设施相关的所有集群中通电人口的总和。这在一定程度上表明,附近的电气化状况可能与卫生设施的类型有关。
在缺乏更详细的(如调查)数据的情况下,目前很难对这种方法进行交叉验证。因此,方法的这一部分对用户输入是开放的。其想法是,建模者可以与当地的利益相关者密切合作,以便校准过程或在获得更多信息时添加“预测器”。
**注意!**在我们的示例中,医疗机构确实包含一些属性,例如它们的类型(如 Centro de Saude Rural I 或 II)。如果可能的话,可以使用这一特性(或任何类似的特性)来帮助估计电力需求。然而,在接下来的步骤中,我们仅使用检索到的人口聚类数据统计,因此该方法可复制到其他地区。
# District/Referral hospital with more than 145 beds
HF.loc[(HF['urban_mean'] >= 0.5) &
(HF['pop_sum'] >= 20000) &
(HF['elecpop_sum'] >= 0), 'HF_Cat'] = 4
# Rural hospital - 50 beds
HF.loc[(HF['urban_mean'] <= 0.5) &
(HF['pop_sum'] >= 20000) &
(HF['elecpop_sum'] >= 0), 'HF_Cat'] = 3
# Small impatient clinic - 14 beds
HF.loc[(HF['urban_mean'] <= 0.5) &
(HF['pop_sum'] < 20000) &
(HF['elecpop_sum'] > 0), 'HF_Cat'] = 2
# Rural dispensary - no inpatient - 4 emergency beds
HF.loc[(HF['urban_mean'] <= 0.5) &
(HF['pop_sum'] < 20000) &
(HF['elecpop_sum'] == 0), 'HF_Cat'] = 1
分类的绘图结果
ax = HF['HF_Cat'].value_counts().plot(kind='bar',figsize=[12,7])
ax.yaxis.set_major_locator(MaxNLocator(integer=True))
plt.title("Categorization of Health facilities in the selected admin area")Text(0.5, 1.0, 'Categorization of Health facilities in the selected admin area')
莫桑比克 Mecanhelas 医疗机构的数量(y 轴)和类型(x 轴)——作者图表
根据类别类型分配电力需求
与分类(见上文)类似,考虑到缺乏定量的地面数据,估计每个医疗机构的电力需求并不是一件容易的事情。在本例中,我们使用 HOMER 供电健康工具界面来量化每种类型的健康机构的潜在电力需求(千瓦时/年)。建模者可以选择适当的设备并相应地定制电力目标。
HF.loc[(HF['HF_Cat'] == 1), 'HF_kWh'] = 5.7*365
HF.loc[(HF['HF_Cat'] == 2), 'HF_kWh'] = 13.9*365
HF.loc[(HF['HF_Cat'] == 3), 'HF_kWh'] = 37*365
HF.loc[(HF['HF_Cat'] == 4), 'HF_kWh'] = 361.1*365
基于上述假设,预计 Mecanhelas 医疗机构的电力需求为 ~225,314.5kWh/年。
在地图上打印带有估计需求的医疗机构的位置
# Vizualize result on an interactive map exported as html
#Define limits for map rendering
x_ave = HF["Lon"].mean()
y_ave = HF["Lat"].mean()
# Create the map using folium module
map_dem = folium.Map(location=[y_ave,x_ave], zoom_start=6, control_scale=True)
# Definition of a function that returns different color names based on lcoe result categorization
# Colors are in Hexa-code e.g. #RRGGBB
def colorvalue(x):
if x <= 0.5:
return "#ADFF2F"
elif x >= 1 and x < 5000:
return "#32CD32"
elif x >= 5000 and x < 10000:
return "#228B22"
elif x >= 10000 and x < 15000:
return "#008000"
elif x >= 15000 and x < 20000:
return "#006400"
else:
return "#000000"
# Then we create a marker for each cluster;
# We pass coordinates as attributes to appear on the rendered map
for index, row in HF.iterrows():
el_demand = row["HF_kWh"]
color_code = colorvalue(el_demand)
folium.CircleMarker([row["Lat"], row["Lon"]],
radius=2,
color=color_code,
popup="<b>Name:</b> {}, <br> <br> <b>Type:</b> {}, <br> <br> <b>Demand:</b> {} kWh/year, <br> <br> <b>".format(row["fcname"], row["fctype"], row["HF_kWh"]),
fill = True,
fill_opacity=0).add_to(map_dem)
# We define the limits of the legend and fix its printout format
# We use branca module to create a colormap legend and then add legend to the map
min_dem = HF["HF_kWh"].min()
max_dem = HF["HF_kWh"].max()
min_dem = float("{0:.2f}".format(min_dem))
max_dem = float("{0:.2f}".format(max_dem))
legend = cm.LinearColormap(['#ADFF2F','#32CD32','#228B22','#008000','#006400','#000000'],
index=None, vmin=min_dem, vmax=max_dem)
legend.add_to(map_dem)
expl_text = '#ADFF2F:1, #32CD32:2, #228B22:3, #008000:4, #006400:5'
iframe = folium.IFrame(expl_text, width=700, height=450)
popup = folium.Popup(iframe, max_width=3000)
Text = folium.Marker(location=[x_ave,y_ave], popup=popup,
icon=folium.Icon(icon_color='green'))
map_dem.add_child(Text)
# Create a new directory where the map(s) can be saved
try:
os.makedirs('maps')
except FileExistsError:
pass
map_dem_output = 'maps/map_{}_{}.html'.format("Health_Facilities", "Mecanhelas")
map_dem.save(map_dem_output)# Publish map on datapane for easier rendering in websites
dp.Report(dp.Plot(map_dem)).publish(name='HF_elec_demand_Mecanhelas', visibility='PUBLIC')# Add the link that leads to the final map output
display(Markdown('<a href="{}" target="_blank">Click here to render the map of electrification of health facilities </a>'.format(map_dem_output)))
莫桑比克 Mecanhelas 卫生设施的位置和预计电力需求。作者地图—通过数据面板呈现—查看完整报告此处。
第四步。将医疗机构目标电力需求分配回人口集群
每个医疗机构的电力需求被分配给最近的集群。
查找最近的聚类
HF["id"] = HF.apply(calculate_nearest, destination=clusters_centroid, val="id", axis=1)
将结果合并到初始聚类
clusters_gdf = gpd.read_file(clusters_path + "\\" + clusters_name)final_clusters_HF_kWh = HF.merge(clusters_gdf, how="outer", on='id')
第五步。映射结果并导出更新的人口聚类数据集
final_clusters_HF_kWh_gdf = gpd.GeoDataFrame(final_clusters_HF_kWh, geometry='geometry', crs={'init': 'epsg:4326'})# Create the axis first
fig, ax = plt.subplots(figsize=(10, 10))
admin_gdf.plot(ax=ax, edgecolor='brown', alpha=0.2)
final_clusters_HF_kWh_gdf.sort_values('HF_kWh', ascending=True).plot(ax=ax, column='HF_kWh',
legend=True, markersize=3, cmap="viridis",
figsize=(10, 10), alpha=0.5)
ax.set_aspect('equal', 'box')
txt = ax.set_title('Electricity requirements (kWh/year) for HF in Mecanhelas'.format(""))
作者图片
将图层导出为地理包
final_clusters_HF_kWh_gdf.to_file("Mecanhelas_HF_kWh.gpkg", driver="GPKG")
请注意,本例中给出的方法和结果仅是说明性的;仅显示空间分析如何用于支持类似的规划活动。
结束语
这是一种探索性的方法,仅基于现有的开放访问数据集。因此,对于量化撒南地区卫生设施电力需求的尝试,它只能提供一个粗略的“第一步”,特别是在没有太多数据的偏远农村地区。
这种分析当然可以通过以下方式得到改进:
- 利用地理定位卫生设施的更好属性数据;此类数据集可能已经存在于国家机构中,如人口普查局/部门、公共统计局、国家调查和制图机构以及其他部门/部委。
- 与目标地区健康和能源实践的当地利益相关者密切合作,以便更好地校准和/或改进此处介绍的方法。
- 相应地,使用详细的调查数据(如果可用)和机器学习来改进分类和对卫生设施的类型和电力需求的预测。
如果结果令人满意,最终产品(包括卫生设施电力需求的人口集群)可用于地理空间电气化模型,以制定成本最低的投资计划。一个例子是GEP-昂塞特模型,它最近被修改以允许包含电力的生产性使用。
作为参考,您可以查看以下地图,这些地图显示了莫桑比克医疗机构和/或相关人群的最低成本电气化方案。
注意!!下面的结果是只是说明性的。
地图 1 :莫桑比克医疗机构的位置,包括其成本最低的电气化技术(结果以弹出形式提供)。
作者地图—通过数据面板呈现—查看完整报告此处。
地图 2: 与莫桑比克一个或多个医疗机构相关的人口集群的最低成本电气化计划(结果以医疗机构弹出窗口和集群工具提示的形式提供)。
作者地图—通过数据面板呈现—查看完整报告此处。
支持材料的链接
要快速浏览支持这个博客的方法和代码,你可以看看 nbviewer 。
或者你可以在 GitHub 上访问(并贡献)完整版本的代码。
这项工作是支持全球电气化平台开发的多年研究工作的一部分。
感谢阅读!
特别感谢 Benjamin Stewart、Ashish Shrestha、Rhonda Lenai Jordan、Nicolina Erica Maria Lindblad、Babak Khavari、Andreas Sahlberg 和 Mark Howells,他们都支持这项工作。