我有多个键/值对的数据/行,其中键的数量未知-我想从中创建一个Spark DataFrame,其中有些重叠,有些则没有。我的最终目标是从此DataFrame中写入CSV。
我对输入数据/行具有灵活性:最容易使用的是JSON字符串,但可以通过可能重叠的键进行转换:
{"color":"red", "animal":"fish"}
{"color":"green", "animal":"panda"}
{"color":"red", "animal":"panda", "fruit":"watermelon"}
{"animal":"aardvark"}
{"color":"blue", "fruit":"apple"}
理想情况下,我想根据此数据创建一个看起来像这样的DataFrame:
-----------------------------
color | animal | fruit
-----------------------------
red | fish | null
green | panda | null
red | panda | watermelon
null | aardvark | null
blue | null | apple
-----------------------------
值得注意的是,没有特定键的数据/行是null
,并且数据/行中的所有键都表示为列。
我对许多Spark基础知识感到比较满意,但是在设想一个流程以有效地将我的RDD / DataFrame与键/值对结合使用时遇到了麻烦– 但列和键的数量未知 -并使用这些键作为列创建一个DataFrame。
高效,因为如果可能的话,我想避免创建一个将所有输入行都保存在内存中的对象(例如,单个字典)。
再一次,编写CSV的最终目标是实现这一目标的合理步骤。
某些数据将是多值的,例如:
{"color":"pink", "animal":["fish","mustang"]}
{"color":["orange","purple"], "animal":"panda"}
使用提供的定界符,例如/
为避免与,
冲突以分隔列,我想在列的输出中对它们进行分隔,例如:
------------------------------------
color | animal | fruit
------------------------------------
pink | fish/mustang | null
orange/purple | panda | null
------------------------------------
一旦有解决主要问题的方法,我相信我可以解决这一问题,但是无论如何都将其丢掉,因为这将成为问题的一个方面。
答案 0 :(得分:2)
如果您的数据存储在文件中(假设它名为myfile.json
),如下所示:
{"color":"red", "animal":"fish"}
{"color":"green", "animal":"panda"}
{"color":"red", "animal":"panda", "fruit":"watermelon"}
{"animal":"aardvark"}
{"color":"blue", "fruit":"apple"}
{"color":"pink", "animal":["fish","mustang"]}
{"color":["orange","purple"], "animal":"panda"}
您可以使用pyspark.sql.DataFrameReader.json
以换行符分隔的JSON记录的形式读取文件。
df = spark.read.json("myfile.json")
df.show()
#+------------------+-------------------+----------+
#| animal| color| fruit|
#+------------------+-------------------+----------+
#| fish| red| null|
#| panda| green| null|
#| panda| red|watermelon|
#| aardvark| null| null|
#| null| blue| apple|
#|["fish","mustang"]| pink| null|
#| panda|["orange","purple"]| null|
#+------------------+-------------------+----------+
df.printSchema()
#root
# |-- animal: string (nullable = true)
# |-- color: string (nullable = true)
# |-- fruit: string (nullable = true)
您也可以从rdd
中读取内容:
import json
rdd = sc.parallelize(
map(
json.dumps,
[
{"color":"red", "animal":"fish"},
{"color":"green", "animal":"panda"},
{"color":"red", "animal":"panda", "fruit":"watermelon"},
{"animal":"aardvark"},
{"color":"blue", "fruit":"apple"},
{"color":"pink", "animal":["fish","mustang"]},
{"color":["orange","purple"], "animal":"panda"}
]
)
)
df = spark.read.json(rdd)
第二部分,您可以根据需要使用pyspark.sql.functions.regexp_replace
格式化多值记录。
from pyspark.sql.functions import regexp_replace
def format_column(column):
return regexp_replace(regexp_replace(column, '(^\[)|(\]$)|(")', ''), ",", "/")
df.select(*[format_column(c).alias(c) for c in df.columns]).show()
#+------------+-------------+----------+
#| animal| color| fruit|
#+------------+-------------+----------+
#| fish| red| null|
#| panda| green| null|
#| panda| red|watermelon|
#| aardvark| null| null|
#| null| blue| apple|
#|fish/mustang| pink| null|
#| panda|orange/purple| null|
#+------------+-------------+----------+