136

I have a dataframe with column as String. I wanted to change the column type to Double type in PySpark.

Following is the way, I did:

toDoublefunc = UserDefinedFunction(lambda x: x,DoubleType())
changedTypedf = joindf.withColumn("label",toDoublefunc(joindf['show']))

Just wanted to know, is this the right way to do it as while running through Logistic Regression, I am getting some error, so I wonder, is this the reason for the trouble.

ZygD
  • 10,844
  • 36
  • 65
  • 84
Abhishek Choudhary
  • 7,985
  • 18
  • 66
  • 123

5 Answers5

239

There is no need for an UDF here. Column already provides cast method with DataType instance :

from pyspark.sql.types import DoubleType

changedTypedf = joindf.withColumn("label", joindf["show"].cast(DoubleType()))

or short string:

changedTypedf = joindf.withColumn("label", joindf["show"].cast("double"))

where canonical string names (other variations can be supported as well) correspond to simpleString value. So for atomic types:

from pyspark.sql import types 

for t in ['BinaryType', 'BooleanType', 'ByteType', 'DateType', 
          'DecimalType', 'DoubleType', 'FloatType', 'IntegerType', 
           'LongType', 'ShortType', 'StringType', 'TimestampType']:
    print(f"{t}: {getattr(types, t)().simpleString()}")
BinaryType: binary
BooleanType: boolean
ByteType: tinyint
DateType: date
DecimalType: decimal(10,0)
DoubleType: double
FloatType: float
IntegerType: int
LongType: bigint
ShortType: smallint
StringType: string
TimestampType: timestamp

and for example complex types

types.ArrayType(types.IntegerType()).simpleString()   
'array<int>'
types.MapType(types.StringType(), types.IntegerType()).simpleString()
'map<string,int>'
10465355
  • 4,499
  • 2
  • 16
  • 39
zero323
  • 305,283
  • 89
  • 921
  • 912
  • 6
    Using the `col` function also works. `from pyspark.sql.functions import col`, `changedTypedf = joindf.withColumn("label", col("show").cast(DoubleType())) ` – Staza Apr 03 '18 at 22:38
  • What are the possible values of cast() argument (the "string" syntax)? – Wirawan Purwanto Nov 28 '18 at 01:56
  • I can't believe how terse Spark doc was on the valid string for the datatype. The closest reference I could find was this: https://docs.tibco.com/pub/sfire-analyst/7.7.1/doc/html/en-US/TIB_sfire-analyst_UsersGuide/connectors/apache-spark/apache_spark_data_types.htm . – Wirawan Purwanto Nov 28 '18 at 02:07
  • 1
    How to convert multiple columns in one go? – hui chen Dec 30 '19 at 14:38
  • How do I change nullable to false? – pitchblack408 Jun 27 '20 at 01:59
70

Preserve the name of the column and avoid extra column addition by using the same name as input column:

from pyspark.sql.types import DoubleType
changedTypedf = joindf.withColumn("show", joindf["show"].cast(DoubleType()))
ZygD
  • 10,844
  • 36
  • 65
  • 84
Duckling
  • 821
  • 7
  • 12
14

Given answers are enough to deal with the problem but I want to share another way which may be introduced the new version of Spark (I am not sure about it) so given answer didn't catch it.

We can reach the column in spark statement with col("colum_name") keyword:

from pyspark.sql.functions import col
changedTypedf = joindf.withColumn("show", col("show").cast("double"))
ZygD
  • 10,844
  • 36
  • 65
  • 84
serkan kucukbay
  • 593
  • 6
  • 15
  • Thank you! Using `'double'` is more elegant than `DoubleType()` which may also need to be imported. – ZygD Sep 30 '21 at 15:02
6

PySpark version:

df = <source data>
df.printSchema()

from pyspark.sql.types import *

# Change column type
df_new = df.withColumn("myColumn", df["myColumn"].cast(IntegerType()))
df_new.printSchema()
df_new.select("myColumn").show()
ZygD
  • 10,844
  • 36
  • 65
  • 84
Cristian
  • 500
  • 6
  • 7
1

the solution was simple -

toDoublefunc = UserDefinedFunction(lambda x: float(x),DoubleType())
changedTypedf = joindf.withColumn("label",toDoublefunc(joindf['show']))
Abhishek Choudhary
  • 7,985
  • 18
  • 66
  • 123