Если бы oop MapReduce не выдавал желаемый результат - PullRequest
2 голосов
/ 22 апреля 2020

У меня есть один большой файл, который содержит патентную информацию. Заголовок следующий: «ПАТЕНТ», «ГОД», «GDATE», «APPYEAR», «СТРАНА», «POSTATE», «ASSIGNEE», «ASSCODE», «CLAIMS».

Я хочу рассчитать среднюю сумму претензий на патент по годам, где ключом является год, а значением - средняя сумма. Тем не менее, выход редуктора показывает, что мое среднее количество постоянно равно 1,0. Где моя программа go не так?

Основной класс

 public static void main(String [] args) throws Exception{
    int res = ToolRunner.run(new Configuration(), new AvgClaimsByYear(), args);
    System.exit(res);
}

Класс водителя

    Configuration config = this.getConf();  
    Job job = Job.getInstance(config, "average claims per year"); 
    job.setJarByClass(AvgClaimsByYear.class);
    job.setMapperClass(TheMapper.class);
    job.setPartitionerClass(ThePartitioner.class);
    job.setNumReduceTasks(4);
    job.setReducerClass(TheReducer.class);
    job.setOutputKeyClass(IntWritable.class);
    job.setOutputValueClass(IntWritable.class);

    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    return job.waitForCompletion(true) ? 0 : 1;

Класс Mapper

    public static class TheMapper extends Mapper<LongWritable, Text, IntWritable, IntWritable> {
      private IntWritable yearAsKeyOut = new IntWritable();
      private IntWritable claimsAsValueOut = new IntWritable(1);
      @Override
      public void map(LongWritable keyIn, Text valueIn, Context context) throws IOException,InterruptedException {
        String line = valueIn.toString();
        if(line.contains("PATENT")) {
            return; //skip header
        }
        else {
            String [] patentData = line.split(","); 
            yearAsKeyOut.set(Integer.parseInt(patentData[1])); 
            if (patentData[8].length() > 0) {
                claimsAsValueOut.set(Integer.parseInt(patentData[8]));
            }
        }
        context.write(yearAsKeyOut, claimsAsValueOut);
    }   
}

Класс Partitioner

    public static class ThePartitioner extends Partitioner<IntWritable, IntWritable> {
      public int getPartition(IntWritable keyIn, IntWritable valueIn, int totalNumPartition) {
        int theYear = keyIn.get();

        if (theYear <= 1970) {
            return 0;
        }
        else if(theYear > 1970 && theYear <= 1979) {
            return 1;
        }
        else if(theYear > 1979 && theYear <=1989) {
            return 2;
        }
        else{
            return 3;
        }
    }

}

Класс редуктора

 public static class TheReducer extends Reducer<IntWritable,IntWritable,IntWritable,FloatWritable> {
    @Override
    public void reduce(IntWritable yearKey, Iterable<IntWritable> values, Context context) throws IOException,InterruptedException {
        int totalClaimsThatYear = 0;
        int totalPatentCountThatYear = 0;
        FloatWritable avgClaim = new FloatWritable();

        for(IntWritable value : values) {

            totalClaimsThatYear += value.get();
            totalPatentCountThatYear += 1;      
        }
        avgClaim.set(calculateAvgClaimPerPatent (totalPatentCountThatYear, totalClaimsThatYear)); 
        context.write(yearKey, avgClaim);
    }

    public float calculateAvgClaimPerPatent (int totalPatentCount, int totalClaims) {
        return (float)totalClaims/totalPatentCount;
    }
}

Вход

  3070801,1963,1096,,"BE","",,1,,269,6,69,,1,,0,,,,,,,
  3070802,1963,1096,,"US","TX",,1,,2,6,63,,0,,,,,,,,,
  3070803,1963,1096,,"US","IL",,1,,2,6,63,,9,,0.3704,,,,,,,
  3070804,1963,1096,,"US","OH",,1,,2,6,63,,3,,0.6667,,,,,,,
  3070805,1963,1096,,"US","CA",,1,,2,6,63,,1,,0,,,,,,,

Выход

1963 1.0 
1964 1.0
1965 1.0 
1966 1.0 
1967 1.0 
1968 1.0 
1969 1.0 
1970 1.0

1 Ответ

1 голос
/ 23 апреля 2020

В Функция CalculateAvgClaimPerPatent () ваше выражение выполняет целочисленное деление перед преобразованием в число с плавающей точкой. Конвертируйте два целых числа в число с плавающей точкой перед делением.

- edit -

Кроме того, при повторном просмотре кода среднее записанное число - это действительно среднее число заявок на запись, сгруппированных по 4 интервалам, определенным вашим разделителем. Другими словами, число заявок на один патент в 1972 году усредняется с количеством заявок на другой патент в 1975 году. Это не соответствует описанию вашей проблемы.

...