rmr2正在复制我的映射器中的键

时间:2014-07-21 03:41:54

标签: rhadoop

出于某种原因,rmr2似乎在某些情况下不正确地处理密钥,复制每个值的密钥。

我在Windows 7下使用的是64版本的R 3.1.1版本。我的rmr版本是rmr2_2.3.0。

我通过设置rmr.options(backend =" local")来使用本地模式。

我有一个非常简单的文本文件,其中包含以下内容:

a|1|blue
b|2|green
c|1|green
d|3|blue
e|2|yellow

我可以使用以下map-reduce作业轻松检索这些内容,其中f是我文件的路径:

library(rmr2)

from.dfs(
  mapreduce(
  input=f,
  input.format="text",
  map = function(k,v) keyval(k,v)))

正如预期的那样,输出是:

$key
NULL

$val
[1] "a|1|blue"   "b|2|green"  "c|1|green"  "d|3|blue"   "e|2|yellow"

我可以运行另一个map reduce作业,它将行的长度指定为要传递给reducer的键:

from.dfs(
  mapreduce(
  input=f,
  input.format="text",
   map = function(k,v) keyval(str_length(v),v)))

正如所料,输出是:

$key
[1]  8  8  9  9 10

$val
[1] "a|1|blue"   "d|3|blue"   "b|2|green"  "c|1|green"  "e|2|yellow"

而不是值的长度,我可以取代第一个字符:

from.dfs(
  mapreduce(
  input=f,
  input.format="text",
  map = function(k,v) keyval(substr(v,0,1),v)))

输出再次如预期的那样:

$key
[1] "a" "b" "c" "d" "e"

$val
[1] "a|1|blue"   "b|2|green"  "c|1|green"  "d|3|blue"   "e|2|yellow"

到目前为止,这么好。现在我想分割值并使用第一个字段。我的代码是:

from.dfs(
  mapreduce(
  input=f,
  input.format="text",
  map = function(k,v) keyval(unlist(strsplit(v,'\\|'))[1],v)))

这次出乎意料的输出是:

$key
[1] "a" "a" "a" "a" "a"

$val
[1] "a|1|blue"   "b|2|green"  "c|1|green"  "d|3|blue"   "e|2|yellow"

我希望使用子字符串看到与前一个示例相同的输出,但不是键向量是" a" " B" " C" " d" " E"它只是重复5次的第一把钥匙, "" "" "" "" ""

我可以改变我想要的字段,例如改为第三个字段:

from.dfs(
  mapreduce(
  input=f,
  input.format="text",
  map = function(k,v) keyval(unlist(strsplit(v,'\\|'))[3],v)))

再次重复第一个键,而不是每个值的唯一键。输出是:

$key
[1] "blue" "blue" "blue" "blue" "blue"

$val
[1] "a|1|blue"   "b|2|green"  "c|1|green"  "d|3|blue"   "e|2|yellow"

我最终知道这件事。怎么了?这是rmr2中的错误,还是什么?

更新: 我在运行rmr2_3.1.1的Ubuntu 12.04系统上尝试了相同的例子,它具有完全分布式的HDP2集群,并得到了几乎相同的结果。对于返回预期结果的示例,我得到的唯一区别是key,val对的顺序与文件中的顺序不同(这是可以理解的)。对于有问题的例子我甚至得到了更奇怪的结果:

$key
[1] "d" "d" "a" "a" "a"

$val
[1] "d|3|blue"   "e|2|yellow" "a|1|blue"   "b|2|green"  "c|1|green"

1 个答案:

答案 0 :(得分:3)

回答我自己的问题。该问题的答案涉及理解(猜测)输入到地图函数的(k,v)参数的结构。它们似乎是价值观的载体。也就是说,map函数被称为一次,其中包含分割的所有值的向量。这是可能的,因为正在使用Hadoop流。将此与典型的Java Hadoop映射函数进行对比,该映射函数为每个值调用一次,并在每次调用时仅接收一个值。

所以解决方案是使用:

from.dfs( 
  mapreduce(
  input=f,
  input.format="text",
   map = function(k,v) keyval(matrix(unlist(strsplit(v,'\\|')),nrow=length(v),byrow=TRUE)[,1],v)))

产生所需的副产品:

$key
[1] "d" "e" "a" "b" "c"

$val
[1] "d|3|blue"   "e|2|yellow" "a|1|blue"   "b|2|green"  "c|1|green"