我是Hadoop的新手。 我尝试使用MapReduce来获取每年的最小和最大每月降水值。 这是一年的数据集,看起来像:
Product code,Station number,Year,Month,Monthly Precipitation Total (millimetres),Quality
IDCJAC0001,023000,1839,01,11.5,Y
IDCJAC0001,023000,1839,02,11.4,Y
IDCJAC0001,023000,1839,03,20.8,Y
IDCJAC0001,023000,1839,04,10.5,Y
IDCJAC0001,023000,1839,05,4.8,Y
IDCJAC0001,023000,1839,06,90.4,Y
IDCJAC0001,023000,1839,07,54.2,Y
IDCJAC0001,023000,1839,08,97.4,Y
IDCJAC0001,023000,1839,09,41.4,Y
IDCJAC0001,023000,1839,10,40.8,Y
IDCJAC0001,023000,1839,11,113.2,Y
IDCJAC0001,023000,1839,12,8.9,Y
这就是我1839年得到的结果:
1839 1.31709005E9 1.3172928E9
很明显,结果与原始数据不匹配...但是我无法弄清楚为什么会发生...
答案 0 :(得分:1)
您发现在Reducer中的最小和最大暴露量的逻辑似乎已消失。您设置了maxExposure
两次,并且从不检查它是否实际上是最大曝光量。我会去的:
public void reduce(Text key, Iterable<MinMaxExposure> values,
Context context) throws IOException, InterruptedException {
Double minExposure = Double.MAX_VALUE;
Double maxExposure = Double.MIN_VALUE;
for (MinMaxExposure val : values) {
if (val.getMinExposure() < minExposure) {
minExposure = val.getMinExposure();
}
if (val.getMaxExposure() > maxExposure) {
maxExposure = val.getMaxExposure();
}
}
MinMaxExposure resultRow = new MinMaxExposure();
resultRow.setMinExposure(minExposure);
resultRow.setMaxExposure(maxExposure);
context.write(key, resultRow);
}
答案 1 :(得分:1)
您的代码有多个问题。
(1)在MinMixExposure
中,您写了双精度字,但读了整数。您还使用Double类型(意味着您关心空值),但在序列化/反序列化中不处理空值。如果您确实需要null,则应编写如下内容:
// write
out.writeBoolean(value != null);
if (value != null) {
out.writeDouble(value);
}
// read
if (in.readBoolean()) {
value = in.readDouble();
} else {
value = null;
}
如果不需要存储空值,请将Double
替换为double
。
(2)在map函数中,将代码包装在IOException
catch块中。这没有任何意义。如果输入数据的记录格式不正确,那么很可能会在NullPointerException
中得到NumberFormatError
/ Double.parseDouble()
。但是,您不处理这些异常。
在调用parseDouble
之后检查空值也是没有道理的。
(3)您将映射键作为Text
传递给减速器。我建议将年份设置为IntWritable
(并用job.setMapOutputKeyClass(IntWritable.class);
配置您的工作)。
(4)maxExposure
的处理方式必须与减速器代码中的minExposure
类似。目前,您只返回最后一条记录的值。