Python 无法写入从两个压缩数据帧创建的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

我试图遵循在没有共享连接键的情况下组合两个数据帧的方法(通过数据库表或数据帧中的“索引”组合,除了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.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