如何根据键类型使Reducer发出

时间:2015-12-14 19:28:49

标签: python hadoop mapreduce reduce

作为this问题的后续问题,我有一个Mapper,它经历了大量数据并将ID号作为键发出,值为1.每个键都有两个部分,用管道分隔符分隔,例如:

映射器发出:
a | abc 1
b | efg 1
a | cba 1
a | abc 1
b | dhh 1
b | dhh 1

我想要做的是让Reducer解析密钥,对于每个类型为'a'的密钥,即'a | abc',我希望Reducer只发出重复项,但是对于其他每种类型(例如输入'b',即'b | abc'),我希望Reducer发出一切,即使该值只有1。

所以上述数据会产生:
a | abc 2
b | efg 1
b | dhh 2

在这种情况下,'a | cba 1'不会被发出,因为它是'a'类型的键,并且它没有重复。下面是我尝试的代码,它几乎按预期工作,除了我得到92个额外的发出,其中键是'a'类型,计数是1.注意:92是根据我的MapReduce日志减少任务的数量

由于我只想要密钥类型'a'的重复项,我如何修复Reducer以便我不会获得值为1的那些额外92个密钥类型'a'的发出?

import sys
import codecs

sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
inData = codecs.getreader('utf-8')(sys.stdin)

(last_key, tot_cnt) = (None, 0)
for line in inData:
    (key, val) = line.strip().split("\t")
    if last_key != key:
        k = key.split('|')
        v_id = k[0]
        if v_id == 'a':
            if tot_cnt > 1:
                sys.stdout.write("%s\t%s\n" % (last_key,tot_cnt))
        else:
            sys.stdout.write("%s\t%s\n" % (last_key,tot_cnt))

        (last_key, tot_cnt) = (key, int(val))
    else:
        (last_key, tot_cnt) = (key, tot_cnt + int(val))
if last_key:
    if v_id == 'a':
        if tot_cnt > 1:
            sys.stdout.write("%s\t%s\n" % (last_key, tot_cnt))
    else:
        sys.stdout.write("%s\t%s\n" % (last_key, tot_cnt))

1 个答案:

答案 0 :(得分:1)

以下是您的代码中的错误:

  1. 在全局级别声明v_id,以便随处可见。

    更改此行:

    (last_key, tot_cnt) = (None, 0)
    

    要:

    (last_key, tot_cnt, v_id) = (None, 0, None)
    
  2. 分拆后应位于last_key而非当前key。当前键是“b | dhh”而最后一个键是“a | abc”时,你应该得到v_id“a | abc”。

    更改此代码:

    if last_key != key:
        k = key.split('|')
        v_id = k[0]
    if v_id == 'a':
        if tot_cnt > 1:
            sys.stdout.write("%s\t%s\n" % (last_key,tot_cnt))
    else:
        sys.stdout.write("%s\t%s\n" % (last_key,tot_cnt))
    

    致:

    if last_key != key:
        if last_key != None:
            k = last_key.split('|')
            v_id = k[0]
    
            if v_id == 'a':
                if tot_cnt > 1:
                    sys.stdout.write("%s\t%s\n" % (last_key,tot_cnt))
            else:
                sys.stdout.write("%s\t%s\n" % (last_key,tot_cnt))
    
  3. 因此,修改后的reducer代码如下所示:

    import sys
    import codecs
    
    sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
    inData = codecs.getreader('utf-8')(sys.stdin)
    
    (last_key, tot_cnt, v_id) = (None, 0, None)
    
    for line in inData:
        (key, val) = line.strip().split("\t")
        if last_key != key:
            if last_key != None:
                k = last_key.split('|')
                v_id = k[0]
    
                if v_id == 'a':
                    if tot_cnt > 1:
                        sys.stdout.write("%s\t%s\n" % (last_key,tot_cnt))
                else:
                    sys.stdout.write("%s\t%s\n" % (last_key,tot_cnt))
    
            (last_key, tot_cnt) = (key, int(val))
        else:
            (last_key, tot_cnt) = (key, tot_cnt + int(val))
    
    if last_key:
        if v_id == 'a':
            if tot_cnt > 1:
                sys.stdout.write("%s\t%s\n" % (last_key, tot_cnt)) 
        else:
            sys.stdout.write("%s\t%s\n" % (last_key, tot_cnt))
    

    当我跑步时,我得到了输出:

    a|abc   2
    b|dhh   2
    b|efg   1
    

    注意:我不是Python专家。我觉得,你可以优化这段代码。因此,请检查脚本中是否存在任何极端情况和冗余检查。