Apache spark 如何将PythonRDD(JSON中的行)转换为数据帧?
我试图读取多个JSON来创建一个数据帧 我将多个JSONs文件放在一个PythonRDD中,然后当我尝试转换为DataFrame时,它失败了。我使用方法Apache spark 如何将PythonRDD(JSON中的行)转换为数据帧?,apache-spark,pyspark,apache-spark-sql,Apache Spark,Pyspark,Apache Spark Sql,我试图读取多个JSON来创建一个数据帧 我将多个JSONs文件放在一个PythonRDD中,然后当我尝试转换为DataFrame时,它失败了。我使用方法toDF()或sqlContext.createDataFrame()得到以下错误: ValueError: Some of types cannot be determined by the first 100 rows, please try again with sampling 这很奇怪,因为使用sqlContext.read.json
toDF()
或sqlContext.createDataFrame()
得到以下错误:
ValueError: Some of types cannot be determined by the first 100 rows, please try again with sampling
这很奇怪,因为使用sqlContext.read.json()
这是我的密码:
import json
from pyspark.sql import Row
def dict_to_row(obj):
if isinstance(obj, dict) and len(obj.values())>0:
d = {}
for k in obj.keys():
d[k] = dict_to_row(obj[k])
return Row(**d)
elif isinstance(obj, list):
return [dict_to_row(o) for o in obj]
else:
return obj
def distributed_json_read(filename):
jsons = open(filename,'r')
json_list = jsons.readlines()
for e in json_list:
json_row = json.loads(e.rstrip())
yield dict_to_row(json_row)
json_list = ['test1.json','test2.json']
parallel_keys = sc.parallelize(json_list)
data_rdd = parallel_keys.flatMap(distributed_json_read)
df = sqlContext.createDataFrame(data_rdd)
下面是test1.json的一个示例:
{
"data": {
"f": {
"a": {
"a1": 100,
"a2": 1
},
"b": [
{
"b1": {
"b11": 1,
"b12": null
},
"date1": "2016-02-05T01:58:04.000-0400",
"b2": {
"b21": null,
"b22": "9ca6d130fddb",
"b23": false
}
}
]
}
},
"id": 1689
}
有人经历过这个错误吗
实际上,我的目标是读取多个JSONs文件,这些文件可以具有不同的模式,但最终构建一个数据框架,其模式将是JSONs模式的联合。与使用sqlContext.read.json()可以实现的类似,如果参数是一个包含多个json的文件。您可以为数据帧提供静态模式(所有类型的超集),或者为代码提供第一个json和所有字段,这将有助于拥有默认模式
一个问题当您没有默认模式并提供json(字段较少)时,以后读取带有新字段的新json文件时可能会出现问题。Spark中的json必须是一行,即单个json文件应该是一行
scala> final case class Token(id: Int, body: String)
defined class Token
scala> val df = spark.createDataset(Seq(Token(0, "hello"), Token(1, "world")))
df: org.apache.spark.sql.Dataset[Token] = [id: int, body: string]
scala> df.show
+---+-----+
| id| body|
+---+-----+
| 0|hello|
| 1|world|
+---+-----+
scala> df.write.json("so.json")
// $ cat so.json/part-r-00003-469964b4-aaf8-4c7a-8f8a-d76c08e792ce.json
// {"id":0,"body":"hello"}
我以前为spark编写过一个自定义json阅读器。我在包含json文件的文件夹中使用了sc.wholeTextFiles()或sc.binaryFiles()
这将为您提供一个rdd(k,v)(文件url,wholeFile/BinaryFile)
然后你可以在rdd上应用你的平面图
rdd=sc.wholeTextFiles(“包含JSON的超级文件夹”)
数据rdd=rdd.flatMap(分布式json读取)
df=sqlContext.createDataFrame(data_rdd)实际上json是一行,我只是简单地说了一下。我不确定你的解决方案是否有效,因为如果你在flatMap(例如)中使用一个函数,你就没有访问sc(SparkContext)的权限。是的,同意,你不需要在分布式json读取或dict to行中使用sc,使用这个解决方案。我事先就知道全局模式,但是当Spark试图构建最终的RDD时,如果两个或更多JSON没有相同的模式,似乎就会失败。我有点困惑。为什么要创建行而不是直接读取JSON?嗨@zero323我的最终目标是从不同的S3存储桶读取JSON。我想并行读取它们,这就是为什么我不能使用read.json()函数的原因