Python 基于某个键值从RDD创建多个Spark数据帧(pyspark)
我有一些包含JSON对象的文本文件(每行一个对象)。例如:Python 基于某个键值从RDD创建多个Spark数据帧(pyspark),python,apache-spark,pyspark,spark-dataframe,rdd,Python,Apache Spark,Pyspark,Spark Dataframe,Rdd,我有一些包含JSON对象的文本文件(每行一个对象)。例如: {"a": 1, "b": 2, "table": "foo"} {"c": 3, "d": 4, "table": "bar"} {"a": 5, "b": 6, "table": "foo"} ... 我想根据表名将文本文件的内容解析为Spark数据帧。因此,在上面的示例中,我将有一个用于“foo”的数据帧和另一个用于“bar”的数据帧。我已经用以下(pyspark)代码将JSON行分组到RDD中的列表中: 这将生成一个RDD,其
{"a": 1, "b": 2, "table": "foo"}
{"c": 3, "d": 4, "table": "bar"}
{"a": 5, "b": 6, "table": "foo"}
...
我想根据表名将文本文件的内容解析为Spark数据帧。因此,在上面的示例中,我将有一个用于“foo”的数据帧和另一个用于“bar”的数据帧。我已经用以下(pyspark)代码将JSON行分组到RDD中的列表中:
这将生成一个RDD,其中包含具有以下结构的元组列表:
RDD[("foo", ['{"a": 1, "b": 2, "table": "foo"}', ...],
("bar", ['{"c": 3, "d": 4, "table": "bar"}', ...]]
如何将此RDD分解为每个表键的数据帧
编辑:我试图在上面澄清,一个文件中有多行包含表的信息。我知道我可以在我创建的“groupBy”RDD上调用.collectAsMap,但我知道这将在我的驱动程序上消耗大量RAM。我的问题是:有没有一种方法可以在不使用.collectAsMap的情况下将“groupBy”RDD分解为多个数据帧?以下是步骤:
jsonRdd = sc.textFile(os.path.join("/path/to/data", "*")).map (.....)
tables = jsonRdd.map(<extract table name only from json object >).distinct().collect()
我不是python开发人员,所以精确的代码片段可能无法正常工作 您可以有效地将其拆分为拼花地板分区: 首先,我们将其转换为数据帧:
text\u rdd=sc.textFile(os.path.join(“/path/to/data”,“*”)
df=spark.read.json(text_rdd)
df.printSchema()
根
|--a:long(nullable=true)
|--b:long(nullable=true)
|--c:long(nullable=true)
|--d:long(nullable=true)
|--表:字符串(nullable=true)
现在我们可以写它了:
df.write.partitionBy('table').parquet([output directory name])
如果列出[output directory name]
的内容,您将看到与表的不同值一样多的分区:
hadoop fs-ls[输出目录名]
_成功
表=巴/
表=foo/
如果只想保留每个表的列,可以这样做(假设每当该表出现在文件中时都会出现完整的列列表)
导入ast
从pyspark.sql导入行
table_cols=spark.createDataFrame(text_rdd.map(lambda l:ast.literal_eval(l)).map(lambda l:Row(
table=l[“table”],
keys=已排序(l.keys())
))).distinct().toPandas()
表列=表列集合索引(“表”)
表[u cols.to[u dict()[“keys”]
{u'bar':[u'c',u'd',u'table'],u'foo':[u'a',u'b',u'table']}
tables = jsonRdd.map(<extract table name only from json object >).distinct().collect()
tablesRDD=[]
for table in tables:
# categorize each main rdd record based on table name.
# Compare each json object table element with for loop table string and on successful match return true.
output.append(jasonRdd.filter(lambda jsonObj: jsonObj['table'] == table))