假设我做的事情如下:
val df = sqlContext.load("com.databricks.spark.csv", Map("path" -> "cars.csv", "header" -> "true"))
df.printSchema()
root
|-- year: string (nullable = true)
|-- make: string (nullable = true)
|-- model: string (nullable = true)
|-- comment: string (nullable = true)
|-- blank: string (nullable = true)
df.show()
year make model comment blank
2012 Tesla S No comment
1997 Ford E350 Go get one now th...
但我真的希望 year
为 Int
(并且可能会转换其他一些列) .
我能想到的最好的是
df.withColumn("year2", 'year.cast("Int")).select('year2 as 'year, 'make, 'model, 'comment, 'blank)
org.apache.spark.sql.DataFrame = [year: int, make: string, model: string, comment: string, blank: string]
这有点令人费解 .
我来自R,而且我习惯于写作,例如
df2 <- df %>%
mutate(year = year %>% as.integer,
make = make %>% toupper)
我可能会遗漏一些东西,因为在spark / scala中应该有更好的方法来做到这一点......
16 回答
从Spark 1.4版开始,您可以在列上应用带有DataType的强制转换方法:
如果您使用的是sql表达式,您还可以:
有关更多信息,请查看文档:http://spark.apache.org/docs/1.6.0/api/scala/#org.apache.spark.sql.DataFrame
[编辑:2016年3月:感谢投票!虽然真的,这不是最好的答案,我认为msemelman,Martin Senne和其他人提出的基于
withColumn
,withColumnRenamed
和cast
的解决方案更简单,更清洁 .我认为你的方法还可以,回想一下Spark
DataFrame
是Rows的一个(不可变的)RDD,所以我们永远不会真正替换一个列,只是每次使用新模式创建新的DataFrame
.假设您有一个具有以下架构的原始df:
并且在一列或多列上定义了一些UDF:
更改列类型甚至从另一个构建新的DataFrame可以这样写:
产量:
这非常接近您自己的解决方案 . 简单地说,将类型更改和其他转换保持为单独的
udf val
s使代码更具可读性和可重用性 .由于
cast
操作可用于SparkColumn
(并且由于我个人不赞成@652832_此时提出的udf
),如何:转换为请求的类型?作为一个整洁的副作用,在这个意义上,不能施展的 Value 将变成
null
.如果您需要 a helper method ,请使用:
使用如下:
首先,如果你想要铸造类型
使用相同的列名称,该列将替换为新列,您无需添加和删除 .
第二,关于Scala vs R. Scala代码与R最相似,我可以实现:
虽然长度比R长一点 . 请注意,
mutate
是R数据帧的一个函数,因此Scala在不使用特殊函数的情况下表现出的功率非常好 .(
df.columns
令人惊讶的是一个Array [String]而不是Array [Column],也许他们希望它看起来像Python pandas的数据帧 . )您可以使用
selectExpr
使其更清洁:要将年份从字符串转换为int,您可以将以下选项添加到csv阅读器:"inferSchema" - > "true",请参阅DataBricks documentation
用于将DataFrame的数据类型从String修改为Integer的Java代码
它将简单地将现有(String数据类型)强制转换为Integer .
所以这只有在你将问题保存到像sqlserver这样的jdbc驱动程序时才能真正起作用,但它对于你将遇到语法和类型的错误非常有帮助 .
建议使用cast,FYI,spark 1.4.1中的cast方法的答案被打破了 .
例如,当转换为bigint时,具有值为“8182175552014127960”的字符串列的数据帧具有值“8182175552014128100”
在找到这个bug之前我们不得不面对很多问题,因为我们在 生产环境 中有bigint列 .
生成包含五个值的简单数据集,并将
int
转换为string
类型:此方法将删除旧列并创建具有相同值和新数据类型的新列 . 创建DataFrame时的原始数据类型是: -
在此之后,我运行以下代码来更改数据类型: -
在此之后我的结果出现了: -
您可以使用以下代码 .
将 year 列转换为
IntegerType
列 .可以通过在spark sql中使用强制转换来更改列的数据类型 . 表名是表,它有两列只有column1和column2,column1数据类型要更改 . ex-spark.sql(“select cast(column1 as Double)column1NewName,column2 from table”)在double中写入你的数据类型 .
其他方式: