出于某种原因,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"
答案 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"