簡體   English   中英

在python中的Groupby和列表理解頭痛

[英]Groupby and list comprehension headache in python

我從Hadoop教程中得到了這個。 它是一個reducer,它基本上從stdin接收(word,count)對並對它們求和。

def read_mapper_output(file, separator='\t'):
    for line in file:
        yield line.rstrip().split(separator, 1)

def main(separator='\t'):
    data = read_mapper_output(sys.stdin, separator=separator)
    for current_word, group in groupby(data, itemgetter(0)):
        try:
            total_uppercount = sum(int(count) for current_word, count in group)
            print "%s%s%d" % (current_word, separator, total_count)
        except ValueError:
            pass

現在,我希望能夠接受元組(word,count1,count2),但是這個groupbysum(int(count for current_word, count in group)業務對我來說完全難以辨認。如何修改這個塊以便它基本上繼續做它現在做的事情,但是有第二個計數器值?即輸入是(word,count1,count2),輸出是(word,count1,count2)。

編輯1:

from itertools import groupby, izip
from operator import itemgetter
import sys

def read_mapper_output(file, separator='\t'):
    for line in file:
        yield line.rstrip().split(separator, 2)

def main(separator='\t'):
    data = read_mapper_output(sys.stdin, separator=separator)
    for current_word, group in groupby(data, itemgetter(0)):
        try:
            counts_a, counts_b = izip((int(count_a), int(count_b)) for current_word, count_a, count_b in group)
            t1, t2 = sum(counts_a), sum(counts_b)
            print "%s%s%d%s%d" % (current_word, separator, t1, separator, t2)
        except ValueError:
            pass

這是一個Hadoop作業,所以輸出如下:

11/11/23 18:44:21 INFO streaming.StreamJob:  map 100%  reduce 0%
11/11/23 18:44:30 INFO streaming.StreamJob:  map 100%  reduce 17%
11/11/23 18:44:33 INFO streaming.StreamJob:  map 100%  reduce 2%
11/11/23 18:44:42 INFO streaming.StreamJob:  map 100%  reduce 12%
11/11/23 18:44:45 INFO streaming.StreamJob:  map 100%  reduce 0%
11/11/23 18:44:51 INFO streaming.StreamJob:  map 100%  reduce 3%
11/11/23 18:44:54 INFO streaming.StreamJob:  map 100%  reduce 7%
11/11/23 18:44:57 INFO streaming.StreamJob:  map 100%  reduce 0%
11/11/23 18:45:05 INFO streaming.StreamJob:  map 100%  reduce 2%
11/11/23 18:45:06 INFO streaming.StreamJob:  map 100%  reduce 8%
11/11/23 18:45:08 INFO streaming.StreamJob:  map 100%  reduce 7%
11/11/23 18:45:09 INFO streaming.StreamJob:  map 100%  reduce 3%
11/11/23 18:45:12 INFO streaming.StreamJob:  map 100%  reduce 100%
...
11/11/23 18:45:12 ERROR streaming.StreamJob: Job not Successful!

從日志:

java.lang.RuntimeException: PipeMapRed.waitOutputThreads(): subprocess failed with code 1
    at org.apache.hadoop.streaming.PipeMapRed.waitOutputThreads(PipeMapRed.java:311)
    at org.apache.hadoop.streaming.PipeMapRed.mapRedFinished(PipeMapRed.java:545)
    at org.apache.hadoop.streaming.PipeReducer.close(PipeReducer.java:137)
    at org.apache.hadoop.mapred.ReduceTask.runOldReducer(ReduceTask.java:473)
    at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:411)
    at org.apache.hadoop.mapred.Child.main(Child.java:170)

java.lang.RuntimeException: PipeMapRed.waitOutputThreads(): subprocess failed with code 1
    at org.apache.hadoop.streaming.PipeMapRed.waitOutputThreads(PipeMapRed.java:311)
    at org.apache.hadoop.streaming.PipeMapRed.mapRedFinished(PipeMapRed.java:545)
    at org.apache.hadoop.streaming.PipeReducer.close(PipeReducer.java:137)
    at org.apache.hadoop.mapred.ReduceTask.runOldReducer(ReduceTask.java:473)
    at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:411)
    at org.apache.hadoop.mapred.Child.main(Child.java:170)

Shuffle Error: Exceeded MAX_FAILED_UNIQUE_FETCHES; bailing-out.

通過...分組

這是itertools模塊中的groupby函數,在此處記錄 data “按”將itemgetter(0) (來自operator模塊的itemgetter類的實例,在此記錄 )的結果“分組”到每個元素。 它返回成對的(關鍵結果,iterator-over-elements-with-key)。 因此,每次循環時, current_word是一堆data行共有的“字”(index-0,即第一項,由itemgetter提取), groupdata行上的迭代器用那個word 如代碼文檔中所述,文件的每一行都有兩個單詞:實際的“單詞”和計數(用於解釋為數字的文本)

sum(current_word的int(count),group中的count)

意味着正是它說 :對的整數值的總和count ,每個( current_wordcount中找到)對group 如上所述,每個group是來自data一組線。 因此,我們采用以current_word開頭的所有行,將其字符串count數值轉換為整數,然后將它們相加。

我如何修改這個塊,以便它基本上繼續做它現在做的事情,但是有第二個計數器值? 即輸入是(word,count1,count2),輸出是(word,count1,count2)。

那么,您希望每個計數代表什么,以及您希望數據來自何處?

我將采用我認為最簡單的解釋:您將修改數據文件以在每一行上有三個項目,並且您將分別從每列數字中獲取總和。

groupby將是相同的,因為我們仍然以相同的方式對行進行分組,並且我們仍然根據“單詞”對它們進行分組。

sum部分需要計算兩個值:第一列數字的總和和第二列數字的總和。

當我們遍歷group ,我們將獲得三個值的集合,因此我們想要將它們解壓縮為三個值:例如current_word, group_a, group_b 對於其中的每一個,我們希望將整數轉換應用於每行上的兩個數字。 這給了我們一系列數字序列; 如果我們想要添加所有第一個數字和所有第二個數字,那么我們應該制作一對數字序列。 為此,我們可以使用另一個名為izip itertools函數。 然后我們可以將它們分別相加,將它們再次打包成兩個獨立的數字序列變量,並對它們求和。

從而:

counts_a, counts_b = izip(
    (int(count_a), int(count_b)) for current_word, count_a, count_b in group
)
total_a, total_b = sum(counts_a), sum(counts_b)

或者我們可以通過再次執行相同的操作(x中的y代表y)來制作一對計數:

totals = (
    sum(counts)
    for counts in izip(
        (int(count_a), int(count_b)) for current_word, count_a, count_b in group
    )
)

雖然在打印語句中使用該結果會有些棘手:)

from collections import defaultdict

def main(separator='\t'):
    data = read_mapper_output(sys.stdin, separator=separator)
    counts = defaultdict(lambda: [0, 0])
    for word, (count1, count2) in data:
        values = counts[word]
        values[0] += count1
        values[1] += count2

    for word, (count1, count2) in counts.iteritems():
        print('{0}\t{1}\t{2}'.format(word, count1, count2))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM