【发布时间】:2015-09-25 09:17:24
【问题描述】:
我有两个csv 文件。一个有(user_id, gameName,score),另一个有(user_id, age)。如何使用 map reduce 编程执行连接,以便计算每个游戏玩家的平均年龄。我不知道如何继续这个。
【问题讨论】:
标签: csv join mapreduce bigdata
我有两个csv 文件。一个有(user_id, gameName,score),另一个有(user_id, age)。如何使用 map reduce 编程执行连接,以便计算每个游戏玩家的平均年龄。我不知道如何继续这个。
【问题讨论】:
标签: csv join mapreduce bigdata
您可以使用两个 MapReduce 作业来实现此目的。首先,加入两个数据集。第二,计算每场比赛球员的平均年龄。
让我们将数据集 (user_id ,gameName,score) 称为 GameSet 并将 (user_id ,age) 称为 AgeSet。
首先,JoinMapreduce 作业将为每个数据集分别有两个映射器定义。这些映射器任务将输出user_id as key 和record as value,并将标识符作为前缀附加到记录中。假设这个前缀是 "game" 用于第一个数据集和 "age" 用于第二个数据集。这是识别Reducer 中的记录所必需的。 Reducer 将在列表中为每个键接收两个值(假设数据中没有重复项)。标识符将帮助我们识别记录,我们将创建一个new record,其中将包含有关用户的所有信息,例如gameName、score 和age。 reducer 的输出将有gameName as key 和record as value。 (如果你想优化,那么你可以只发出用户的年龄。)
其次,第一个 MapReduce 作业的输出是 GameName as Key 和 Record as Value。这将作为下一个 AvgAgePerGame MapReduce 作业的输入。它将具有身份映射器,它将输入作为映射器输出发出。现在在 reducer 中,您将收到 GameName as key 和 list of records(年龄列表)作为值。您可以将玩家的年龄相加,然后将其除以 reduce 方法中的玩家人数。输出密钥 (GameName) 和 avg。年龄作为价值。
【讨论】:
@YoungHobbit 给出的答案是正确的。可以通过使用MutlipleInputFormat 和Chaining jobs 的ReduceSide joins 的组合来解决您的问题。
我已经为这个问题实现了整个 MapReduce 代码,可以在我的 github repo here 中找到。
我们需要使用 2 个映射器,即 GameMapper 和 AgeMapper 来处理我们需要加入的 2 个文件。这可以通过MultipleInputFormat来实现。
接下来,我们使用 reducer 连接来自两个映射器的数据并将输出写入 HDFS。这可以通过Reduce Side Joins来实现
接下来我们编写另一个 MR 作业,它使用前一个 MR 作业的输出作为输入。此映射器将游戏名称作为键发出,将年龄作为每条记录的值发出。
最后在逻辑发生的地方编写了一个 reducer,以找出每个游戏的用户平均年龄。然后将输出写入 HDFS。
在我的实现中,这两个 MR 作业都是从单个 Driver 类调用的。这是由Chaining Jobs 实现的。
有关我实现此问题的更多信息,请查看 github repo here 中的自述文件。
【讨论】: