我正在尝试使用MapReduce构建算法属性值频率的第一阶段(频率计算),其中计算每列中每个属性的频率。我在我的问题中提到了所需的键值对。所以即使算法对你不熟悉也希望它不会有问题。我有一个数据集如下:
ID1,2,1,4
ID2,2,2,2
ID3,5,3,1
每行都有一个ID,后跟三个属性的值。在map阶段,我需要生成[attributeNo attributeValue]作为键,[ID]作为值。我已正确设计并执行了地图阶段。我通过直接在reduce阶段打印生成的键值对来测试我的map阶段,而不进行任何处理。我发现键值对已经正确生成,即,还原阶段从映射阶段获得正确的输入。我的地图类是:
public static class Map extends MapReduceBase implements Mapper<LongWritable, Text, Text, Text>
{
public void map(LongWritable key, Text value, OutputCollector<Text,Text> output, Reporter reporter) throws IOException
{
String[] rows = value.toString().split("\r?\n");
for(int i=0;i<rows.length;i++)
{
String[] cols = rows[i].toString().split(",");
String v=cols[0];
for(int j=1;j<cols.length;j++)
{
String k =j+","+cols[j];
output.collect(new Text(k),new Text(v));
}
}
}
}
更正地图阶段生成的键值对:
2,3 ID3
3,2 ID2
1,5 ID3
1,2 ID1,ID2
2,1 ID1
3,4 ID1
2,2 ID2
3,1 ID3
现在,这些键值映射对作为输入提供给reduce。我的reduce阶段需要生成[ID,attributeNo]作为键,[attributeValue,frequency]作为值,其中frequency是与每个键对应的ID的数量。我的reduce类是:
public static class Reduce extends MapReduceBase implements Reducer<Text, Text, Text, Text>
{
public void reduce(Text key, Iterator<Text> values, OutputCollector<Text, Text>output, Reporter reporter) throws IOException
{
/** map phase check
while (values.hasNext())
{
String s = (values.next()).toString();
output.collect(key,new Text(s));
}**/
// Frequency Calculation
int count =0;
String[] attr = key.toString().split(",");
List<String> list = new ArrayList<String>();
while(values.hasNext())
{
list.add((values.next()).toString());
count++;
}
String v=attr[1]+","+count;
for(String s:list)
{
String k=s+","+attr[0];
output.collect(new Text(k),new Text(v));
}
}
我得到了一个输出:
2,1,ID3 3,1
3,1,ID3 2,1
5,1,ID3 1,1
2,2,ID1 1,1
2,2,ID2 1,1
1,1,ID1 2,1
4,1,ID1 3,1
2,1,ID1 2,1
1,1,ID3 3,1
所需的输出是:
ID1,1 2,2
ID1,2 1,1
ID1,3 4,1
ID2,1 2,1
ID2,2 2,1
ID2,3 2,1
ID3,1 4,1
ID3,2 2,1
ID3,3 1,1
请告诉我在减少阶段我的代码或逻辑有什么问题?甚至在reduce阶段生成的密钥格式也不对。请帮我纠正输出到减少阶段。