複合キーと値の形式のタプルがたくさんあります。例えば、
tfile.collect() = [(('id1','pd1','t1'),5.0),
(('id2','pd2','t2'),6.0),
(('id1','pd1','t2'),7.5),
(('id1','pd1','t3'),8.1) ]
このコレクションに対してSQLのような操作を実行したいのですが、id [1..n]またはpd [1..n]に基づいて情報を集約できます。 SQLContextを使用せずにVanillapysparkapisを使用して実装したいと思います。私の現在の実装では、一連のファイルから読み取り、RDDをマージしています。
def readfile():
fr = range(6,23)
tfile = sc.union([sc.textFile(basepath+str(f)+".txt")
.map(lambda view: set_feature(view,f))
.reduceByKey(lambda a, b: a+b)
for f in fr])
return tfile
集約された配列を値として作成するつもりです。例えば、
agg_tfile = [((id1,pd1),[5.0,7.5,8.1])]
ここで、5.0、7.5、8.1は[t1、t2、t3]を表します。私は現在、Vanilla python辞書を使用したコードで同じことを達成しています。小さなデータセットでは問題なく動作しますが、大きなデータセットでは拡張できない可能性があるので心配です。効率的な方法はありますか? pyspark apisを使用して同じですか?
私の推測では、複数のフィールドに従ってデータを転置したいと思います。
簡単な方法は、グループ化するターゲットフィールドを連結し、それをペアのRDDのキーにすることです。例えば:
lines = sc.parallelize(['id1,pd1,t1,5.0', 'id2,pd2,t2,6.0', 'id1,pd1,t2,7.5', 'id1,pd1,t3,8.1'])
rdd = lines.map(lambda x: x.split(',')).map(lambda x: (x[0] + ', ' + x[1], x[3])).reduceByKey(lambda a, b: a + ', ' + b)
print rdd.collect()
次に、転置された結果が得られます。
[('id1, pd1', '5.0, 7.5, 8.1'), ('id2, pd2', '6.0')]
((id1、t1)、((p1,5.0)、(p2,6.0))などをマップ関数としてグループ化しました。後で、[p1、p2 、。の配列を作成するmap_groupの使用を減らします。 。。]そしてそれぞれの位置に値を入力します。
def map_group(pgroup):
x = np.zeros(19)
x[0] = 1
value_list = pgroup[1]
for val in value_list:
fno = val[0].split('.')[0]
x[int(fno)-5] = val[1]
return x
tgbr = tfile.map(lambda d: ((d[0][0],d[0][2]),[(d[0][1],d[1])])) \
.reduceByKey(lambda p,q:p+q) \
.map(lambda d: (d[0], map_group(d)))
これは、計算の観点からは高価なソリューションのように感じます。しかし、今のところは機能します。