如何在Spark DataFrame / DataSet中将行拆分为不同的列?

时间:2016-11-14 10:16:05

标签: apache-spark spark-dataframe apache-spark-dataset

假设我的数据集如下:

Name | Subject | Y1  | Y2 
A    | math    | 1998| 2000
B    |         | 1996| 1999
     | science | 2004| 2005

我想拆分此数据集的行,以便Y2列将被删除,如:

Name | Subject | Y1
A    | math    | 1998
A    | math    | 1999
A    | math    | 2000
B    |         | 1996
B    |         | 1997
B    |         | 1998
B    |         | 1999
     | science | 2004
     | science | 2005

有人可以在这里提出建议吗?我希望我的查询清楚了。提前谢谢。

4 个答案:

答案 0 :(得分:4)

我认为您只需要创建udf来创建范围。然后,您可以使用explode创建必要的行:

val createRange = udf { (yearFrom: Int, yearTo: Int) =>
    (yearFrom to yearTo).toList
}

df.select($"Name", $"Subject", functions.explode(createRange($"Y1", $"Y2"))).show()

编辑:此代码的python版本类似于:

from pyspark.sql import Row
from pyspark.sql.functions import udf, explode
from pyspark.sql.types import IntegerType

createRange=udf( lambda (yearFrom, yearTo): list(range(yearFrom, yearTo)), IntegerType())

df.select($"Name", $"Subject", explode(createRange($"Y1", $"Y2"))).show()

答案 1 :(得分:1)

我在pyspark中测试了这段代码,它按预期工作:

data= sc.parallelize([["A","math",1998,2000],["B","",1996,1999],["","science",2004,2005]]

data.map(lambda reg: ((reg[0],reg[1]),(range(reg[2],reg[3]+1))) )
    .flatMapValues(lambda reg: reg).collect()

更详细地说,您需要将输入数据转换为表格(键,值)中的一对RDD,其中key由前两个字段组成,因为结果将被展平,保持密钥与{{{ 1}}。要映射的值构造为从flatMapValuesrange的{​​{1}}。所有这些都是在第一个Y1中完成的。

Y2将返回与其map相关联的flatMapValues中的每个值。

输出如下:

range

答案 2 :(得分:0)

以下是实现此目的的方法:

  val resultantDF= df.rdd.flatMap{row =>
    val rangeInitial = row.getInt(2)
    val rangeEnd = row.getInt(3)
    val array = rangeInitial to rangeEnd
    (List.fill(array.size)(row.getString(0)),List.fill(array.size)(row.getString(1)),array).zipped.toList
    }.toDF("Name","Subject","Y1")

resultantDF.show()

答案 3 :(得分:-1)

您可以轻松地使用spark select在数据框中获得所需内容,甚至可以在RDD中使用。

Dataset<Row> sqlDF = spark.sql("SELECT Name,Subject,Y1 FROM tableName");

如果你是从已经使用数据框开始的,比如说用户,你可以使用这样的东西:

resultDF = usersDF.select("Name","Subject","Y1");