Apache spark Pyspark:按布尔列对连续行进行分组

Apache spark Pyspark:按布尔列对连续行进行分组,apache-spark,pyspark,apache-spark-sql,Apache Spark,Pyspark,Apache Spark Sql,我在Python中有一个Spark数据帧,它按照特定的顺序将行划分为正确的组,根据“start\u of_section”列,该列的值为1或0。对于需要分组在一起的每一行集合,除“value”和“start\u of_section”之外的每一列都是相等的。我想将每一个这样的集合分组到一行中,该行的每一列的值都相同,另一列“list_values”的每一行中都有一个值数组 因此,某些行可能如下所示: Row(category=fruit, object=apple, value=60, star

我在Python中有一个Spark数据帧,它按照特定的顺序将行划分为正确的组,根据“start\u of_section”列,该列的值为1或0。对于需要分组在一起的每一行集合,除“value”和“start\u of_section”之外的每一列都是相等的。我想将每一个这样的集合分组到一行中,该行的每一列的值都相同,另一列“list_values”的每一行中都有一个值数组

因此,某些行可能如下所示:

Row(category=fruit, object=apple, value=60, start_of_section=1)
Row(category=fruit, object=apple, value=160, start_of_section=0)
Row(category=fruit, object=apple, value=30, start_of_section=0)
在新的数据框架中,这将是

Row(category=fruit, object=apple, list_values=[60, 160, 30])
(编辑:请注意,最后的数据框中不应包含“开始\u部分”列。)

我在尝试研究答案时遇到的问题是,我只找到了按列值分组的方法,而不考虑排序,这样会错误地生成两行,一行将所有行分组为“start\u of_section”=1,另一行将所有行分组为“start\u of_section”=0


什么代码可以实现这一点?

好吧,现在我明白了。您可以通过对部分的开始部分求和的列进行分组

为了确定结果,您应该包括ordering列

from pyspark.sql.types import Row
from pyspark.sql.functions import *
from pyspark.sql import Window

data = [Row(category='fruit', object='apple', value=60, start_of_section=1),
    Row(category='fruit', object='apple', value=160, start_of_section=0),
    Row(category='fruit', object='apple', value=30, start_of_section=0),
    Row(category='fruit', object='apple', value=50, start_of_section=1),
    Row(category='fruit', object='apple', value=30, start_of_section=0),
    Row(category='fruit', object='apple', value=60, start_of_section=1),
    Row(category='fruit', object='apple', value=110, start_of_section=0)]

df = spark.createDataFrame(data)

w = Window.partitionBy('category', 'object').rowsBetween(Window.unboundedPreceding, Window.currentRow)

df.withColumn('group', sum('start_of_section').over(w)) \
  .groupBy('category', 'object', 'group').agg(collect_list('value').alias('list_value')) \
  .drop('group').show()

+--------+------+-------------+
|category|object|   list_value|
+--------+------+-------------+
|   fruit| apple|[60, 160, 30]|
|   fruit| apple|     [50, 30]|
|   fruit| apple|    [60, 110]|
+--------+------+-------------+

失败:
当您有多个分区时,单调递增的\u id
会失败

df.repartition(7) \
  .withColumn('id', monotonically_increasing_id()) \
  .withColumn('group', sum('start_of_section').over(w)) \
  .groupBy('category', 'object', 'group').agg(collect_list('value').alias('list_value')) \
  .drop('group').show()

+--------+------+--------------------+
|category|object|          list_value|
+--------+------+--------------------+
|   fruit| apple|                [60]|
|   fruit| apple|[60, 160, 30, 30,...|
|   fruit| apple|                [50]|
+--------+------+--------------------+

这完全不是我想要的。

好吧,现在我拿到了。您可以通过对部分的开始部分求和的列进行分组

为了确定结果,您应该包括ordering列

from pyspark.sql.types import Row
from pyspark.sql.functions import *
from pyspark.sql import Window

data = [Row(category='fruit', object='apple', value=60, start_of_section=1),
    Row(category='fruit', object='apple', value=160, start_of_section=0),
    Row(category='fruit', object='apple', value=30, start_of_section=0),
    Row(category='fruit', object='apple', value=50, start_of_section=1),
    Row(category='fruit', object='apple', value=30, start_of_section=0),
    Row(category='fruit', object='apple', value=60, start_of_section=1),
    Row(category='fruit', object='apple', value=110, start_of_section=0)]

df = spark.createDataFrame(data)

w = Window.partitionBy('category', 'object').rowsBetween(Window.unboundedPreceding, Window.currentRow)

df.withColumn('group', sum('start_of_section').over(w)) \
  .groupBy('category', 'object', 'group').agg(collect_list('value').alias('list_value')) \
  .drop('group').show()

+--------+------+-------------+
|category|object|   list_value|
+--------+------+-------------+
|   fruit| apple|[60, 160, 30]|
|   fruit| apple|     [50, 30]|
|   fruit| apple|    [60, 110]|
+--------+------+-------------+

失败:
当您有多个分区时,单调递增的\u id
会失败

df.repartition(7) \
  .withColumn('id', monotonically_increasing_id()) \
  .withColumn('group', sum('start_of_section').over(w)) \
  .groupBy('category', 'object', 'group').agg(collect_list('value').alias('list_value')) \
  .drop('group').show()

+--------+------+--------------------+
|category|object|          list_value|
+--------+------+--------------------+
|   fruit| apple|                [60]|
|   fruit| apple|[60, 160, 30, 30,...|
|   fruit| apple|                [50]|
+--------+------+--------------------+

这是完全不需要的。

假设您的订单列是
order\u col

df.show()
+--------+------+---------+----------------+-----+
|类别|对象|顺序|列|开始|节|值|
+--------+------+---------+----------------+-----+
|水果|苹果| 1 | 1 | 60|
|水果|苹果| 2 | 0 | 160|
|水果|苹果| 3 | 0 | 30|
|水果|苹果| 4 | 1 | 50|
+--------+------+---------+----------------+-----+
您需要生成一个id以将同一节中的行分组在一起,然后根据此id和所需的尺寸进行分组。这是你怎么做的

从pyspark.sql导入函数为F,窗口为W
df.withColumn(
“身份证”,
F.sum(“起始部分”)。结束(
W.partitionBy(“类别”、“对象”)。orderBy(“订单”)
),
).groupBy(“类别”、“对象”、“id”).agg(F.collect_列表(“值”).alias(“值”)).drop(
“id”
).show()
+--------+------+-------------+
|类别|对象|值|
+--------+------+-------------+
|水果|苹果|[60,160,30]|
|水果|苹果|[50]|
+--------+------+-------------+


编辑:如果您没有任何订单,这是一项不可能完成的任务。将数据框中的行视为包中的大理石。他们没有任何订单。您可以根据一些标准在将它们从袋子中取出时订购,但在其他情况下,您不能接受任何订单<代码>表演就是你从袋子里拿出10个弹珠(线)。每次您这样做时,顺序可能是相同的,但会突然改变,并且您无法控制它

假设您的订单列是
order\u col

df.show()
+--------+------+---------+----------------+-----+
|类别|对象|顺序|列|开始|节|值|
+--------+------+---------+----------------+-----+
|水果|苹果| 1 | 1 | 60|
|水果|苹果| 2 | 0 | 160|
|水果|苹果| 3 | 0 | 30|
|水果|苹果| 4 | 1 | 50|
+--------+------+---------+----------------+-----+
您需要生成一个id以将同一节中的行分组在一起,然后根据此id和所需的尺寸进行分组。这是你怎么做的

从pyspark.sql导入函数为F,窗口为W
df.withColumn(
“身份证”,
F.sum(“起始部分”)。结束(
W.partitionBy(“类别”、“对象”)。orderBy(“订单”)
),
).groupBy(“类别”、“对象”、“id”).agg(F.collect_列表(“值”).alias(“值”)).drop(
“id”
).show()
+--------+------+-------------+
|类别|对象|值|
+--------+------+-------------+
|水果|苹果|[60,160,30]|
|水果|苹果|[50]|
+--------+------+-------------+


编辑:如果您没有任何订单,这是一项不可能完成的任务。将数据框中的行视为包中的大理石。他们没有任何订单。您可以根据一些标准在将它们从袋子中取出时订购,但在其他情况下,您不能接受任何订单<代码>表演就是你从袋子里拿出10个弹珠(线)。每次你这样做时,顺序可能是相同的,但突然改变,你无法控制它

你如何定义顺序?您需要一个“订单”列,它使用我在使用“show”时看到的订单是否足够?否则,我可以根据数据帧中的当前位置创建一个带有递增计数器的新列吗?请提供您的订单列。我们需要它来定义这个部分什么时候开始。拉马努斯和我都给出了相同的答案。只要确保你有一个“订单”栏,它应该会工作。否则,你就完了。你如何定义顺序?您需要一个“订单”列,它使用我在使用“show”时看到的订单是否足够?否则,我可以根据数据帧中的当前位置创建一个带有递增计数器的新列吗?请提供您的订单列。我们需要它来定义这个部分什么时候开始。拉马努斯和我都给出了相同的答案。只要确保你有一个“订单”栏,它应该会工作。否则,你就注定要失败。不,你没有错过什么——这是完美的。但请注意,我犯了一个错误