我有以下示例数据框
df = spark.createDataFrame([('start','end'), ('start1','end1')] ,["start", "end"])
,我想爆炸每行中的值,并在生成的行中关联交替的1-0值。这样,我可以识别每行中的开始/结束条目。
我能够通过这种方式达到预期的结果
from pyspark.sql.window import Window
w = Window().orderBy(lit('A'))
df = (df.withColumn('start_end', fn.array('start', 'end'))
.withColumn('date', fn.explode('start_end'))
.withColumn('row_num', fn.row_number().over(w)))
df = (df.withColumn('is_start', fn.when(fn.col('row_num')%2 == 0, 0).otherwise(1))
.select('date', 'is_start'))
给出
| date | is_start |
|--------|----------|
| start | 1 |
| end | 0 |
| start1 | 1 |
| end1 | 0 |
但是对于这样一个简单的任务来说似乎太复杂了。
有没有不使用UDF的更好/更清洁的方法?
答案 0 :(得分:1)
您可以尝试data.groupby(['Month/Year'])[['col1','col2','col3','col4']].sum()
:
union
df = spark.createDataFrame([('start','end'), ('start1','end1')] ,["start", "end"])
df = df.withColumn('startv', F.lit(1))
df = df.withColumn('endv', F.lit(0))
df = df.select(['start', 'startv']).union(df.select(['end', 'endv']))
df.show()
您可以重命名列并从此处开始重新排列行。
答案 1 :(得分:1)
我的用例中也有类似情况。在我的情况下,我有巨大的数据集(〜50GB),并且进行任何自连接/重转换都会导致更多的内存和不稳定的执行。
我又进一步降低了数据集的层次,并使用了 rdd 的平面图。这将使用地图端转换,并且在改组,cpu和内存方面将具有成本效益。
df = spark.createDataFrame([('start','end'), ('start1','end1')] ,["start", "end"])
df.show()
+------+----+
| start| end|
+------+----+
| start| end|
|start1|end1|
+------+----+
final_df = df.rdd.flatMap(lambda row: [(row.start, 1), (row.end, 0)]).toDF(['date', 'is_start'])
final_df.show()
+------+--------+
| date|is_start|
+------+--------+
| start| 1|
| end| 0|
|start1| 1|
| end1| 0|
+------+--------+
答案 2 :(得分:1)
您可以将pyspark.sql.functions.posexplode
与pyspark.sql.functions.array
一起使用。
首先在start
和end
列中创建一个数组,然后使用以下位置将其爆炸:
from pyspark.sql.functions import array, posexplode
df.select(posexplode(array("end", "start")).alias("is_start", "date")).show()
#+--------+------+
#|is_start| date|
#+--------+------+
#| 0| end|
#| 1| start|
#| 0| end1|
#| 1|start1|
#+--------+------+