Iterate rows and columns in Spark dataframe

前端 未结 7 1038
囚心锁ツ
囚心锁ツ 2020-12-23 12:32

I have the following Spark dataframe that is created dynamically:

val sf1 = StructField(\"name\", StringType, nullable = true)
val sf2 = StructField(\"sector         


        
7条回答
  •  Happy的楠姐
    2020-12-23 12:51

    Consider you have a Dataframe like below

    +-----+------+---+
    | name|sector|age|
    +-----+------+---+
    | Andy|   aaa| 20|
    |Berta|   bbb| 30|
    |  Joe|   ccc| 40|
    +-----+------+---+
    

    To loop your Dataframe and extract the elements from the Dataframe, you can either chose one of the below approaches.

    Approach 1 - Loop using foreach

    Looping a dataframe directly using foreach loop is not possible. To do this, first you have to define schema of dataframe using case class and then you have to specify this schema to the dataframe.

    import spark.implicits._
    import org.apache.spark.sql._
    case class cls_Employee(name:String, sector:String, age:Int)
    val df = Seq(cls_Employee("Andy","aaa", 20), cls_Employee("Berta","bbb", 30), cls_Employee("Joe","ccc", 40)).toDF()
    df.as[cls_Employee].take(df.count.toInt).foreach(t => println(s"name=${t.name},sector=${t.sector},age=${t.age}"))
    

    Please see the result below :

    Approach 2 - Loop using rdd

    Use rdd.collect on top of your Dataframe. The row variable will contain each row of Dataframe of rdd row type. To get each element from a row, use row.mkString(",") which will contain value of each row in comma separated values. Using split function (inbuilt function) you can access each column value of rdd row with index.

    for (row <- df.rdd.collect)
    {   
        var name = row.mkString(",").split(",")(0)
        var sector = row.mkString(",").split(",")(1)
        var age = row.mkString(",").split(",")(2)   
    }
    

    Note that there are two drawback of this approach.
    1. If there is a , in the column value, data will be wrongly split to adjacent column.
    2. rdd.collect is an action that returns all the data to the driver's memory where driver's memory might not be that much huge to hold the data, ending up with getting the application failed.

    I would recommend to use Approach 1.

    Approach 3 - Using where and select

    You can directly use where and select which will internally loop and finds the data. Since it should not throws Index out of bound exception, an if condition is used

    if(df.where($"name" === "Andy").select(col("name")).collect().length >= 1)
        name = df.where($"name" === "Andy").select(col("name")).collect()(0).get(0).toString
    

    Approach 4 - Using temp tables

    You can register dataframe as temptable which will be stored in spark's memory. Then you can use a select query as like other database to query the data and then collect and save in a variable

    df.registerTempTable("student")
    name = sqlContext.sql("select name from student where name='Andy'").collect()(0).toString().replace("[","").replace("]","")
    

提交回复
热议问题