我正在将CSV文件加载到DataFrame中,如下所示。
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
类型?
答案 0 :(得分:28)
鉴于val spark=SparkSession.builder().getOrCreate()
我猜测您正在使用Spark 2.x.
首先,请注意Spark 2.x具有CSV格式的原生支持,因此不需要通过其长名称指定格式,即org.apache.spark.csv
,而只需csv
。
spark.read.format("csv")...
由于您使用csv
运算符,因此隐含了CSV格式,因此您可以跳过/删除format("csv")
。
// note that I removed format("csv")
spark.read.option("header", true).csv("/home/cloudera/Book1.csv")
有了这个,你有很多选择,但我强烈建议使用一个案例类......只是架构。如果您对Spark 2.0中的操作方式感到好奇,请参阅最后的解决方案。
您可以使用cast运算符。
scala> Seq("1").toDF("str").withColumn("num", 'str cast "int").printSchema
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
您还可以使用自己手工制作的模式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)
我最近发现的很有趣的是所谓的 Schema DSL 。使用StructType
和StructField
构建的上述架构可以重写如下:
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)
答案 1 :(得分:20)
有inferSchema
选项可通过以下方式自动识别变量的类型:
val df=spark.read
.format("org.apache.spark.csv")
.option("header", true)
.option("inferSchema", true) // <-- HERE
.csv("/home/cloudera/Book1.csv")
spark-csv
最初是databricks的外部库,但包含在spark版本2.0之后的核心spark中。您可以参考图书馆github page上的文档来查找可用选项。
答案 2 :(得分:-2)
在这种情况下,您可以使用UDF:
第1步:创建一个将String转换为Int的udf。
val stringToIntUDF = udf((value:String)=>value.toInt)
第2步:将此UDF应用于要转换的列!
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")