当前位置: 首页 > 知识库问答 >
问题:

在Scala中,从另一个没有数组列的数据帧中创建带有数组类型列的Spark数据帧的有效方法是什么?

公羊喜
2023-03-14

假设,我有以下数据帧:

 id | col1 | col2 
-----------------
 x  |  p1  |  a1  
-----------------
 x  |  p2  |  b1
-----------------
 y  |  p2  |  b2
-----------------
 y  |  p2  |  b3
-----------------
 y  |  p3  |  c1

与 col1 不同的值(p1、p2、p3)单独具有 id,将用作最终数据帧的列。在这里,id y 对于相同的 col1 值 p2 有两个 col2 值(b2 和 b3),因此,p2 将被视为数组类型列。因此,最终的数据帧将是

  id  |   p1   |   p2   |   p3
--------------------------------
  x   |   a1   |  [b1]  |  null
--------------------------------
  y   |  null  |[b2, b3]|  c1

如何从第一个数据帧高效地实现第二个数据帧?

共有1个答案

金秦斩
2023-03-14

您基本上是在寻找表数据透视;对于您的情况,groupByidpivotcol1作为头,并使用<code>collect_list聚合为列表:

df.groupBy("id").pivot("col1").agg(collect_list("col2")).show
+---+----+--------+----+
| id|  p1|      p2|  p3|
+---+----+--------+----+
|  x|[a1]|    [b1]|  []|
|  y|  []|[b2, b3]|[c1]|
+---+----+--------+----+

如果保证每个< code>id在< code>p1和< code>p3中最多有一个值,您可以通过< code >获取数组的第一项将这些列转换为字符串类型:

df.groupBy("id").pivot("col1").agg(collect_list("col2"))
  .withColumn("p1", $"p1"(0)).withColumn("p3", $"p3"(0))
  .show
+---+----+--------+----+
| id|  p1|      p2|  p3|
+---+----+--------+----+
|  x|  a1|    [b1]|null|
|  y|null|[b2, b3]|  c1|
+---+----+--------+----+

如果您需要动态转换列类型,即仅在必要时使用数组类型列类型:

// get array Type columns
val arrayColumns = df.groupBy("id", "col1").agg(count("*").as("N"))
    .where($"N" > 1).select("col1").distinct.collect.map(row => row.getString(0))
// arrayColumns: Array[String] = Array(p2)

// aggregate / pivot data frame
val aggDf = df.groupBy("id").pivot("col1").agg(collect_list("col2"))
// aggDf: org.apache.spark.sql.DataFrame = [id: string, p1: array<string> ... 2 more fields]

// get string columns
val stringColumns = aggDf.columns.filter(x => x != "id" && !arrayColumns.contains(x))

// use foldLeft on string columns to convert the columns to string type
stringColumns.foldLeft(aggDf)((df, x) => df.withColumn(x, col(x)(0))).show
+---+----+--------+----+
| id|  p1|      p2|  p3|
+---+----+--------+----+
|  x|  a1|    [b1]|null|
|  y|null|[b2, b3]|  c1|
+---+----+--------+----+
 类似资料:
  • 我正在尝试查看我们是否可以使用 spark/scala 从 dataFrame 中某个列中的值创建新列。我有一个数据帧,其中包含以下数据 在上面的数据中,col1/col2/col3是列名,后跟它的值。列名和值由< code >,分隔。每组由< code>|分隔。 现在,我想做到这一点 感谢任何帮助。

  • 我正在尝试在 pyspark 中连接两个数据帧,但将一个表作为数组列连接在另一个表上。 例如,对于这些表: 我想在列和上将df1连接到df2,但和应该是单个数组类型列。此外,应保留所有名称。新数据框的输出应该能够转换为此json结构(例如前两行): 任何关于如何实现这一目标的想法都将不胜感激! 谢谢, 卡罗莱纳州

  • 我不是本地JAVA程序员。我正在为web服务API创建一个客户端。API基本上需要一个数组参数。 我正在解析一个XML文件,创建记录,然后使用此API进行批量插入。 问题是这个API一次只能插入200条记录,这意味着我的数组在调用时只能有200条或更少的记录。 由于我不知道预先有多少条记录,所以我将我的记录存储在ArrayList中,然后使用将其转换为Array。ToArray() 现在,由于AP

  • 我正在改装一些现有代码以使用Spark。我有多个包含不同数据集的数据帧。在转换主数据帧(或主数据集)时,我需要使用来自其他数据帧的数据来完成转换。我还有一种情况(至少在当前结构中),我需要在另一个数据帧的转换函数中创建新的数据帧。 我试图确定以下内容: 我可以在另一个数据帧的转换函数中访问数据帧吗 关于如何处理这种情况的指针将非常有帮助。

  • 我和Spark一起在Databricks上工作。编程语言是Scala。 我有两个数据帧: 主数据框:见截图:1 查找数据帧:参见屏幕截图3 我想: 查找主数据框中“年龄”=-1的所有行 我对如何做这件事伤了脑筋。我唯一想到的是将dataframe存储为DataRicks中的表,并使用SQL语句(SQL.Context.SQL…),结果非常复杂。 我想知道是否有更有效的方法。 编辑:添加可复制的示例

  • 我得到以下错误:org.apache.spark.sql.analysisException:不允许在另一个聚合函数的参数中使用聚合函数。请在子查询中使用内部聚合函数。;; 我尝试了多种解决方案来解决这个问题,但似乎没有任何效果。所有的想法都得到了赞赏。谢了!