我开始使用python的mrjob将一些长时间运行的python程序转换为MapReduce hadoop作业。我已经得到了简单的单词计数示例,我从概念上理解了“文本分类”示例。
但是,我在解决我需要采取的步骤以解决问题时遇到了一些麻烦。
我有多个文件(大约6000个),每个文件各有2到800行。在这种情况下,每一行都是一个简单的以空格分隔的“信号”。我需要比较每个文件中每一行与所有文件中的每一行(包括其自身)之间的相关性。然后根据相关系数,我将输出结果。
一个文件的示例:
1 2 3 4 2 3 1 2 3 4 1 2
2 2 3 1 3 3 1 2 3 1 4 1
2 3 4 5 3 2 1 3 4 5 2 1
...
我需要让这个文件的每个LINE与每个其他文件中的每个其他行配对......或者我可以将所有文件连接成一个文件,如果这样可以更容易,但我仍然需要成对迭代。
我了解如何进行计算以及如何使用最终的reduce步骤来聚合和过滤结果。我遇到的困难是如何在不读取单个setp中的所有文件的情况下yield
所有成对项目到连续步骤?我想我可以提前准备一个使用itertools.product
的输入文件,但这个文件会非常大。
答案 0 :(得分:1)
好吧,既然没有人提出答案,我会发布我目前的工作情况,以防其他任何人需要它。我不确定这是多么'有些'或有效,但到目前为止它已经有效了。
我将文件名作为文件每行的第一项,然后是\t
,后跟其余数据。对于这个例子,我只是在每一行上使用一个数字然后对它们求平均值,这只是一个非常简单的例子。
然后我在mrjob
中进行了以下map-reduce步骤。
class MRAvgPairwiseLines(MRJob):
def input_mapper(self, _, value):
"""Takes each input line and converts it to (fnum, num) and a key of 'ALL'"""
fnum, val = value.split('\t')
yield 'ALL', (fnum, val)
def input_reducer(self, key, values):
for (fnum1, val1), (fnum2, val2) in product(values, repeat = 2):
yield fnum1, (fnum1, fnum2, val1, val2)
def do_avg(self, key, value):
fnum1, fnum2, val1, val2 = value
res = (float(val1)+float(val2))/float(2)
yield key, (fnum2, res)
def get_max_avg(self, key, values):
max_fnum, max_avg = max(values, key = lambda x: x[1])
yield key, (max_fnum, max_avg)
def steps(self):
return [self.mr(mapper=self.input_mapper, reducer=self.input_reducer),
self.mr(mapper=self.do_avg, reducer=self.get_max_avg)]
这样,input_mapper
函数的所有输出都被分组到相同的input_reducer
,然后是yield
个连续的对。然后它们会传递到适当的位置,最终返回最大的平均值(实际上是所有其他文件中最大的项目)。
希望能有所帮助。