【问题标题】:List of dataframes to RDD in separate partition单独分区中到 RDD 的数据帧列表
【发布时间】:2018-06-27 14:30:38
【问题描述】:

我有一个 spark 数据帧列表,我必须对它们执行一些操作 我想从中创建一个 rdd,以便每个数据帧进入一个单独的分区,以便我可以简单地在这个 rdd 上使用 mapPartitions 在单独的节点上并行执行每个数据帧的计算。

【问题讨论】:

  • 每个数据框的架构是否相同,或者它们有不同的列?
  • @RyanWidmaier.. 所有数据帧的架构都相同。由于我要执行的计算涉及滚动计算,例如运行总和等,并且每个数据帧都是不同对象的数据,所以我不希望不同的数据帧位于同一分区中,因为滚动计算将被计算错误。

标签: apache-spark pyspark cluster-computing rdd partitioning


【解决方案1】:

以下是实现此目的的一些代码。一般的方法是将所有数据合并在一起,并添加一个source 列来标记每一行的来源。 union 调用不应该改变 DataFrames 的分区,只需将所有分区合并为一个 uber DataFrame。如果您确实有导致重新洗牌的东西,您可以使用 spark_partition_id() 添加具有原始分区 ID 的列,然后在 sourcepartition_id 列上调用 repartition

from pyspark.sql.functions import struct, lit, col

df1 = sc.parallelize([
    (1, 2, 3),
    (2, 3, 4)
]).toDF(["col1", "col2", "col3"])

df2 = sc.parallelize([
    (3, 4, 5),
    (4, 5, 6)
]).toDF(["col1", "col2", "col3"])

# Setup the DF's for union.  Their columns need to be in the same order and
# add a source column
df1_union = df1.select(lit("df1").alias("source"), *[col(c) for c in sorted(df1.columns)])
df2_union = df2.select(lit("df2").alias("source"), *[col(c) for c in sorted(df2.columns)])

# You could do this instead if the schemas are different
# df1_union = df1.select(lit("df1").alias("source"), struct(*df1.columns).alias("df1"), lit(None).alias("df2"))
# df2_union = df2.select(lit("df2").alias("source"), lit(None).alias("df1"), struct(*df2.columns).alias("df2"))

combined = df1_union.unionAll(df2_union) 

combined.show()
combined.rdd.mapPartitions(lambda row: do whatever..)

注意,合并后的数据如下:

+------+----+----+----+
|source|col1|col2|col3|
+------+----+----+----+
|   df1|   1|   2|   3|
|   df1|   2|   3|   4|
|   df2|   3|   4|   5|
|   df2|   4|   5|   6|
+------+----+----+----+

【讨论】:

  • 感谢您的回答。在这种情况下,分区会根据源列发生吗?我的意思是同一源的所有数据都会进入同一个分区吗?我想对来自每个源的数据执行运行总和,因此不能在同一分区中有不同的源数据。非常感谢您的帮助...非常感谢...
  • 在上面的例子中不会发生随机播放。 Union 只是将列出的 DataFrame 中的所有原始分区放入一个 DF 中,而不移动任何行。您可以运行 combine.explain() 来查看。换句话说,如果您有带有分区 A 和 B 的 DF1,而带有分区 C 和 D 的 DF2,则组合起来将有分区 A、B、C 和 D
  • 单个数据帧没有任何分区。我只是从镶木地板文件中读取它们。这是否意味着每个单独的数据帧都将使用 UnionAll 进入单独的分区?对不起,我是新来的火花。非常感谢..
  • 这个分区有点令人困惑,有时意味着输入拆分(一些记录数),有时它是按值划分的数据切片(即按月分区)。在这种情况下,我说的是前者。 parquet reader 将加载您的数据,将记录划分为输入拆分,以便可以并行处理它们。如果你执行 df.rdd.getNumPartitions() 你可以看到它创建了多少个分区。或者,您可以查看 Spark UI 中的任务数。
  • 我检查了我的输入数据帧及其 1 上的分区。UnionAll 有效,最终 rdd 有两个分区(每个数据帧一个)。但是,有些输入数据帧有 2 个分区。我也想将它们移至 1,以便最终 rdd 的分区数与数据帧数一样多?另外,从mapPartitions操作后生成的rdd,我如何将每个输入数据帧对应的输出拆分为单独的输出数据帧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
  • 1970-01-01
  • 2021-02-10
  • 1970-01-01
  • 2018-04-13
  • 1970-01-01
相关资源
最近更新 更多