如何基于Apache Beam中的单个键将聚合函数应用于多个列?

时间:2019-03-05 08:44:15

标签: google-cloud-dataflow apache-beam

我正在使用Apache Beam python SDK并正在处理GCP数据流。如何基于单个键将聚合函数应用于多个列? 例如,一个10列的数据集,我的数据看起来像 User_id,product_id,year,quantity,price,... 101,1,2018,10,15,... 101,2,2019,1,10,... 102,1,2019,2,16,...

对于每个用户ID,我该如何计算他已购买的不同产品的数量,最大数量,最小价格等。

我看到了单词计数等示例,您可以在这些示例中将sum应用于(key,value)对中的值。如果我想对不同的列(例如sum / mean / count等)进行不同的转换怎么办?

1 个答案:

答案 0 :(得分:0)

Beam使用PCollection,这是一个并行集合,在Python中,您可以将其视为(通常是)元素列表(通常为元组或dict)。

在您的情况下,它可能是“行”的列表,所以您会

  1. 提取行的键。如果那是User_id,则映射这样的lambda 例如

x -> (x[0], x)

请注意,x用作k,v对中的值,并且它仍然包含键,但这很好,如果您希望删除它并重新包装没有它的值元组。即返回的该元组将类似于Tuple [str,Tuple [int,int,int,float,float]]的类型,并假定它们是User_id,product_id,year,quantity,price 的正确类型

  1. 应用窗口
  2. 按键分组(在按键分组之前定义窗口非常重要,并且知道该窗口仅在按键分组时才生效)

  3. 使用某些方法提取您感兴趣的列(元组中的值),应用聚合,并对下游的任何内容重新打包。

在单个元组值上使用聚合函数似乎很奇怪,但是聚合将被映射/应用于窗口中的整个键组。

此基本示例可以轻松扩展https://github.com/apache/beam/blob/ee96f66e14866f9642e9c67bf2ef231be7e7d55b/sdks/python/apache_beam/examples/wordcount.py#L99

如果您需要做一些简单的事情,只需映射一个函数,如果您需要的不只是简单的事情,则可以创建DoFn。这很简单。

例如!警告,未经测试的代码在传输中!

def multi_agg(element):
    (key, row ) = element
    return (key, (max(row[3]), min(row[4])))

在这种情况下,我将上一步中的user_id作为键,将数量的最大值和价格的最小值作为键,然后将其打包回k,v对的元组中。 k,v对是一个元组,它是下游PCollection的元素。您需要k,v对的主要原因是因为诸如GroupByKey之类的东西隐式地使用第一个值作为分组的键。整个元素被隐式用作映射到函数的值。在查看Apache Beam示例时,这两件事并不明显。

您可以重新打包成k,v对以进行进一步的下游处理,也可以放入准备写入例如bigquery或bigtable或云存储桶中的文件。无论如何都要使用类型提示是一个好主意。