pyspark:TypeError:IntegerType不能接受类型<type'unicode'=“”>中的对象

时间:2015-10-14 15:47:17

标签: python apache-spark apache-spark-sql pyspark

使用Spark集群上的pyspark进行编程, 数据很大且分片,因此无法加载到内存中或轻松检查数据的完整性

基本上看起来像是

af.b Current%20events 1 996
af.b Kategorie:Musiek 1 4468
af.b Spesiaal:RecentChangesLinked/Gebruikerbespreking:Freakazoid 1 5209
af.b Spesiaal:RecentChangesLinked/Sir_Arthur_Conan_Doyle 1 5214

维基百科数据:

我从aws S3读取它,然后尝试在pyspark intepreter中使用以下python代码构造spark Dataframe:

parts = data.map(lambda l: l.split())
wikis = parts.map(lambda p: (p[0], p[1],p[2],p[3]))


fields = [StructField("project", StringType(), True),
StructField("title", StringType(), True),
StructField("count", IntegerType(), True),
StructField("byte_size", StringType(), True)] 

schema = StructType(fields) 

df = sqlContext.createDataFrame(wikis, schema)

一切都很好,只有createDataFrame给我错误

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/spark/python/pyspark/sql/context.py", line 404, in   createDataFrame
rdd, schema = self._createFromRDD(data, schema, samplingRatio)
File "/usr/lib/spark/python/pyspark/sql/context.py", line 298, in _createFromRDD
_verify_type(row, schema)
File "/usr/lib/spark/python/pyspark/sql/types.py", line 1152, in _verify_type
_verify_type(v, f.dataType)
File "/usr/lib/spark/python/pyspark/sql/types.py", line 1136, in _verify_type
raise TypeError("%s can not accept object in type %s" % (dataType, type(obj)))
TypeError: IntegerType can not accept object in type <type 'unicode'>

为什么我不能设置应该计入IntegerType的第三列? 我该如何解决这个问题?

2 个答案:

答案 0 :(得分:6)

ccheneson所述,您传递了错误的类型。

假设您data看起来像这样:

data = sc.parallelize(["af.b Current%20events 1 996"])

在第一张地图之后,您获得了RDD[List[String]]

parts = data.map(lambda l: l.split())
parts.first()
## ['af.b', 'Current%20events', '1', '996']

第二张地图将其转换为元组(String, String, String, String)

wikis = parts.map(lambda p: (p[0], p[1], p[2],p[3]))
wikis.first()
## ('af.b', 'Current%20events', '1', '996')

您的schema表示第3列是整数:

[f.dataType for f in schema.fields]
## [StringType, StringType, IntegerType, StringType]

Schema最常用于避免全表扫描以推断类型,并且不执行任何类型转换。

您可以在上一张地图中投射数据:

wikis = parts.map(lambda p: (p[0], p[1], int(p[2]), p[3]))

或者将count定义为StringType并投射列

fields[2] = StructField("count", StringType(), True)
schema = StructType(fields) 

wikis.toDF(schema).withColumn("cnt", col("count").cast("integer")).drop("count")

旁注count是SQL中的保留字,不应该用作列名。在Spark中,它会在某些情况下按预期工作,而在另一种情况下会失败。

答案 1 :(得分:1)

使用apache 2.0,您可以让spark推断出数据的架构。总的来说,你需要像上面提到的那样强制转换你的解析器函数:

“当schema为None时,它将尝试从数据中推断出架构(列名和类型),这应该是Row的RDD,或者是nametuple或dict。”