Python Pyspark.toPandas()将在对象列中生成所需的数字列
我从数据仓库中提取数据,将其存储在拼花文件中,并将所有拼花文件加载到spark数据框中。 到现在为止,一直都还不错。但是,当我尝试使用pandas.plot()函数打印时,它会抛出一个“TypeError:Empty'DataFrame”:没有要打印的数字数据” 所以我开始追溯到我的源代码,我认为从我的初始sql语句转换为十进制是问题之一。但我不知道如何解决这个问题。我原以为一个fillna(0)就可以了,但事实并非如此 步骤1:定义SQL语句以提取数据Python Pyspark.toPandas()将在对象列中生成所需的数字列,python,pandas,apache-spark,parquet,Python,Pandas,Apache Spark,Parquet,我从数据仓库中提取数据,将其存储在拼花文件中,并将所有拼花文件加载到spark数据框中。 到现在为止,一直都还不错。但是,当我尝试使用pandas.plot()函数打印时,它会抛出一个“TypeError:Empty'DataFrame”:没有要打印的数字数据” 所以我开始追溯到我的源代码,我认为从我的初始sql语句转换为十进制是问题之一。但我不知道如何解决这个问题。我原以为一个fillna(0)就可以了,但事实并非如此 步骤1:定义SQL语句以提取数据 mpr_sql = """ select
mpr_sql = """
select
CAST(DATE_KEY AS INTEGER) AS DATE_KEY ,
CAST(AMD AS INTEGER) AS AMD ,
CAST(AMD_2 AS DECIMAL(12,2)) AS AMD_2 ,
CAST(AMD_3 AS DECIMAL(12,2)) AS AMD_3 ,
CAST(AMD_4 AS DECIMAL(12,2)) AS AMD_4 ,
CAST(AMD_0 AS DECIMAL(12,2)) AS AMD_0
"""
df1 = sqlContext.load(source="jdbc",
driver="com.teradata.jdbc.TeraDriver",
url=db_url,
user=db_user
TMODE="TERA",
password=db_pwd,
dbtable="( "+sql+") a")
步骤2:从提取的数据创建spark数据帧
mpr_sql = """
select
CAST(DATE_KEY AS INTEGER) AS DATE_KEY ,
CAST(AMD AS INTEGER) AS AMD ,
CAST(AMD_2 AS DECIMAL(12,2)) AS AMD_2 ,
CAST(AMD_3 AS DECIMAL(12,2)) AS AMD_3 ,
CAST(AMD_4 AS DECIMAL(12,2)) AS AMD_4 ,
CAST(AMD_0 AS DECIMAL(12,2)) AS AMD_0
"""
df1 = sqlContext.load(source="jdbc",
driver="com.teradata.jdbc.TeraDriver",
url=db_url,
user=db_user
TMODE="TERA",
password=db_pwd,
dbtable="( "+sql+") a")
步骤3:将spark数据框存储在一个有10个分区的拼花地板文件中
df1.coalesce(10).write.parquet("./mpr"+month+"sorted.parquet")
df = sqlContext.read.parquet('./mpr*sorted.parquet')
步骤4:查看spark数据帧模式(它显示十进制(12,2))
步骤5:将spark数据帧转换为pandas数据帧,并将任何空值替换为0(使用fillna(0))
步骤6:查看相关列的数据帧信息。AMD是正确的(整数),但AMD_4是object类型,我希望它是double或float之类的(抱歉,总是忘记正确的类型)。由于AMD_4是一种非数字类型,我不能用它来打印。
pdf[['AMD','AMD4']].info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 20 entries, 20140101 to 20150801
Data columns (total 2 columns):
AMD 20 non-null int64
AMD_4 20 non-null object
dtypes: int64(1), object(1)
memory usage: 480.0+ bytes
pdf['AMD','AMD4']].info()
INT64索引:20个条目,20140101至20150801
数据列(共2列):
AMD 20非空int64
AMD_4 20非空对象
数据类型:int64(1),对象(1)
内存使用:480.0+字节
所以我的问题是:
首先检查pdf.isnull().sum():
1.应该都是零。出于某种原因,如果某个列计数返回na或nan,则始终可以使用pandas
fillna()
pdf = df.fillna(0).toPandas()
pdf = pdf.fillna(0)
或
2.如果全部为零,则检查类型不匹配的位置
pdf.applymap(lambda x: isinstance(x, (int, float)))
纠正它我也有同样的问题,然后我找出了原因 在转换过程中,会合并数据类型,例如int/long->int64、double->float64、string->obj。对于所有未知数据类型,它将转换为obj类型 在熊猫数据帧中,没有十进制数据类型,因此十进制数据类型的所有列都转换为obj类型 如果在应用toPandas()之前可以将所有十进制数据类型转换为双精度类型,则所有数字数据都可以使用
from pyspark.sql.functions import *
from pyspark.sql.types import *
df = df.withColumn('AMD_4', col('AMD_4').cast(DoubleType())).withColumn('AMD_2', col('AMD_2').cast(DoubleType()))
pdf = df.toPandas()
在pdf中,AMD_4和AMD_2现在将是数字的 损坏的列的类型为decimal.decimal。。我可以使用pdf.applymap(lambda x:float(x)if(isinstance(x,(Decimal)))else x)来更改它。然而,我仍然不明白为什么spark dataframe会导致decimal.decimal类的对象,并且不能直接使用。关于如何解决这个问题,我应该在提取SQL中进行不同的初始转换吗?因为这仍然是我在做所有摘录之前修复它的时间。我对spark不太熟悉,尽管它很奇怪,因为只有一个专栏有这个问题。
from pyspark.sql.functions import *
from pyspark.sql.types import *
df = df.withColumn('AMD_4', col('AMD_4').cast(DoubleType())).withColumn('AMD_2', col('AMD_2').cast(DoubleType()))
pdf = df.toPandas()