Python 无法写入从两个压缩数据帧创建的PySpark数据帧
我试图遵循在没有共享连接键的情况下组合两个数据帧的方法(通过数据库表或数据帧中的“索引”组合,除了PySpark没有该概念外): 我的代码Python 无法写入从两个压缩数据帧创建的PySpark数据帧,python,dataframe,apache-spark,pyspark,Python,Dataframe,Apache Spark,Pyspark,我试图遵循在没有共享连接键的情况下组合两个数据帧的方法(通过数据库表或数据帧中的“索引”组合,除了PySpark没有该概念外): 我的代码 left_df=left_df.repartition(right_df.rdd.getNumPartitions())#FWIW,分区数=303 joined\u schema=StructType(左\u df.schema.fields+右\u df.schema.fields) middial_rdd=left_df.rdd.zip(right_df
left_df=left_df.repartition(right_df.rdd.getNumPartitions())#FWIW,分区数=303
joined\u schema=StructType(左\u df.schema.fields+右\u df.schema.fields)
middial_rdd=left_df.rdd.zip(right_df.rdd.map)(lambda x:x[0]+x[1])
full\u data=spark.createDataFrame(临时\u rdd,联接\u架构)
这一切似乎都很好。我正在使用DataBricks进行测试,我可以毫无问题地运行上面的“单元”。但当我去保存它时,我无法保存,因为它抱怨分区不匹配(???)。我已经确认分区的数量是匹配的,但是您也可以在上面看到,我明确地确保它们匹配。我的保存命令:
full\u data.write.parquet(my\u data\u path,mode=“overwrite”)
错误
我收到以下错误:
原因:org.apache.spark.SparkException:只能压缩每个分区中元素数相同的RDD
我猜
我怀疑问题在于,即使我匹配了分区的数量,但每个分区中的行数并不相同。但我不知道怎么做。我只知道如何指定分区的#,而不知道分区的方式
或者,更具体地说,如果没有可以使用的列,我不知道如何指定如何划分。记住,它们没有共享列
我怎么知道我可以这样组合它们,而不需要共享连接键?在这种情况下,这是因为我正在尝试,但实际上我有这种情况更普遍,在不仅仅是模型数据+预测的情况下 我的问题
- (我知道标准的回答是“你不应该……分区使索引变得毫无意义”,但在Spark创建不会像我在上面的链接中所描述的那样强制数据丢失的ML库之前,这始终是一个问题。)
RDD是老生常谈,但从这个角度回答了错误 来自拉筹伯大学的以下信息: 通过将任一分区的第i个分区与每个分区相结合来连接两个RDD 其他的。生成的RDD将由两个组件元组组成,其中 由提供的方法解释为键值对 PairRDDFunctions扩展 音符对。 这意味着您必须具有相同的分区器,每个分区的分区数和kv数相同,否则上述定义不成立 当从文件中读入时最好应用,因为重新分区(n)可能不会给出相同的分布 解决这个问题的一个小技巧是对k中的k,v使用zipWithIndex,就像这样(Scala不是pyspark的特定方面): 然后,重新分区(n)似乎可以工作,因为k是相同的类型
但每个分区必须有相同的num元素。它就是这样,但它是有意义的。您可以临时切换到RDD,并使用添加索引。然后可以将此索引用作连接标准:
#使用附加索引创建RDD
#当zipWithIndex将索引添加为第二列时,我们必须切换
#第一列和第二列
left=left_df.rdd.zipWithIndex().map(lambda a:(a[1],a[0]))
right=right_df.rdd.zipWithIndex().map(lambda a:(a[1],a[0]))
#加入两个RDD
连接=左。完全外部连接(右)
#恢复原始列
结果=spark.createDataFrame(连接)。选择(“\u 2.\u 1.*”,“\u 2.\u 2.*”)
Javadoc声明
某些RDD(如groupBy()返回的RDD)不能保证分区中元素的顺序
根据原始数据集的性质,此代码可能不会产生确定性结果。谢谢!这是有道理的,但我担心非决定论(按照我的回答,它将是确定性的。我实际上尝试了两者,但由于确定性,我把注意力集中在了@thebluephantom's上。但我无法让它发挥作用。请参阅我在他的评论中发布的错误。感谢所有的帮助!@MikeWilliamson确定性仍然基于行位置。我观察到zipWI分发给同一方将int重新分区为key、value对的key,并将传入的数据保留在相同的位置,因为这只是一个狭窄的转换。也就是说,分区中必须有相同的数字数据,否则就没有压缩RDD(而不是DF)的用例。你的数据集有多大?如果它们不是太大,一种低技术的方法是将它们写入csv文件并使用它们组合。它们很大,但不是太大,无法放入csv…只要我逐行读取它们,这听起来像是粘贴。但这似乎与使用Spark的目的背道而驰。我肯定会考虑它,如果没有更优美的东西。我不能让它工作。分区总是不匹配。最近的错误在几次试验之后:<代码>文件“/Dabrks/Spy/Python /pySc/SQL/Type。Py”,第1387行,在VeriffySytht“字段长度(%d)”%(LeN(Objo),LeN(VeriFor))中)ValueError:对象(2)的长度与字段(31)的长度不匹配
val rddA = sc.parallelize(Seq(
("ICCH 1", 10.0), ("ICCH 2", 10.0), ("ICCH 4", 100.0), ("ICCH 5", 100.0)
))
val rddAA = rddA.zipWithIndex().map(x => (x._2, x._1)).repartition(5)
val rddB = sc.parallelize(Seq(
(10.0, "A"), (64.0, "B"), (39.0, "A"), (9.0, "C"), (80.0, "D"), (89.0, "D")
))
val rddBB = rddA.zipWithIndex().map(x => (x._2, x._1)).repartition(5)
val zippedRDD = (rddAA zip rddBB).map{ case ((id, x), (y, c)) => (id, x, y, c) }
zippedRDD.collect