TL; DR 现在最好的选择是完全跳过熊猫。
问题的根源是熊猫不如Spark SQL富有表现力。Spark提供
NULL(从SQL的意义上说是缺失值)和
NaN(数字不是数字)。
另一只手的熊猫没有可用于表示缺失值的本机值。因此,它使用占位符(例如
NaN/
NaT或)
Inf,这些占位符与Spark的实际区别不大
NaNs,
Infs并且转换规则取决于列类型。唯一的例外是
object可以包含
None值的列(通常是字符串)。您可以从文档中了解有关处理缺失值的更多信息。
例如,当转换为Spark数据帧时,熊猫中的NaN最终为字符串“ NaN”。
这实际上是不正确的。取决于输入列的类型。如果column显示
NaN它很可能不是数字值,则不是纯字符串:
from pyspark.sql.functions import isnan, isnullpdf = pd.Dataframe({ "x": [1, None], "y": [None, "foo"], "z": [pd.Timestamp("20120101"), pd.Timestamp("NaT")]})sdf = spark.createDataframe(pdf)sdf.show()+---+----+-------------------+| x| y| z|+---+----+-------------------+|1.0|null|2012-01-01 00:00:00||NaN| foo| null|+---+----+-------------------+sdf.select([ f(c) for c in sdf.columns for f in [isnan, isnull] if (f, c) != (isnan, "z") # isnan cannot be applied to timestamp ]).show()+--------+-----------+--------+-----------+-----------+|isnan(x)|(x IS NULL)|isnan(y)|(y IS NULL)|(z IS NULL)|+--------+-----------+--------+-----------+-----------+| false| false| false| true| false|| true| false| false| false| true|+--------+-----------+--------+-----------+-----------+实际上,并行化的本地集合(包括Pandas对象)在简单的测试和玩具示例之外的重要性可以忽略不计,因此您始终可以手动转换数据(跳过可能的Arrow优化):
import numpy as npspark.createDataframe([ tuple( None if isinstance(x, (float, int)) and np.isnan(x) else x for x in record.tolist()) for record in pdf.to_records(index=False)], pdf.columns.tolist()).show()+----+----+-------------------+| x| y| z|+----+----+-------------------+| 1.0|null|1325376000000000000||null| foo| null|+----+----+-------------------+
如果缺少/不是数字的歧义不是问题,那么只需照常加载数据并替换为Spark。
from pyspark.sql.functions import col, whensdf.select([ when(~isnan(c), col(c)).alias(c) if t in ("double", "float") else c for c, t in sdf.dtypes]).show()+----+----+-------------------+| x| y| z|+----+----+-------------------+| 1.0|null|2012-01-01 00:00:00||null| foo| null|+----+----+-------------------+


