首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从RDD创建DataFrame,同时在模式中指定DateType()

从RDD创建DataFrame,同时在模式中指定DateType()
EN

Stack Overflow用户
提问于 2019-03-07 07:51:15
回答 1查看 6.2K关注 0票数 8

我正在从RDD创建一个DataFrame,其中一个值是date。我不知道如何在模式中指定DateType()

让我来说明一下眼前的问题-

date加载到DataFrame中的一种方法是首先将其指定为字符串并使用日期()函数将其转换为适当的date

代码语言:javascript
运行
复制
from pyspark.sql.types import Row, StructType, StructField, StringType, IntegerType, DateType
from pyspark.sql.functions import col, to_date
values=sc.parallelize([(3,'2012-02-02'),(5,'2018-08-08')])
rdd= values.map(lambda t: Row(A=t[0],date=t[1]))

# Importing date as String in Schema
schema = StructType([StructField('A', IntegerType(), True), StructField('date', StringType(), True)])
df = sqlContext.createDataFrame(rdd, schema)

# Finally converting the string into date using to_date() function.
df = df.withColumn('date',to_date(col('date'), 'yyyy-MM-dd'))
df.show()
+---+----------+
|  A|      date|
+---+----------+
|  3|2012-02-02|
|  5|2018-08-08|
+---+----------+

df.printSchema()
root
 |-- A: integer (nullable = true)
 |-- date: date (nullable = true)

有没有一种方法,我们可以在schema中使用schema,而不必显式地将string转换为date

就像这样-

代码语言:javascript
运行
复制
values=sc.parallelize([(3,'2012-02-02'),(5,'2018-08-08')])
rdd= values.map(lambda t: Row(A=t[0],date=t[1]))
# Somewhere we would need to specify date format 'yyyy-MM-dd' too, don't know where though.
schema = StructType([StructField('A', DateType(), True), StructField('date', DateType(), True)])

更新:@ code 10465355建议的,以下代码工作-

代码语言:javascript
运行
复制
import datetime
schema = StructType([
  StructField('A', IntegerType(), True),
  StructField('date', DateType(), True)
])
rdd= values.map(lambda t: Row(A=t[0],date=datetime.datetime.strptime(t[1], "%Y-%m-%d")))
df = sqlContext.createDataFrame(rdd, schema)
df.show()
+---+----------+
|  A|      date|
+---+----------+
|  3|2012-02-02|
|  5|2018-08-08|
+---+----------+
df.printSchema()
root
 |-- A: integer (nullable = true)
 |-- date: date (nullable = true)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-07 10:48:42

长话短说,与外部对象的RDD一起使用的模式并不打算以这样的方式使用--声明的类型应该反映数据的实际状态,而不是想要的状态。

换言之,允许:

代码语言:javascript
运行
复制
schema = StructType([
  StructField('A', IntegerType(), True),
  StructField('date', DateType(), True)
])

对应于date字段datetime.date的数据。例如,使用您的RDD[Tuple[int, str]]

代码语言:javascript
运行
复制
import datetime

spark.createDataFrame(
    # Since values from the question are just two element tuples
    # we can use mapValues to transform the "value"
    # but in general case you'll need map
    values.mapValues(datetime.date.fromisoformat),
    schema
)

最接近想要的行为是使用JSON读取器转换数据(RDD[Row]),使用dicts

代码语言:javascript
运行
复制
from pyspark.sql import Row

spark.read.schema(schema).json(rdd.map(Row.asDict))

或者更好的显式JSON转储:

代码语言:javascript
运行
复制
import json
spark.read.schema(schema).json(rdd.map(Row.asDict).map(json.dumps))

但是,这当然比显式铸造要昂贵得多,在简单的情况下,像您描述的那样,BTW很容易自动化:

代码语言:javascript
运行
复制
from pyspark.sql.functions import col

(spark
    .createDataFrame(values, ("a", "date"))
    .select([col(f.name).cast(f.dataType) for f in schema]))
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55038612

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档