あなたが任意の行をしたい場合は、first
やlast
を使用しようとすることができますが、それははるかにきれいからであると私は真剣にスパークのアップグレードを検討します:
from pyspark.sql.functions import col, first
df = sc.parallelize([
(1, "desc1", "v1", "v3"), (2, "desc2", "v4", "v2"),
(1, "desc1", "v4", "v2"), (2, "desc2", "v1", "v3")
]).toDF(["col1", "col2", "col3", "col4"])
keys = ["col1", "col2"]
values = ["col3", "col4"]
agg_exprs = [first(c).alias(c) for c in keys + ["vs_"]]
select_exprs = keys + [
"vs_.col{0} AS {1}".format(i + 1, v) for (i, v) in enumerate(values)]
df_not_so_first = (df
.selectExpr("struct({}) AS vs_".format(",".join(values)), *keys)
.groupBy(*keys)
.agg(*agg_exprs)
.selectExpr(*select_exprs))
注この特定の文脈でfirst
がないこと特定の行を選択すると、結果が確定的でない可能性があります。さらに、Sparkのバージョンによっては、個別の集計を個別にスケジュールすることもできます。それは
df.groupBy("col1", "col2").agg(first("col3"), first("col4"))
がcol3
を保証するものではありません。また、col4
が同じ行から選択されることを意味します。
論理的に考慮する必要はありますか? – eliasah
これを明確にするには:最初/最後の行は必須ではありません。私は、同じ行から(col3、col4)の任意の値と共に(col1、col2)の別個の値が必要です。私はminやmaxのような集計関数を使うことができません。col3とcol4の値を別の行から持ってくるからです。 – Mohan
col5 = 1の値を持つもう1つの列(col5)を導入することができます(col1、col2 order by col1、col2 asc)、新しい列 - col5 = 1を使用して最初の行をフィルタリングできます。 – Mohan