Hadoop Mapreduce过滤器数据

Hadoop Mapreduce过滤器数据,hadoop,mapreduce,Hadoop,Mapreduce,假设我在CSV文件中有如下数据集: Id, Patient cycle no, counseling 2345, 1, No 1234, 22, Yes 4567, 1, No 2378, 10, No 我想使用map reduce筛选出咨询为“否”的记录,这些记录的患者周期=1 如何实现这一点?有两种方法可以实现对记录的过滤: 仅使用Map功能,检查患者周期no是否等于1,咨询是否等于Yes,而无需执行任何Reduce功能,以及 使用Map函数,将患者周期号作为键,将咨询的Id作为复合值,

假设我在CSV文件中有如下数据集:

Id, Patient cycle no, counseling
2345, 1, No
1234, 22, Yes
4567, 1, No
2378, 10, No
我想使用map reduce筛选出咨询为“否”的记录,这些记录的患者周期=1


如何实现这一点?

有两种方法可以实现对记录的过滤:

  • 仅使用
    Map
    功能,检查
    患者周期no
    是否等于
    1
    咨询
    是否等于
    Yes
    ,而无需执行任何
    Reduce
    功能,以及
  • 使用
    Map
    函数,将
    患者周期号
    作为键,将
    咨询
    Id
    作为复合值,以便按照周期号对数据进行分组,这样我们就可以在
    咨询
    等于
    时检查每个(复合)值
由于您可能刚刚开始学习MapReduce范例,我将遵循这两种方法中的第二种方法,使
Map
Reduce
函数更清晰(即使这个答案的逻辑在可伸缩性和执行时间的总体速度方面似乎有点低效,这取决于输入数据的大小和形式)

第一步是实现
Map
功能,这里要做的就是读取每个记录并重新排列其中的列,以将患者的周期作为键。为了保护我们的手不被“弄脏”对于复合值,
Id
Id
字段将放在值字段中,以
字符作为分隔符分隔。因此映射器的输出键值对将遵循以下模式:

对于
Reduce
功能,所有键值对都按键分组,具有相同键的数据都放在同一个reducer中进行处理。这基本上意味着对于每个患者周期,所有
(Id,咨询)
值存储在
Reduce
函数的同一个实例中,我们可以通过一个简单的
for
循环逐个访问它们。这就是我们:

  • \uuu
    分隔符拆分复合值
  • 检查我们当前是否在减速器上,将
    1
    患者的数据分组为周期数,如果是,检查
    咨询
    是否等于
    以将其存储到输出
  • 存储具有不同循环数的所有其他记录
  • 但是,当我们存储记录时,最好让它们与输入数据的形式相似,因此在这里,我们可以通过将患者
    Id
    作为键,将
    患者周期no
    咨询
    作为复合值(此处仅使用空格字符的分隔符
    )再次重新排列数据

    所有这些都是使用下面的源代码(此处的输入数据放在名为
    /patients
    的文件夹中)完成的:

    输出如下所示:

    我不建议在2021年使用MapReduce;您看过Spark吗?如果您自己尝试实施一个解决方案,然后在这里发布任何问题,您会学到更多。
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.Path;
    import org.apache.hadoop.io.Text;
    import org.apache.hadoop.io.LongWritable;
    import org.apache.hadoop.io.IntWritable;
    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.TextInputFormat;
    import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
    import org.apache.hadoop.util.GenericOptionsParser;
    import org.apache.hadoop.fs.FileSystem;
    import org.apache.hadoop.fs.FileStatus;
    import org.apache.hadoop.fs.FSDataOutputStream;
    import org.apache.hadoop.mapreduce.lib.input.FileSplit;
    
    import java.io.*;
    import java.io.IOException;
    import java.util.*;
    import java.nio.charset.StandardCharsets;
    
    public class PatientFilter 
    {
        /* input:  <byte_offset, line_of_dataset>
         * output: <patient_cycle, (ID, counceling)>
         */
        public static class Map extends Mapper<LongWritable, Text, IntWritable, Text> 
        {
            public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException 
            {
                try 
                { 
                    if(value.toString().contains("Patient cycle no"))   // remove header
                        return;
                    else 
                    {
                        String[] columns = value.toString().split(", ");   // split the columns
    
                        String id = columns[0];
                        int patient_cycle = Integer.parseInt(columns[1]);
                        String counceling = columns[2];
    
                        // rearrange the columns to put the cycles as key and the rest as a composite value
                        context.write(new IntWritable(patient_cycle), new Text(id + "_" + counceling));
                    }
                } 
                catch (Exception e) 
                {
                    e.printStackTrace();
                }
            }
        }
    
        /* input: <patient_cycle, (ID, counceling)>
         * output: <ID, (patient_cycle, counceling)>
         */
        public static class Reduce extends Reducer<IntWritable, Text, Text, Text>
        {
            public void reduce(IntWritable key, Iterable<Text> values, Context context) throws IOException, InterruptedException 
            {
                // for every value grouped by key...
                for(Text value : values)
                {
                    String[] split_value = value.toString().split("_");     // split the composite value
    
                    if(key.get() == 1)      // check if the key/patient cycle in this reducer is 1
                    {
                        if(split_value[1].equals("Yes"))    // check if counseling for this record is equal to "Yes"
                        {
                            // for patients with just 1 cycle, only store the records that have "counseling" equal to "Yes"
                            context.write(new Text(split_value[0]), new Text(Integer.toString(key.get()) + " " + split_value[1]));
                        }
                    }
                    else    // store all the other records as well
                        context.write(new Text(split_value[0]), new Text(Integer.toString(key.get()) + " " + split_value[1]));
                }
            }
        }
    
    
        public static void main(String[] args) throws Exception
        {
            // set the paths of the input and output directories in the HDFS
            Path input_dir = new Path("patients");
            Path output_dir = new Path("patients_out");
    
            // in case the output directory already exists, delete it
            Configuration conf = new Configuration();
            FileSystem fs = FileSystem.get(conf);
            if(fs.exists(output_dir))
                fs.delete(output_dir, true);
    
            // configure the MapReduce job
            Job job = Job.getInstance(conf, "Patient Filter");
            job.setJarByClass(PatientFilter.class);
            job.setMapperClass(Map.class);
            job.setReducerClass(Reduce.class);    
            job.setMapOutputKeyClass(IntWritable.class);
            job.setMapOutputValueClass(Text.class);
            job.setOutputKeyClass(Text.class);
            job.setOutputValueClass(Text.class);
            TextInputFormat.addInputPath(job, input_dir);
            TextOutputFormat.setOutputPath(job, output_dir);
            job.waitForCompletion(true);
        }
    }
    
    Id, Patient cycle no, counseling
    2345, 1, No
    1234, 22, Yes
    4567, 1, No
    2378, 10, No
    4852, 2, Yes
    2510, 9, Yes
    6564, 5, No
    3000, 1, No
    6958, 45, No
    1500, 1, No