PowerQuery

我要统计各媒体的投放数据,收到同事发来的表后我就头大了……

2019-04-03  本文已影响9人  PowerQuery

我要统计各媒体的投放数据,就找管后台的小朋友要一下数据,然后,他给我发来了这个表:

我要统计各媒体的投放数据,收到同事发来的表后我就头大了……

作为懒人,最简单的办法是分别剪切空列分隔开的后面两个数据块,然后粘贴到第一个数据块下,再用筛选大法剔除无关紧要的数据,再用数据透视表拉出各媒体的汇总数据即可。

但作为懒人中的懒人+处女座,我拿到这个表就想以后我要是天天遇到这种表、而且里边有几十个几百个这样的,我怎么办?

答案还是要祭出微软出品的数据处理神器PowerQuery。

分析表结构

对数据源进行分析后发现,要感谢同事小朋友用两个空列把数据分成了三个数据块。要是没有这两个用来分隔的空列,想哭都哭不出了。

所以,有了这两个分隔列把数据分成三块之后,我们就可以在PowerQuery中,借助剪切粘贴一样的思路,将第二、三个数据块追加到第一个数据块之后,然后再剔除不需要的行,即可。

引入数据源

第一步是引入数据源:

= Excel.Workbook(File.Contents("C:UserswanghtDesktop统计.xlsx"), null, true)

= 源{[Item="Sheet0",Kind="Sheet"]}[Data]

得到的结果是一个超级宽的表:

我要统计各媒体的投放数据,收到同事发来的表后我就头大了……

得到三个数据块

这是最关键的一步。这时我发现用作分隔符的空列影响了后续操作,所以需要将其剔除。一种办法是直接过滤column5和column10。但这类似于硬编码,所以我选择了另外一种方式。

我利用最后得到的数据列名称不包括“Column”这个单词的方式来动态过滤分隔列,即剔除第一行,然后把原来的第二行作为标题:

= Table.Skip(Sheet0_Sheet,1)

= Table.PromoteHeaders(删除的顶端行, [PromoteAllScalars=true])

然后在此基础上剔除用作分隔符的空列:

= Table.SelectColumns(提升的标题,List.Select(Table.ColumnNames(提升的标题),each Text.Start(_,6)<>"Column"))

接下来,就可以直接用Table.SelectColumns()函数来分别获得三个数据块,然后将其合并:

= Table.Combine({Table.DemoteHeaders(Table.SelectColumns(自定义1,List.Range(Table.ColumnNames(自定义1),0,4))),Table.DemoteHeaders(Table.SelectColumns(自定义1,List.Range(Table.ColumnNames(自定义1),4,4))),Table.DemoteHeaders(Table.SelectColumns(自定义1,List.Range(Table.ColumnNames(自定义1),8,4)))})

注意代码中我用了Table.DemoteHeaders()函数,如果不使用这个函数将标题降级,那么我们合并后的表格还是12列,并且三个数据块彼此是错位的。因为每个数据块的列名称都不一样。通过将每个数据块的标题降级后,就让三个数据块的列标题都变成了Column1,Column2,Column3和Column4这样的。

由于这三个数据块的结构一模一样,只是List.Range()函数的第二个参数不一样,所以我猜测可以用List.Generate()函数一步生成三个数据块,可惜我还没掌握这个函数,所以这里又不得不采取了硬编码的方式,是个遗憾。

得到的结果如下:

我要统计各媒体的投放数据,收到同事发来的表后我就头大了……

提升合并后的表格标题并剔除空行

通过前面的步骤,我们将需要的数据制作成了一个窄表格,该表格的列数就等于最后我们需要获取的数据的列数,列标题和我们要获取的数据的列标题一样。

接下来筛选掉空行。通过观察可以发现,直接在“展现”、“点击”或“点击率”来筛选空行效率是最高的。这样不仅剔除了空行,还剔除了我们不需要的客户名称。

= Table.PromoteHeaders(自定义2, [PromoteAllScalars=true])

= Table.SelectRows(提升的标题1, each ([展现] <> null))

得到的结果是这样:

我要统计各媒体的投放数据,收到同事发来的表后我就头大了……

剔除多余的标题行

上一步完成后,我们发现还多了标题行。去除多余的标题行的最佳办法并不是在第一列筛选“媒体名称”,因为这其实还是硬编码方法。最佳办法是更改“展现”、“点击”或“点击率”列的格式,将其变为整数或小数格式,这样一来,包含文本的行会报错,然后删除错误行即可:

= Table.TransformColumnTypes(筛选的行,{{"点击", Int64.Type}})

= Table.RemoveRowsWithErrors(更改的类型4, {"点击"})

我要统计各媒体的投放数据,收到同事发来的表后我就头大了……

最后的处理

删除不需要的行,根据需要进行其他处理,比如我删除了点击率,根据媒体进行分组,分别对展现和点击求和:

= Table.RemoveColumns(删除的错误,{"点击率"})

= Table.Group(删除的列, {"媒体名称"}, {{"展现", each List.Sum([展现]), type number}, {"点击", each List.Sum([点击]), type number}})

我要统计各媒体的投放数据,收到同事发来的表后我就头大了……

反思

这个例子,如果分布在一张sheet中的数据是以表格方式存在:

我要统计各媒体的投放数据,收到同事发来的表后我就头大了……

处理起来就没有难度:将原始文件放到单独的文件夹中,然后用PowerQuery引入一个来自于文件夹的源,即可处理(不推荐引入来自文件的源,有兴趣的可以试试看)。

如果原始文件没有那两个空列把数据分成三块,处理起来也非常麻烦,估计要用vba来判定每一个数据块的边界。

最后,寻找三个数据块时,由于我对List.Generate()函数不熟,因此还是采取了硬编码的方式,是一个比较大的遗憾。

结语

这个例子因为是纯PowerQuery操作,比较偏门,估计有不少人不明觉厉。但如果您觉得这个帖子对您有用,还是欢迎转发、收藏、评论或关注。如果您能给出Table.Gernerate()函数实现三个数据块的自动获取,我将不胜感激。

上一篇下一篇

猜你喜欢

热点阅读