我有一个pyspark 2.0.1。我正在尝试将数据框和数据分组。从我的数据框中检索所有字段的值。我找到了
z=data1.groupby('country').agg(F.collect_list('names'))
会给我国家和地区的价值观名字属性&对于names属性,它将列标题为collect_list(names)
。但是对于我的工作,我有大约15列的数据框和&我会跑一个循环&每次在循环内部都会改变groupby字段。需要输出所有剩余的字段。你能建议我如何使用collect_list()或任何其他pyspark函数吗?
我也试过这段代码
from pyspark.sql import functions as F
fieldnames=data1.schema.names
names1= list()
for item in names:
if item != 'names':
names1.append(item)
z=data1.groupby('names').agg(F.collect_list(names1))
z.show()
但收到了错误消息
Py4JError: An error occurred while calling z:org.apache.spark.sql.functions.collect_list. Trace: py4j.Py4JException: Method collect_list([class java.util.ArrayList]) does not exist
答案 0 :(得分:3)
在调用groupBy
之前使用struct组合列假设您有数据框
df = spark.createDataFrame(sc.parallelize([(0,1,2),(0,4,5),(1,7,8),(1,8,7)])).toDF("a","b","c")
df = df.select("a", f.struct(["b","c"]).alias("newcol"))
df.show()
+---+------+
| a|newcol|
+---+------+
| 0| [1,2]|
| 0| [4,5]|
| 1| [7,8]|
| 1| [8,7]|
+---+------+
df = df.groupBy("a").agg(f.collect_list("newcol").alias("collected_col"))
df.show()
+---+--------------+
| a| collected_col|
+---+--------------+
| 0|[[1,2], [4,5]]|
| 1|[[7,8], [8,7]]|
+---+--------------+
聚合操作只能在单列上完成。
聚合后,您可以收集结果并迭代它以分离组合列生成索引字典。或者你可以写一个 udf将组合列分开。
from pyspark.sql.types import *
def foo(x):
x1 = [y[0] for y in x]
x2 = [y[1] for y in x]
return(x1,x2)
st = StructType([StructField("b", ArrayType(LongType())), StructField("c", ArrayType(LongType()))])
udf_foo = udf(foo, st)
df = df.withColumn("ncol",
udf_foo("collected_col")).select("a",
col("ncol").getItem("b").alias("b"),
col("ncol").getItem("c").alias("c"))
df.show()
+---+------+------+
| a| b| c|
+---+------+------+
| 0|[1, 4]|[2, 5]|
| 1|[7, 8]|[8, 7]|
+---+------+------+
答案 1 :(得分:1)
在spark 2.4.4和python 3.7中(我想它也与以前的spark和python版本相关)-
我的建议是基于pauli's的答案,
而不是先创建结构然后使用agg函数,而是在内部 collect_list中创建结构:
df = spark.createDataFrame([(0,1,2),(0,4,5),(1,7,8),(1,8,7)]).toDF("a","b","c")
df.groupBy("a").agg(collect_list(struct(["b","c"])).alias("res")).show()
结果:
+---+-----------------+
| a|res |
+---+-----------------+
| 0|[[1, 2], [4, 5]] |
| 1|[[7, 8], [8, 7]] |
+---+-----------------+
答案 2 :(得分:0)
实际上我们可以在pyspark 2.2中做到这一点。
首先,我们需要创建一个常量列(“ Temp”),使用该列创建一个groupBy(“ Temp”),并通过传递可迭代的* exprs来应用agg。
下面是代码:
import pyspark.sql.functions as ftions
import functools as ftools
def groupColumnData(df, columns):
df = df.withColumn("Temp", ftions.lit(1))
exprs = [ftions.collect_list(colName) for colName in columns]
df = df.groupby('Temp').agg(*exprs)
df = df.drop("Temp")
df = df.toDF(*columns)
return df
输入数据:
df.show()
+---+---+---+
| a| b| c|
+---+---+---+
| 0| 1| 2|
| 0| 4| 5|
| 1| 7| 8|
| 1| 8| 7|
+---+---+---+
输出数据:
df.show()
+------------+------------+------------+
| a| b| c|
+------------+------------+------------+
|[0, 0, 1, 1]|[1, 4, 7, 8]|[2, 5, 8, 7]|
+------------+------------+------------+