2017-09-29 23 views
1

我试图把星火字被人算例和集合字被一些其它的值数(例如,词和计数,其中人是“VI”或“MO “在下面的情况下)减少单词的列表,数元组最高聚集键

我有一个RDD这是它的值是元组的列表元组的列表:

[(u'VI', [(u'word1', 1), (u'word2', 1), (u'word3', 1)]), 
(u'MO', 
    [(u'word4', 1), 
    (u'word4', 1), 
    (u'word5', 1), 
    (u'word8', 1), 
    (u'word10', 1), 
    (u'word1', 1), 
    (u'word4', 1), 
    (u'word6', 1), 
    (u'word9', 1), 
    ... 
)] 

我想是这样的:

from operator import add 
reduced_tokens = tokenized.reduceByKey(add) 
reduced_tokens.take(2) 

这给了我:

[ 
('VI', 
    [(u'word1', 1), (u'word2', 1), (u'word3', 1)], 
('MO', 
    [(u'word4', 58), (u'word8', 2), (u'word9', 23) ...) 
] 

word count example here相似,我希望能够过滤掉字下面的一些人一些阈值的计数。谢谢!

回答

0

您尝试减少的键是(name, word)对,而不仅仅是名称。所以,你需要做一个.map一步来解决,你的数据:

def key_by_name_word(record): 
    name, (word, count) = record 
    return (name, word), count 

tokenized_by_name_word = tokenized.map(key_by_name_word) 
counts_by_name_word = tokenized_by_name_word.reduce(add) 

这应该给你

[ 
    (('VI', 'word1'), 1), 
    (('VI', 'word2'), 1), 
    (('VI', 'word3'), 1), 
    (('MO', 'word4'), 58), 
    ... 
] 

要进入它正是你所提到的相同的格式,然后你可以这样做:

def key_by_name(record): 
    # this is the inverse of key_by_name_word 
    (name, word), count = record 
    return name, (word, count) 

output = counts_by_name_word.map(key_by_name).reduceByKey(add) 

但它实际上可能更容易在平板格式counts_by_name_word与数据一起工作。

+0

我的数据结构有点不同,但这有助于我理解如何解决它。我的初始数据看起来像'[Row(key = u'VI',item = u'word1 word2 word3'),...]'并且我创建了一个函数,该函数标记了该项并返回了[[((name,token) ,1)令牌令牌]'。从那里我用flatMap将函数应用于我的数据以获得您建议的结构。 – scmz

0

为了完整起见,这里是我如何解决这个问题的各个部分:

问1:通过一些关键

import re 

def restructure_data(name_and_freetext): 
    name = name_and_freetext[0] 
    tokens = re.sub('[&|/|\d{4}|\.|\,|\:|\-|\(|\)|\+|\$|\!]', ' ', name_and_freetext[1]).split() 
    return [((name, token), 1) for token in tokens] 

filtered_data = data.filter((data.flag==1)).select('name', 'item') 
tokenized = filtered_data.rdd.flatMap(restructure_data) 

总字数问2:过滤掉的话有以下一些计数门槛:

from operator import add 

# keep words which have counts >= 5 
counts_by_state_word = tokenized.reduceByKey(add).filter(lambda x: x[1] >= 5) 

# map filtered word counts into a list by key so we can sort them 
restruct = counts_by_name_word.map(lambda x: (x[0][0], [(x[0][1], x[1])])) 

奖励:从最频繁的排序的话至少频繁

# sort the word counts from most frequent to least frequent words 
output = restruct.reduceByKey(add).map(lambda x: (x[0], sorted(x[1], key=lambda y: y[1], reverse=True))).collect()