Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark Spark DataFrame:根据列值获取按行排序的列名_Apache Spark_Pyspark - Fatal编程技术网

Apache spark Spark DataFrame:根据列值获取按行排序的列名

Apache spark Spark DataFrame:根据列值获取按行排序的列名,apache-spark,pyspark,Apache Spark,Pyspark,对于下面数据框中的每一行,我希望根据降序列条目查找列名(如数组、元组或其他内容)。所以,对于数据帧 +---+---+---+---+---+ |ID |键| a | b | c| +---+---+---+---+---+ | 0| 1| 5| 2| 1| | 1| 1| 3| 4| 5| +---+---+---+---+---+ 我想找到 +---+---+---+---+---+------------------+ |ID |键| a | b | c |下行|列|

对于下面数据框中的每一行,我希望根据降序列条目查找列名(如数组、元组或其他内容)。所以,对于数据帧

+---+---+---+---+---+
|ID |键| a | b | c|
+---+---+---+---+---+
|  0|  1|  5|  2|  1|
|  1|  1|  3|  4|  5|
+---+---+---+---+---+
我想找到

+---+---+---+---+---+------------------+
|ID |键| a | b | c |下行|列|
+---+---+---+---+---+------------------+
|0 | 1 | 5 | 2 | 1 |[a,b,c]|
|1 | 1 | 3 | 4 | 5 |[c,b,a]|
+---+---+---+---+---+------------------+
理想情况下,一般来说,我希望能够遍历预先指定的列,并基于这些列条目应用函数。这可能看起来像:

导入pyspark.sql.f函数
name_cols=[“a”、“b”、“c”]
对于名称为“”的列:
值\u ls.append=[]
…架构规范。。。。
值\u ls.追加(f.col(col)…获取列值…)
df1=df.withColumn(“降序列”,值)
这个问题相当简单,但在pyspark中高效地实现似乎相当具有挑战性


我使用的是pyspark版本2.3.3。

您可以将列插入到单个结构中,并在udf中处理

从pyspark.sql导入函数为F
从pyspark.sql导入类型为T
name_cols=['a','b','c']
def有序_列(行):
返回[x代表ux,x已排序(zip(row.asDict().values(),name_cols),reverse=True)]
udf_ordered_columns=F.udf(ordered_columns,T.ArrayType(T.StringType()))
df1=(
df
.withColumn(
“行”,
F.struct(*名称)
)
.withColumn(
“降序列”,
udf_有序_列(“行”)
)
)

类似的功能应该可以使用,如果上面没有,请告诉我。

对于Spark版本<2.4,您可以在不使用和的情况下使用
udf
实现这一点

首先获取要排序的列的列表

cols\u to\u sort=df.columns[2:]
打印(列到列排序)
#['a','b','c']
现在用两个元素构建一个结构-一个
“value”
和一个
“key”
“key”
是列名,
“value”
是列值。如果确保
结构
中的
“值”
位于第一位,则可以使用
排序数组
以所需的方式对该结构数组进行排序

数组排序后,只需对其进行迭代并提取包含列名的
“key”
部分

从pyspark.sql.functions导入数组、col、lit、sort_数组、struct
df.withColumn(
“下行_列”,
排列(
*[
排序数组(
排列(
*[
结构([col(c).alias(“value”)、lit(c).alias(“key”)]))
对于c,按cols\u to\u排序
]
), 
asc=假
)[i] [“钥匙”]
对于范围内的i(len(cols_至_排序))
]
)
).show(truncate=False)
#+---+---+---+---+---+------------------+
#|ID |键| a | b | c |下行|列|
#+---+---+---+---+---+------------------+
#|0 | 1 | 5 | 2 | 1 |[a,b,c]|
#|1 | 1 | 3 | 4 | 5 |[c,b,a]|
#+---+---+---+---+---+------------------+
尽管这看起来很复杂,但它应该比
udf
解决方案提供更好的性能


更新:若要按原始列顺序对值进行排序,可以在包含索引的结构中插入另一个值。因为排序是递减的,所以我们使用索引的负数

例如,如果您的输入数据帧如下所示:

df.show()
#+---+---+---+---+---+
#|ID |键| a | b | c|
#+---+---+---+---+---+
#|  0|  1|  5|  2|  1|
#|  1|  1|  3|  4|  5|
#|  2|  1|  4|  4|  5|
#+---+---+---+---+---+
上面的最后一行在
a
b
之间有一个连接值。在这种情况下,我们希望
a
b
之前进行排序

df.withColumn(
“下行_列”,
排列(
*[
排序数组(
排列(
*[
结构(
[
第(c)栏。别名(“值”),
lit(-j).别名(“索引”),
lit(c).别名(“钥匙”)
]
) 
对于枚举中的j,c(cols_to_排序)
]
), 
asc=假
)[i] [“钥匙”]
对于范围内的i(len(cols_至_排序))
]
)
).show(truncate=False)
#+---+---+---+---+---+------------------+
#|ID |键| a | b | c |下行|列|
#+---+---+---+---+---+------------------+
#|0 | 1 | 5 | 2 | 1 |[a,b,c]|
#|1 | 1 | 3 | 4 | 5 |[c,b,a]|
#|2 | 1 | 4 | 4 | 5 |[c,a,b]|
#+---+---+---+---+---+------------------+

GCP上的Spark版本2.3.3列名将用作平局情况下的第二个排序条件。感谢Pault的回答。我的下一个挑战是在列条目相等时保持列名的顺序。您应该如何实现这一点?您可以在结构中添加第二个条目,即列数组中的索引。然后,这将被用作第一个平局破坏者。我可以发布更新。