Pyspark - 将rdd转换为数据框时数据设置为null
Posted
技术标签:
【中文标题】Pyspark - 将rdd转换为数据框时数据设置为null【英文标题】:Pyspark - Data set to null when converting rdd to dataframe 【发布时间】:2017-11-03 16:25:23 【问题描述】:使用 PySpark,我正在尝试将嵌套字典的 RDD 转换为数据框,但我在某些设置为 null 的字段中丢失了数据。
代码如下:
sc = SparkContext()
sqlContext = SQLContext(sc)
def convert_to_row(d):
return Row(**d)
df2 = sc.parallelize(["id": "14yy74hwogxoyl2l3v", "geoloc": "country": "geoname_id": 3017382, "iso_code": "FR", "name": "France"]).map(convert_to_row).toDF()
df2.printSchema()
df2.show()
df2.toJSON().saveAsTextFile("/tmp/json.test")
当我查看 /tmp/json.test 时,内容如下(手动缩进后):
"geoloc":
"country":
"name": null,
"iso_code": null,
"geoname_id": 3017382
,
"id": "14yy74hwogxoyl2l3v"
iso_code
和 name
已转换为 null
。
有人可以帮我吗?看不懂。
我正在使用 Python 2.7 和 Spark 2.0.0
谢谢!
【问题讨论】:
感谢您以严谨且可重复的方式提出您的第一个 SO 问题(不幸的是,对于新用户来说这很不寻常)。继续接受和支持好的答案(这会占用受访者的宝贵时间)... 【参考方案1】:按照@user6910411 已经提供的解释(并节省我自己做的时间),补救措施(即中间JSON 表示)是使用read.json
而不是toDF
和你的函数:
spark.version
# u'2.0.2'
jsonRDD = sc.parallelize(["id": "14yy74hwogxoyl2l3v", "geoloc": "country": "geoname_id": 3017382, "iso_code": "FR", "name": "France"])
df = spark.read.json(jsonRDD)
df.collect()
# result:
[Row(geoloc=Row(country=Row(geoname_id=3017382, iso_code=u'FR', name=u'France')), id=u'14yy74hwogxoyl2l3v')]
# just to have a look at what will be saved:
df.toJSON().collect()
# result:
[u'"geoloc":"country":"geoname_id":3017382,"iso_code":"FR","name":"France","id":"14yy74hwogxoyl2l3v"']
df.toJSON().saveAsTextFile("/tmp/json.test")
作为比较,这是您自己的 df2
的外观:
df2.collect()
# result:
[Row(geoloc=u'country': u'geoname_id': 3017382, u'iso_code': None, u'name': None, id=u'14yy74hwogxoyl2l3v')]
df2.toJSON().collect()
# result:
[u'"geoloc":"country":"name":null,"iso_code":null,"geoname_id":3017382,"id":"14yy74hwogxoyl2l3v"']
【讨论】:
【参考方案2】:发生这种情况是因为您没有正确使用Row
。 Row
构造函数不是递归的,只对***字段进行操作。当您查看架构时:
root
|-- geoloc: map (nullable = true)
| |-- key: string
| |-- value: map (valueContainsNull = true)
| | |-- key: string
| | |-- value: long (valueContainsNull = true)
|-- id: string (nullable = true)
您会看到geoloc
表示为map<string,struct<string,long>>
。结构的正确表示将使用嵌套的Rows
:
Row(
id="14yy74hwogxoyl2l3v",
geoloc=Row(
country=Row(geoname_id=3017382, iso_code="FR", name="France")))
而你传递的相当于:
Row(
geoloc='country':
'geoname_id': 3017382, 'iso_code': 'FR', 'name': 'France',
id='14yy74hwogxoyl2l3v')
由于创建正确的实现必须涵盖许多边界情况,因此使用中间 JSON 表示和 Spark JSON 数据源会更有意义。
【讨论】:
以上是关于Pyspark - 将rdd转换为数据框时数据设置为null的主要内容,如果未能解决你的问题,请参考以下文章