关于Java:在Reducer中获取输入文件

Get input file in Reducer

我正在尝试编写mapreduce作业,该作业需要对值进行两次迭代。

因此,当给出数值csv文件时,我们需要将其应用于每一列。

为此,我们需要找到minmax值并将其应用于equation(v1)。

我到目前为止所做的是

1
2
3
4
In map()
I emit the column id as key and each column as values
In Reduce()
I calculated the min and max values of each column.

那之后,我被困住了。
接下来,我的目标是apply等式

(v = [(v a?’ minA)/(maxA a?’ minA)]*(new maxA a?’ new minA ) + new minA )

我的new maxA and new minA is 0.1,0.0和我的每一列也分别是max和min。
为了应用eqn v1,我需要获取v,即输入文件。

如何获取?

我原以为是-

从输入的csv文件中获取第一行(iris数据集)

1
[5.3,3.6,1.6,0.3]

为每个属性应用eqn并发出整个行(在Reducer本身中知道Min和Max值)。但是在reducer中,我只会获取列值,否则我应该将我的输入文件作为reducer()的setup()中的参数读取。

这是最佳实践。
任何建议。

更新

根据Mark Vickery的建议,我执行了以下操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public void reduce(Text key, Iterable<DoubleWritable> values, Context context) throws IOException,
    InterruptedException {
System.out.println("in reducer");
double min = Integer.MAX_VALUE,max = 0;
Iterator<DoubleWritable> iterator = values.iterator();
ListIterator<DoubleWritable> lit = IteratorUtils.toListIterator(iterator);
System.out.println("Using ListIterator 1st pass");
while(lit.hasNext()){
    System.out.println(lit.next());
    DoubleWritable value = lit.next();
    if (value.get()< min) {
        min = value.get();
    }
    if (value.get() > max) {
        max = value.get();
    }
}
System.out.println(min);
System.out.println(max);

// move the list iterator back to start
while(lit.hasPrevious()){
    lit.previous();
}

System.out.println("Using ListIterator 2nd pass");
double x = 0;
while(lit.hasNext()){
    System.out.println(lit.next());

}

在第1遍中,我能够正确获取所有值。但是对于第2遍,我仅重复获取每个元素。


我找到了答案。
如果我们尝试在Reducer中迭代两次,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
    ListIterator<DoubleWritable> lit = IteratorUtils.toListIterator(it);
    System.out.println("Using ListIterator 1st pass");
    while(lit.hasNext())
        System.out.println(lit.next());

    // move the list iterator back to start
    while(lit.hasPrevious())
        lit.previous();

    System.out.println("Using ListIterator 2nd pass");
    while(lit.hasNext())
        System.out.println(lit.next());

我们只会输出为

1
2
3
4
5
6
7
8
9
10
11
12
Using ListIterator 1st pass
5.3
4.9
5.3
4.6
4.6
Using ListIterator 2nd pass
5.3
5.3
5.3
5.3
5.3

为了以正确的方式获取它,我们应该像这样循环:

1
2
3
4
5
6
7
8
9
10
11
ArrayList<DoubleWritable> cache = new ArrayList<DoubleWritable>();
 for (DoubleWritable aNum : values) {
    System.out.println("first iteration:" + aNum);
    DoubleWritable writable = new DoubleWritable();
    writable.set(aNum.get());
    cache.add(writable);
 }
 int size = cache.size();
 for (int i = 0; i < size; ++i) {
     System.out.println("second iteration:" + cache.get(i));
  }

输出

1
2
3
4
5
6
7
8
9
10
first iteration: 5.3
first iteration: 4.9
first iteration: 5.3
first iteration: 4.6
first iteration: 4.6
second iteration: 5.3
second iteration: 4.9
second iteration: 5.3
second iteration: 4.6
second iteration: 4.6


您可以在同一归约中两次枚举归约值。第一次计算最小值和最大值,第二次计算您的值,然后发出它。

粗略示例:

1
2
3
4
5
6
7
8
9
10
11
12
public void Reduce(string key, List<string> values, Context context)
{
    var minA = Min(values);
    var maxA = Min(values);

    foreach (var v in values)
    {
        var result = [(v a?’ minA)/(maxA a?’ minA)]*(new maxA a?new minA ) + new minA;

        context.Emit(result);
    }
}