Mapreduce Nombre de Mots Hadoop Mot La Plus Haute Fréquence


Donc du site de tutoriel Hadoop(http://hadoop.apache.org/docs/current/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html#Source_Code) sur la façon d'implémenter le nombre de mots à l'aide d'une approche de réduction de carte, je comprends comment cela fonctionne et que la sortie sera tous les mots avec une fréquence.

Ce que je veux faire, c'est que la sortie soit le mot de fréquence la plus élevée du fichier d'entrée que j'ai.

Example: Jim Jim Jim Jim Tom Dane

Je veux la sortie juste pour être

Jim 4

La sortie actuelle du nombre de mots est chaque mot et sa fréquence. Quelqu'un a-t-il modifié le nombre de mots pour qu'il imprime simplement le mot de fréquence la plus élevée et sa fréquence?

Quelqu'un a-t-il des conseils sur la façon d'y parvenir?

Comment pourrais-je écrire un autre MapReducer qui trouvera le mot de fréquence la plus élevée à partir de la sortie de WordCount?

Ou existe-t-il un autre moyen?

Toute aide serait très appréciée.

Merci vous!

Nombre de mots.jave:

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordCount {

  public static class TokenizerMapper
       extends Mapper<Object, Text, Text, IntWritable>{

    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();

    public void map(Object key, Text value, Context context
                    ) throws IOException, InterruptedException {
      StringTokenizer itr = new StringTokenizer(value.toString());
      while (itr.hasMoreTokens()) {
        word.set(itr.nextToken());
        context.write(word, one);
      }
    }
  }

  public static class IntSumReducer
       extends Reducer<Text,IntWritable,Text,IntWritable> {
    private IntWritable result = new IntWritable();

    public void reduce(Text key, Iterable<IntWritable> values,
                       Context context
                       ) throws IOException, InterruptedException {
      int sum = 0;
      for (IntWritable val : values) {
        sum += val.get();
      }
      result.set(sum);
      context.write(key, result);
    }
  }

  public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();
    Job job = Job.getInstance(conf, "word count");
    job.setJarByClass(WordCount.class);
    job.setMapperClass(TokenizerMapper.class);
    job.setCombinerClass(IntSumReducer.class);
    job.setReducerClass(IntSumReducer.class);
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);
    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    System.exit(job.waitForCompletion(true) ? 0 : 1);
  }
}
Author: mike_tech123, 2015-03-06

3 answers

Une solution possible est de définir le nombre de réducteurs à "1". Ensuite, faites en sorte qu'un réducteur se souvienne du mot avec la fréquence la plus élevée et écrivez-le dans la sortie du nettoyage. Comme ceci:

public static class IntSumReducer
       extends Reducer<Text,IntWritable,Text,IntWritable> {

    private Text tmpWord = new Text("");
    private int tmpFrequency = 0;

    @Override
    public void reduce(Text key, Iterable<IntWritable> values,
                       Context context
                       ) throws IOException, InterruptedException {
      int sum = 0;
      for (IntWritable val : values) {
        sum += val.get();
      }
      if(sum > tmpFrequency) {
         tmpFrequency = sum;
         tmpWord = key;
      }
    }

    @Override
    public void cleanup(Context context) {
    // write the word with the highest frequency
        context.write(tmpWord, new IntWritable(tmpFrequency));
    }
}
 2
Author: Matthias Kricke, 2015-09-23 08:26:57

Vous ne pourrez pas le faire en une seule étape, la phase de réduction est effectuée indépendamment pour chaque clé (la synchronisation n'est pas possible) . La solution consisterait à exécuter un nouveau travail MapReduce qui agrégera la sortie de votre travail WordCount d'origine en une seule clé et sélectionnera simplement max. GL!

 0
Author: www, 2015-03-06 08:14:16

Si vous forcez une exécution MapReduce avec une seule tâche de réduction, dans le code, vous implémentez une recherche de fréquence majeure de toutes les clés dans une boucle.

A la fin de cela, la sortie de la boucle contient la clé avec la fréquence majeure. Cette paire que vous pouvez envoyer à la sortie finale (La phrase context.write() doit être exécutée une fois à la fin).

 0
Author: Tuxman, 2015-03-06 17:44:00