在Reducer中获取输入文件

时间:2014-02-25 05:50:36

标签: java csv hadoop mapreduce normalization

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

因此,当给出数字csv文件时,我们需要为每列应用此文件。

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

到目前为止我做的是

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 − minA)/(maxA − minA)]*(new maxA − new minA ) + new minA )

我的new maxA and new minA is 0.1,0.0,我也有每列max和min。 为了应用eqn v1我需要得到v,即输入文件。

如何获得?

我的想法是什么 -

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

[5.3,3.6,1.6,0.3]

为每个属性应用eqn并发出整行(Mincer和Max值在Reducer本身中是已知的)。但是在reducer中我只会得到列值。否则我应该将我的inputfile作为reducer()的setup()中的参数读取。

这是最佳做法吗? 任何建议。

更新

正如Mark Vickery建议我做了以下内容。

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());

}

在第一遍中,我能够正确地获得所有值。但是对于第二遍,我只是重复获得每个元素。

2 个答案:

答案 0 :(得分:1)

您可以在同一个reduce中对reducer值进行两次枚举。第一次计算最小值和最大值,第二次计算你的值,然后发出它。

粗略的例子:

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 − minA)/(maxA − minA)]*(new maxA − new minA ) + new minA;

        context.Emit(result);
    }
}

答案 1 :(得分:1)

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

    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());

我们只会输出

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

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

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));
  }

输出

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