首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Apache管道中Python的CombineFn

问Apache管道中Python的CombineFn
EN

Stack Overflow用户
提问于 2022-11-21 16:24:37
回答 1查看 34关注 0票数 0

我一直在用Python中的Apache进行实验,以编写数据处理管道。

我的数据模拟了Google主题中的IoT传感器数据,该主题如下所示:

代码语言:javascript
复制
{"id": 1, "temperature": 12.34}
{"id": 2, "temperature": 76.54}

有从0到99的ID。将JSON读入Python并不是问题。

我创建了一个自定义CombineFn来由CombinePerKey进行处理。我希望我的累加器的输出将是计算,按PCollection中字典中相应的PCollection字段分组。

但是,当调用add_input方法时,它只接收字符串 temperature,而不是整个字典。我也没有找到任何引用来告诉CombinePerKey哪个键(在我的例子中是id字段),我希望它对数据进行分组。

也许我也误解了CombinePerKey和CombineFn的概念。我希望能在这方面提供任何帮助或暗示。也许有人有一个用基于ID的分组处理JSON批的示例?我必须把字典翻译成别的东西吗?

EN

回答 1

Stack Overflow用户

发布于 2022-11-25 09:41:07

您需要调整您的CombineFn或(我建议的)保持CombineFn尽可能通用,并相应地映射CombinePerKey的输入。我在下面使用这个公有梁的例子做了两个案例的简短例子。

特异CombineFn

代码语言:javascript
复制
import apache_beam as beam

class SpecificAverageFn(beam.CombineFn):
  def create_accumulator(self):
    sum = 0.0
    count = 0
    accumulator = sum, count
    return accumulator

  def add_input(self, accumulator, input):
    sum, count = accumulator
    extracted_input = input['temperature'] # <- this is a dict, you need to create custom code here
    return sum + extracted_input, count + 1

  def merge_accumulators(self, accumulators):
    # accumulators = [(sum1, count1), (sum2, count2), (sum3, count3), ...]
    sums, counts = zip(*accumulators)
    # sums = [sum1, sum2, sum3, ...]
    # counts = [count1, count2, count3, ...]
    return sum(sums), sum(counts)

  def extract_output(self, accumulator):
    sum, count = accumulator
    if count == 0:
      return float('NaN')
    return sum / count

with beam.Pipeline() as pipeline:
  (
    pipeline
    | "mock input" >> beam.Create([
     {'id': 1, 'temperature': 2},
     {'id': 2, 'temperature': 3},
     {'id': 2, 'temperature': 2}
    ])
    | "add key" >> beam.Map(lambda x: (x['id'], x))
    | beam.CombinePerKey(SpecificAverageFn())
    | beam.Map(print)
  )

通用Combinefn

代码语言:javascript
复制
import apache_beam as beam

class GenericAverageFn(beam.CombineFn):
  # everything as SpecificAverageFn, except add_input:
  def add_input(self, accumulator, input):
    sum, count = accumulator
    return sum + input, count + 1


with beam.Pipeline() as pipeline:
  iot_data = (
    pipeline
    | "mock input" >> beam.Create([
     {'id': 1, 'temperature': 2},
     {'id': 2, 'temperature': 3},
     {'id': 2, 'temperature': 2}
    ])
    | "add key" >> beam.Map(lambda x: (x['id'], x))
  )

  # repeat below for other values
  (
    iot_data
    | "extract temp" >> beam.Map(lambda x: (x[0], x[1]['temperature']) 
    | beam.CombinePerKey(AverageFn())
    | beam.Map(print)
  )

两种方法都回来了

代码语言:javascript
复制
(1, 2.0)
(2, 2.5)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74521933

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档