将 Pandas 数据帧转换为 Spark 数据帧时,是否可以将 float 转换为 long?
When converting a Pandas dataframe into a Spark dataframe, is it possible to cast float into long?
我有以下两个场景共享的前奏代码:
from pyspark.sql import SparkSession
from pyspark.sql.types import *
import pyspark.sql.functions as F
import pandas as pd
import numpy as np
spark = SparkSession.builder.getOrCreate()
df = pd.DataFrame({"col1": [1, 2, 3], "col2": [22.0, 88.0, np.nan]})
现在,我想将 df
转换为 pyspark 数据帧 (sdf
)。当我尝试在创建 sdf
期间通过模式将 "col2"
隐式“投射”到 LongType
时,它失败了:
schema = StructType([StructField("col1", LongType()), StructField("col2", LongType())])
sdf = spark.createDataFrame(df[schema.fieldNames()], schema=schema)
错误:
TypeError: field col2: LongType can not accept object 22.0 in type
<class 'float'>
但是如果我 运行 下面的片段它工作得很好:
schema_2 = StructType(
[StructField("col1", LongType()), StructField("col2", FloatType())]
)
sdf = spark.createDataFrame(df[schema.fieldNames()], schema=schema_2)
cast_sdf = sdf.withColumn("col2", F.col("col2").cast(LongType()))
cast_sdf.show()
输出:
+----+----+
|col1|col2|
+----+----+
| 1| 22|
| 2| 88|
| 3| 0|
+----+----+
将我的评论转化为答案。
这实际上就是 Spark 使用模式的方式。它并不特定于将 pandas 数据帧转换为 pyspark 数据帧。将 createDataframe
方法与元组列表一起使用时,您会遇到相同的错误:
import numpy as np
schema = StructType([StructField("col1", LongType()), StructField("col2", LongType())])
df = spark.createDataFrame([(1, 22.0), (2, 88.0), (3, np.nan)], schema)
# TypeError: field col2: LongType can not accept object 22.0 in type <class 'float'>
当您传递架构时,这也是 CSV 等数据源的行为(尽管在读取 CSV 时它不会因模式 PERMISSIVE
而失败,但值加载为 null)。因为模式不会自动转换类型,它只是告诉 Spark 行中的每一列应该有哪种数据类型。
因此,当使用架构时,您必须传递与指定类型匹配的数据或使用不会失败的 StringType
,然后使用显式转换将您的列转换为所需的类型。
schema = StructType([StructField("col1", LongType()), StructField("col2", StringType())])
df = spark.createDataFrame([(1, 22.0), (2, 88.0), (3, np.nan)], schema)
df = df.withColumn("col2", F.col("col2").cast("long"))
df.show()
#+----+----+
#|col1|col2|
#+----+----+
#| 1| 22|
#| 2| 88|
#| 3|null|
#+----+----+
我有以下两个场景共享的前奏代码:
from pyspark.sql import SparkSession
from pyspark.sql.types import *
import pyspark.sql.functions as F
import pandas as pd
import numpy as np
spark = SparkSession.builder.getOrCreate()
df = pd.DataFrame({"col1": [1, 2, 3], "col2": [22.0, 88.0, np.nan]})
现在,我想将 df
转换为 pyspark 数据帧 (sdf
)。当我尝试在创建 sdf
期间通过模式将 "col2"
隐式“投射”到 LongType
时,它失败了:
schema = StructType([StructField("col1", LongType()), StructField("col2", LongType())])
sdf = spark.createDataFrame(df[schema.fieldNames()], schema=schema)
错误:
TypeError: field col2: LongType can not accept object 22.0 in type <class 'float'>
但是如果我 运行 下面的片段它工作得很好:
schema_2 = StructType(
[StructField("col1", LongType()), StructField("col2", FloatType())]
)
sdf = spark.createDataFrame(df[schema.fieldNames()], schema=schema_2)
cast_sdf = sdf.withColumn("col2", F.col("col2").cast(LongType()))
cast_sdf.show()
输出:
+----+----+
|col1|col2|
+----+----+
| 1| 22|
| 2| 88|
| 3| 0|
+----+----+
将我的评论转化为答案。
这实际上就是 Spark 使用模式的方式。它并不特定于将 pandas 数据帧转换为 pyspark 数据帧。将 createDataframe
方法与元组列表一起使用时,您会遇到相同的错误:
import numpy as np
schema = StructType([StructField("col1", LongType()), StructField("col2", LongType())])
df = spark.createDataFrame([(1, 22.0), (2, 88.0), (3, np.nan)], schema)
# TypeError: field col2: LongType can not accept object 22.0 in type <class 'float'>
当您传递架构时,这也是 CSV 等数据源的行为(尽管在读取 CSV 时它不会因模式 PERMISSIVE
而失败,但值加载为 null)。因为模式不会自动转换类型,它只是告诉 Spark 行中的每一列应该有哪种数据类型。
因此,当使用架构时,您必须传递与指定类型匹配的数据或使用不会失败的 StringType
,然后使用显式转换将您的列转换为所需的类型。
schema = StructType([StructField("col1", LongType()), StructField("col2", StringType())])
df = spark.createDataFrame([(1, 22.0), (2, 88.0), (3, np.nan)], schema)
df = df.withColumn("col2", F.col("col2").cast("long"))
df.show()
#+----+----+
#|col1|col2|
#+----+----+
#| 1| 22|
#| 2| 88|
#| 3|null|
#+----+----+