繁体   English   中英

Pyspark - 将rdd转换为dataframe时数据设置为null

[英]Pyspark - Data set to null when converting rdd to dataframe

使用PySpark我试图将嵌套dicts的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_codename已转换为null

任何人都可以帮助我吗? 我无法理解。

我正在使用Python 2.7和Spark 2.0.0

谢谢 !

发生这种情况是因为您没有正确使用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数据源会更有意义。

按照@ 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"}']

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM