如何将上一行的键复制到键值对RDD中下一行的键字段

时间:2014-11-12 09:44:45

标签: scala apache-spark rdd

示例数据集:

$, Claw         "OnCreativity" (2012)  [Himself]

$, Homo         Nykytaiteen museo (1986)  [Himself]  <25>
            Suuri illusioni (1985)  [Guests]  <22>

$, Steve        E.R. Sluts (2003) (V)  <12>

$hort, Too      2012 AVN Awards Show (2012) (TV)  [Himself - Musical Guest]
            2012 AVN Red Carpet Show (2012) (TV)  [Himself]
            5th Annual VH1 Hip Hop Honors (2008) (TV)  [Himself]
            American Pimp (1999)  [Too $hort]

我使用以下代码创建了一个键值对RDD:

To split data: val actorTuple = actor.map(l => l.split("\t"))
 To make KV pair: val actorKV = actorTuple.map(l => (l(0), l(l.length-1))).filter{case(x,y) => y != "" }

控制台上的键值RDD输出:

Array(($, Claw,"OnCreativity" (2012)  [Himself]), ($, Homo,Nykytaiteen museo (1986)  [Himself]  <25>), ("",Suuri illusioni (1985)  [Guests]  <22>), ($, Steve,E.R. Sluts (2003) (V)  <12>).......

但是,很多行都将这个“”作为键,即空白(参见上面的RDD输出),因为数据集的性质,所以,我希望有一个函数将前一行的actor复制到此如果它是空的那一行。 如何做到这一点。

2 个答案:

答案 0 :(得分:1)

Spark和Scala的新手。但也许改变你的行解析会更简单,并且首先创建一个具有list类型值的RDD对,例如。

($,Homo,(Nykytaiteen museo(1986)[Himself]&lt; 25&gt;,Suuri illusioni(1985)[嘉宾]&lt; 22&gt;))

我不知道您的数据,但也许如果一行不以&#34; $&#34;您附加到值列表。

然后根据你想要做的事情,也许你可以在上面描述的对RDD上使用flatMapValues(func)。这将应用一个函数,该函数将迭代器返回到RDD对的每个值,并且对于返回的每个元素,使用旧键生成键值条目。

增加: 您的输入数据是什么格式(&#34;示例数据集&#34;)?它是文本文件还是.tsv? 您可能想要一次加载整个文件。也就是说,使用.wholeTextFiles()而不是.textFile()来加载数据。这是因为您的记录存储在文件中的多行中。

ADDED 我不打算下载该文件,但在我看来,您感兴趣的每条记录都以&#34; $&#34;开头。 Spark可以使用任何Hadoop输入格式,因此请检查它们是否有适用于您的示例数据的格式。

如果没有,您可以编写自己的Hadoop InputFormat实现,将文件解析为拆分在此字符上的记录,而不是TextFiles的默认值,即&#39; \ n&#39;字符。

答案 1 :(得分:1)

继续xyzzy给出的想法,如何在将文件作为字符串加载后尝试此操作:

val actorFileSplit = actorsFile.split("\n\n")
val actorData = sc.parallelize(actorsFileSplit)
val actorDataSplit = actorsData.map(x => x.split("\t+",2).toList).map(line => (line(0), line(1).split("\n\t+").toList))

为了解释我在做什么,我开始在每次找到换行符时拆分字符串。我连续地将它并行化为用于映射函数的sparkcontext。然后我将每个条目分成两个部分,这两部分由多个标签(一个或多个)的第一次出现分隔。第一部分现在应该是演员,第二部分应该仍然是电影片名的字符串。第二部分可以再次在每个新行分开,然后是多个标签。这应该创建一个列表,其中包含每个actor的所有标题。最终结果如下:

actorDataSplit = [(String, [String])]
祝你好运