2

由于某种原因,rmr2 似乎在某些情况下不正确地处理键,为每个值复制键。

我在 Windows 7 下使用 R 版本 3.1.1,即 64 位版本。我的 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 次,“a” “一个”“一个”“一个”“一个”。

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

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 系统上尝试了相同的示例,并获得了几乎相同的结果。对于返回预期结果的示例,我得到的唯一区别是 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"
4

1 回答 1

3

回答我自己的问题。该问题的答案涉及理解(猜测)输入到 map 函数的 (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"
于 2014-07-21T17:48:36.853 回答