带有键和RDD的RDD到数据帧

时间:2018-03-21 17:33:50

标签: apache-spark pyspark pyspark-sql

我有来自不同时代和各大洲的许多温度测量数据。 我将数据加载到rdd(我在此代码示例中给出了数据示例),按键组合,然后将dicts列表转换为dataframe。

def to_list(a):
    return [a]


def append(a, b):
    a.append(b)
    return a


def extend(a, b):
    a.extend(b)
    return a


def main():
    sc = pyspark.SparkContext()
    parsing_obj = [[('Africa', {'time': '1', 'temp': '2'})], [('Africa', {'time': '1', 'temp': '2'})],
                   [('America', {'time': '1', 'temp': '2'})], [('America', {'time': '1', 'temp': '2'})],
                   [('Africa', {'time': '1', 'temp': '2'})]]

    rdd = sc.parallelize(parsing_obj)
    rdd = rdd.map(lambda l: l[0]).combineByKey(to_list, append, extend)
    print rdd.collect()

这个数据结构输出:

[
('Africa', [{'temp': '2', 'time': '1'}, {'temp': '2', 'time': '1'}, {'temp': '2', 'time': '1'}]),
('America', [{'temp': '2', 'time': '1'}, {'temp': '2', 'time': '1'}])
]

\ 有没有办法在没有驱动驱动程序中的rdd的每个键,创建数据帧并保存到hdfs? 我希望采用更加平行和通用的方式来实现它。

1 个答案:

答案 0 :(得分:0)

您可以简单地执行以下操作

parsing_obj = [[('Africa', {'time': '1', 'temp': '2'})], [('Africa', {'time': '1', 'temp': '2'})],
               [('America', {'time': '1', 'temp': '2'})], [('America', {'time': '1', 'temp': '2'})],
               [('Africa', {'time': '1', 'temp': '2'})]]

df = sc.parallelize(parsing_obj).toDF(['info'])
df = df.select(df.info._1.alias('country'), df.info._2.alias('info'))
from pyspark.sql import functions as F
df = df.groupBy(df.country).agg(F.collect_list(df.info).alias('info'))
df.show(truncate=False)

会给你

+-------+---------------------------------------------------------------------------------+
|country|info                                                                             |
+-------+---------------------------------------------------------------------------------+
|Africa |[Map(temp -> 2, time -> 1), Map(temp -> 2, time -> 1), Map(temp -> 2, time -> 1)]|
|America|[Map(temp -> 2, time -> 1), Map(temp -> 2, time -> 1)]                           |
+-------+---------------------------------------------------------------------------------+

您可以将其另存为parquet文件

df.coalesce(1).write.parquet('path to parquet file`)

<强>更新

如果您不希望保存表格的schema并希望将其保存为纯文本csv ,那么您将需要转换字典和数组到纯文本。我有定义了一个udf函数,用于将dict转换为文本json,并使用concat_ws将所有列转换为csv文本

from pyspark.sql import functions as F
from pyspark.sql import types as T
import json
def makeStringFunc(list):
    return '['+', '.join(json.dumps(x).replace("\"", "'") for x in list)+']'

makeStringUdf = F.udf(makeStringFunc, T.StringType())
df = df.groupBy(df.country)\
    .agg(makeStringUdf(F.collect_list(df.info)).alias('info'))\
    .select(F.concat_ws(", ", F.col('country'), F.col('info')))

应该是

+--------------------------------------------------------------------------------------------+
|concat_ws(, , country, info)                                                                |
+--------------------------------------------------------------------------------------------+
|Africa, [{'temp': '2', 'time': '1'}, {'temp': '2', 'time': '1'}, {'temp': '2', 'time': '1'}]|
|America, [{'temp': '2', 'time': '1'}, {'temp': '2', 'time': '1'}]                           |
+--------------------------------------------------------------------------------------------+

您可以使用csv函数

保存它
df.coalesce(1).write.csv("path to ouput path")