如何在不使用Scala case类的情况下为CSV文件指定模式?
我正在将CSV文件加载到数据框中,如下所示如何在不使用Scala case类的情况下为CSV文件指定模式?,scala,apache-spark,apache-spark-sql,Scala,Apache Spark,Apache Spark Sql,我正在将CSV文件加载到数据框中,如下所示 val conf=new SparkConf().setAppName("dataframes").setMaster("local") val sc=new SparkContext(conf) val spark=SparkSession.builder().getOrCreate() import spark.implicits._ val df = spark. read. format("org.apache.spark.csv
val conf=new SparkConf().setAppName("dataframes").setMaster("local")
val sc=new SparkContext(conf)
val spark=SparkSession.builder().getOrCreate()
import spark.implicits._
val df = spark.
read.
format("org.apache.spark.csv").
option("header", true).
csv("/home/cloudera/Book1.csv")
scala> df.printSchema()
root
|-- name: string (nullable = true)
|-- address: string (nullable = true)
|-- age: string (nullable = true)
如何将
age
列更改为Int
类型?在这种情况下,您可以使用自定义项:
步骤1:创建一个将字符串转换为Int的自定义项
val stringToIntUDF = udf((value:String)=>value.toInt)
步骤2:将此自定义项应用于要转换的列
val updatedDF = df.withColumns("age",stringToIntUDF(df("age")))
updatedDF.printSchema
这会给你你想要的结果
如果您只是想从CSV文件推断您的模式。那么@vdep解决方案似乎是在做正确的事情
val df=spark.read
.format("org.apache.spark.csv")
.option("header",true)
.option("inferSchema", "true") // <-- HERE
.csv("/home/cloudera/Book1.csv")
val df=spark.read
.format(“org.apache.spark.csv”)
.选项(“标题”,真)
.option(“inferSchema”,“true”)/有inferSchema
选项可通过以下方式自动识别变量类型:
val df=spark.read
.format("org.apache.spark.csv")
.option("header", true)
.option("inferSchema", true) // <-- HERE
.csv("/home/cloudera/Book1.csv")
val df=spark.read
.format(“org.apache.spark.csv”)
.选项(“标题”,真)
.option(“inferSchema”,true)/给定val spark=SparkSession.builder().getOrCreate()
我猜您使用的是spark 2.x
首先,请注意Spark 2.x本机支持CSV格式,因此不需要通过其长名称指定格式,即org.apache.Spark.CSV
,而只需CSV
spark.read.format("csv")...
// note that I removed format("csv")
spark.read.option("header", true).csv("/home/cloudera/Book1.csv")
由于您使用了csv
运算符,因此csv格式是隐含的,因此您可以跳过/删除格式(“csv”)
有了它,您就有了很多选择,但我强烈建议使用case类来处理模式。如果您想知道如何在Spark 2.0中实现,请参阅最后一个解决方案
铸造操作工
你可以用接线员
scala> Seq("1").toDF("str").withColumn("num", 'str cast "int").printSchema
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
使用StructType
您还可以使用自己手工制作的模式,如下所示:
import org.apache.spark.sql.types._
val schema = StructType(
StructField("str", StringType, true) ::
StructField("num", IntegerType, true) :: Nil)
scala> schema.printTreeString
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
val q = spark.
read.
option("header", true).
schema(schema).
csv("numbers.csv")
scala> q.printSchema
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
import org.apache.spark.sql.types._
val schema = StructType(
$"str".string ::
$"num".int :: Nil)
scala> schema.printTreeString
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
// or even
val schema = new StructType().
add($"str".string).
add($"num".int)
scala> schema.printTreeString
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
模式DSL
最近我发现非常有趣的是所谓的模式DSL。使用StructType
和StructField
构建的上述架构可以按如下方式重新编写:
import org.apache.spark.sql.types._
val schema = StructType(
StructField("str", StringType, true) ::
StructField("num", IntegerType, true) :: Nil)
scala> schema.printTreeString
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
val q = spark.
read.
option("header", true).
schema(schema).
csv("numbers.csv")
scala> q.printSchema
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
import org.apache.spark.sql.types._
val schema = StructType(
$"str".string ::
$"num".int :: Nil)
scala> schema.printTreeString
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
// or even
val schema = new StructType().
add($"str".string).
add($"num".int)
scala> schema.printTreeString
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
编码器
编码器非常容易使用,以至于很难相信您不需要它们,即使只是构建模式而不处理StructType
、StructField
和DataType
// Define a business object that describes your dataset
case class MyRecord(str: String, num: Int)
// Use Encoders object to create a schema off the business object
import org.apache.spark.sql.Encoders
val schema = Encoders.product[MyRecord].schema
scala> schema.printTreeString
root
|-- str: string (nullable = true)
|-- num: integer (nullable = false)
很抱歉,我无法正确理解这个问题,我以为您只是想将年龄从字符串更改为Int,因此提供了此解决方案!