按部门名称划分的女员工缩减代码

Reducer code for female employee by department name

我是 map-reduce 编码的新手。我请求帮助编写 reducer 代码,但找不到。按部门名称划分的女性员工人数。

我有两个结构化数据文件。一个给员工,另一个给部门。在员工档案中,我有 "Empid"、"Empname"、"Empgender"、"EmpDeptId" 和 "Empsalary"。在第二个部门文件中,我有 "DepId" 和 "DeptName"。现在我想通过每个部门名称找出 FEMALE 员工的数量。

我写了一个 EmpMapper,我在其中 return 将密钥设置为 DeptId (IntWritable) 而不是。出现次数,即迭代(作为文本)作为值。 例如

(1,[1])
(2,[1])
(3,[1])
(4,[1])
(1,[1])

在洗牌和排序阶段之后,输出如下:

(1,[1,1])
(2,[1])
(3,[1])
(4,[1])

我还从 DeptMapper return 输出以下输出(键作为 DeptId (IntWritable) 和 DeptName(作为文本)作为值):

(1,[IT])
(2,[Comsc])
(3,[Electrical])
(4,[Mechanical])

现在我担心的是我无法正确编写减速器。我想 return reducer 输出为

(IT,2)
(Comsc,1)
(Electrical,1)
(Mechanical,1)

请在 reducer 代码中帮助我(其中需要一种连接)。

在 MapReduce 中编写连接很麻烦。如果您已经拥有结构化(关系)数据,那么考虑一个高级框架可能是有意义的,例如 Hive,它允许您编写 SQL 查询。

如果您想为此使用 MapReduce,请查看 this post for reduce-side joins and this post for map-side joins。

这基本上是一个reduce端连接,在reducer端创建一个部门映射,并为每个员工使用这个映射获取每个员工的部门,然后主要是一个单独的数据结构来计数。

你的reducer有key = IntWritable, value = Text。因此,您可以轻松地将它们连接在一起,但是当您获得计数时,我会遇到类型问题(例如“1”、“1”以及部门名称 "IT")。

一个简单的方法是只检查您的文本是否为 int,如果遇到解析错误,您可以假设它是您的部门名称。

也许下面的代码(尽管有点老套)可能会帮助您找到解决方案:

@Override
protected void reduce(Text key, Iterable<Text> values, Context context)
        throws IOException, InterruptedException {

    String departmentName = null;
    int sum = 0;
    for (Text value : values) {
        String unknown = value.toString();
        try {
            int valueCount = Integer.parseInt(unknown);
            sum += valueCount;
        } catch (NumberFormatException e) {
            departmentName = unknown;
        }
    }

    assert departmentName != null;

    context.write(new Text(departmentName), new IntWritable(sum));
}

我不喜欢使用异常来进行流量控制,但让我们在这里务实一点。

小工作改进:

  1. 您可以通过使用 MultipleInputs
    1. 以department-id为key,count+department name为value
    2. 做上面的减少