Hadoop MapReduce 在 reducer 中访问 mapper 输出数
Hadoop MapReduce access mapper output number in reducer
我有一个映射器,它输出句子中的每个字母,这是键,数字 1 作为它的值。例如,我的映射器输出 'How are you' 为
H 1
o 1
w 1
a 1
r 1
e 1
y 1
o 1
u 1
我的 reducer 接受这个并使用 1 来计算每个字母的出现次数。例如,它会输出字母 'o' 作为键,输出 2 作为它的值,因为它出现了两次。
我的问题是我想计算每个字母在句子中出现的频率。为此,我需要访问句子中字母的总数(映射器输出的数量)。我是 mapreduce 的新手,所以我不确定最好的方法。
假设你的映射器正在获取一个完整的句子,你试图在其中找到频率并且你正在使用 Java API,你可以通过 [=16] 从映射器输出两个键=]函数:
java 映射器语法:public void map(LongWritable key, Text value, Context context)
- 键:
<lineNo_Letter>
;值:c_m
- 键:
<lineNo_Letter>
;值:t_n
其中
lineNo = same as key to the mapper (the first parameter to the above function)
letter = your desired letter
m = <total number of letters in the line (the 2nd parameter to the above function) input to the mapper>
n = <number of occurrence of letter in the line (the 2nd parameter to the above function) mapper input line>
c_
和 a_
只是标识计数类型的前缀。 c
代表字母出现;而 t
代表总出现次数。
基本上,我们在这里利用的概念是,您可以从 mapper/reducer.
中编写任意数量的 key-value
现在reducer会得到类似的东西
键:<lineNo_letter>
值:ListOf[c_m, t_n]
现在,只需迭代列表,使用定界符 _
和标识符前缀(t
和 c
)将其拆分;您在减速器中有所需的值。即
Total number of letter in the sentence = m
Total number of occurrence of the letter = n
编辑:添加伪逻辑
以您的示例为例,假设映射器函数 public void map(LongWritable key, Text value, Context context)
的输入行是
LongWritable key = 1
Text value = howareyou
映射器的输出应该是:
-- Output length of the Text Value against each letter
context.write("1_h", "t_9");
context.write("1_o", "t_9");
context.write("1_w", "t_9");
context.write("1_a", "t_9");
context.write("1_r", "t_9");
context.write("1_e", "t_9");
context.write("1_y", "t_9");
context.write("1_u", "t_9");
请注意,上面的输出是来自映射器的句子的每个字母一次。这就是为什么字母 o
只输出一次(即使它在输入中出现两次)。
映射器代码的更多输出将是
-- Output individual letter count in the input text as
context.write("1_h", "c_1");
context.write("1_o", "c_2");
context.write("1_w", "c_1");
context.write("1_a", "c_1");
context.write("1_r", "c_1");
context.write("1_e", "c_1");
context.write("1_y", "c_1");
context.write("1_u", "c_1");
同样,您可以看到字母 o
的值为 c_2
,因为它在句子中出现了两次。
现在将生成 8 个 reducer,每个都将获得以下键值对之一:
key: "1_h" value: ListOf["t_9", "c_1"]
key: "1_o" value: ListOf["t_9", "c_2"]
key: "1_w" value: ListOf["t_9", "c_1"]
key: "1_a" value: ListOf["t_9", "c_1"]
key: "1_r" value: ListOf["t_9", "c_1"]
key: "1_e" value: ListOf["t_9", "c_1"]
key: "1_y" value: ListOf["t_9", "c_1"]
key: "1_u" value: ListOf["t_9", "c_1"]
现在在每个reducer中,拆分key得到行号和字母。
遍历值列表以提取总数和字母出现次数。
第 1 行中字母 h
的出现频率 = Integer.parseInt("c_1".split("_")[1])/Integer.parseInt("t_9".split("_")[1])
这是你实现的伪逻辑。
不要看到每个字母就马上写下来。数一数所有的字符,然后写下总数和字符。
然后根据您编写值的方式,您的减速器将看到
o, [(1,9), (1,9)]
求和,提取任意一个九,然后除法
自己解决:使用全局计数器访问MAP_OUTPUT_RECORDS得到reducer中mapper输出的总数。
代码:
Configuration conf = context.getConfiguration();
Cluster cluster = new Cluster(conf);
Job currentJob = cluster.getJob(context.getJobID());
long totalCharacters = currentJob.getCounters().findCounter(TaskCounter.MAP_OUTPUT_RECORDS).getValue();
我有一个映射器,它输出句子中的每个字母,这是键,数字 1 作为它的值。例如,我的映射器输出 'How are you' 为
H 1
o 1
w 1
a 1
r 1
e 1
y 1
o 1
u 1
我的 reducer 接受这个并使用 1 来计算每个字母的出现次数。例如,它会输出字母 'o' 作为键,输出 2 作为它的值,因为它出现了两次。
我的问题是我想计算每个字母在句子中出现的频率。为此,我需要访问句子中字母的总数(映射器输出的数量)。我是 mapreduce 的新手,所以我不确定最好的方法。
假设你的映射器正在获取一个完整的句子,你试图在其中找到频率并且你正在使用 Java API,你可以通过 [=16] 从映射器输出两个键=]函数:
java 映射器语法:public void map(LongWritable key, Text value, Context context)
- 键:
<lineNo_Letter>
;值:c_m
- 键:
<lineNo_Letter>
;值:t_n
其中
lineNo = same as key to the mapper (the first parameter to the above function) letter = your desired letter m = <total number of letters in the line (the 2nd parameter to the above function) input to the mapper> n = <number of occurrence of letter in the line (the 2nd parameter to the above function) mapper input line>
c_
和 a_
只是标识计数类型的前缀。 c
代表字母出现;而 t
代表总出现次数。
基本上,我们在这里利用的概念是,您可以从 mapper/reducer.
中编写任意数量的 key-value现在reducer会得到类似的东西
键:<lineNo_letter>
值:ListOf[c_m, t_n]
现在,只需迭代列表,使用定界符 _
和标识符前缀(t
和 c
)将其拆分;您在减速器中有所需的值。即
Total number of letter in the sentence = m
Total number of occurrence of the letter = n
编辑:添加伪逻辑
以您的示例为例,假设映射器函数 public void map(LongWritable key, Text value, Context context)
的输入行是
LongWritable key = 1
Text value = howareyou
映射器的输出应该是:
-- Output length of the Text Value against each letter
context.write("1_h", "t_9");
context.write("1_o", "t_9");
context.write("1_w", "t_9");
context.write("1_a", "t_9");
context.write("1_r", "t_9");
context.write("1_e", "t_9");
context.write("1_y", "t_9");
context.write("1_u", "t_9");
请注意,上面的输出是来自映射器的句子的每个字母一次。这就是为什么字母 o
只输出一次(即使它在输入中出现两次)。
映射器代码的更多输出将是
-- Output individual letter count in the input text as
context.write("1_h", "c_1");
context.write("1_o", "c_2");
context.write("1_w", "c_1");
context.write("1_a", "c_1");
context.write("1_r", "c_1");
context.write("1_e", "c_1");
context.write("1_y", "c_1");
context.write("1_u", "c_1");
同样,您可以看到字母 o
的值为 c_2
,因为它在句子中出现了两次。
现在将生成 8 个 reducer,每个都将获得以下键值对之一:
key: "1_h" value: ListOf["t_9", "c_1"]
key: "1_o" value: ListOf["t_9", "c_2"]
key: "1_w" value: ListOf["t_9", "c_1"]
key: "1_a" value: ListOf["t_9", "c_1"]
key: "1_r" value: ListOf["t_9", "c_1"]
key: "1_e" value: ListOf["t_9", "c_1"]
key: "1_y" value: ListOf["t_9", "c_1"]
key: "1_u" value: ListOf["t_9", "c_1"]
现在在每个reducer中,拆分key得到行号和字母。 遍历值列表以提取总数和字母出现次数。
第 1 行中字母 h
的出现频率 = Integer.parseInt("c_1".split("_")[1])/Integer.parseInt("t_9".split("_")[1])
这是你实现的伪逻辑。
不要看到每个字母就马上写下来。数一数所有的字符,然后写下总数和字符。
然后根据您编写值的方式,您的减速器将看到
o, [(1,9), (1,9)]
求和,提取任意一个九,然后除法
自己解决:使用全局计数器访问MAP_OUTPUT_RECORDS得到reducer中mapper输出的总数。
代码:
Configuration conf = context.getConfiguration();
Cluster cluster = new Cluster(conf);
Job currentJob = cluster.getJob(context.getJobID());
long totalCharacters = currentJob.getCounters().findCounter(TaskCounter.MAP_OUTPUT_RECORDS).getValue();