DataFrame에서 Column 유무 체크 방법

DataFrame에서 Column 체크하는 방법을 설명합니다.

DafaFrame에서 Column 유무 검사

//  Example 1
val schema = StructType( Array(
                 StructField("language", StringType,true),
                 StructField("users", IntegerType,true)
             ))

val rowData= Seq(Row("Java", 20000), 
Row("Python", 100000), 
Row("Scala", 3000))
var df = spark.createDataFrame(rowData,schema)
df.printSchema()

// root
// |-- language: string (nullable = true)
// |-- users: integer (nullable = true)  

Spark DataFrame의 columns attribute는 모든 column 이름을 Array[String] 타입으로 반환합니다. Column의 유무를 check하기 위해 contains() 함수를 이용해서 column의 유무를 확인 할 수 있습니다.

val columnName = "users"
if(df.columns.contains(columnName))
    println("column exists")
else
    println("column not exists")

중첩된 구조의 DataFrame에서 Column 유무 검사

// Example2
[{
    "manufacturer": "hyundai",
    "model":[
        {
            "name" : "2022 Genesis GV70 ",
            "release-date" : "2021. 12. 8",
            "price" : "6,000"
        },
        {
            "name" : "2022 Genesis G90 ",
            "release-date" : "2021. 12. 19",
            "price" : "9,300"
        }
    ]
},
{
   "manufacturer": "bmw",
    "model":[
        {
            "name" : "2023 i7 ",
            "release-date" : "-",
            "price" : "-"
        },
        {
            "name" : "2023 x5 ",
            "release-date" : "2022",
            "price" : "12,420"
        }
        
    ] 
},
{
   "manufacturer": "benz",
    "model":[
        {
            "name" : "2022 AMG GT 4-door coupe ",
            "release-date" : "2022. 3. 25",
            "price" : "16,960"
        },
        {
            "name" : "2022 C Class ",
            "release-date" : "2022. 4. 01",
            "price" : "6,800"
        }
        
    ] 
}]

위와 같은 중첩된 구조의 Json 형식의 데이터를 DataFrame으로 구성했을 경우 Column의 유무를 검색하는 방법을 알아봅니다.

val jsonStr =
    """
      |[{
      |    "manufacturer": "hyundai",
      |    "model":[
      |        {
      |            "name" : "2022 Genesis GV70 ",
      |            "release-date" : "2021. 12. 8",
      |            "price" : "6,000"
      |        },
      |        {
      |            "name" : "2022 Genesis G90 ",
      |            "release-date" : "2021. 12. 19",
      |            "price" : "9,300"
      |        }
      |    ]
      |},
      |{
      |   "manufacturer": "bmw",
      |    "model":[
      |        {
      |            "name" : "2023 i7 ",
      |            "release-date" : "-",
      |            "price" : "-"
      |        },
      |        {
      |            "name" : "2023 x5 ",
      |            "release-date" : "2022",
      |            "price" : "12,420"
      |        }
      |        
      |    ] 
      |},
      |{
      |   "manufacturer": "benz",
      |    "model":[
      |        {
      |            "name" : "2022 AMG GT 4-door coupe ",
      |            "release-date" : "2022. 3. 25",
      |            "price" : "16,960"
      |        },
      |        {
      |            "name" : "2022 C Class ",
      |            "release-date" : "2022. 4. 01",
      |            "price" : "6,800"
      |        }
      |        
      |    ] 
      |}]
      |""".stripMargin
    

val df = sqlContext.read.json(Seq(jsonStr).toDS())
df.printSchema()
df.show(false)
root
 |-- manufacturer: string (nullable = true)
 |-- model: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- name: string (nullable = true)
 |    |    |-- price: string (nullable = true)
 |    |    |-- release-date: string (nullable = true)

+------------+---------------------------------------------------------------------------------------+
|manufacturer|model                                                                                  |
+------------+---------------------------------------------------------------------------------------+
|hyundai     |[[2022 Genesis GV70 , 6,000, 2021. 12. 8], [2022 Genesis G90 , 9,300, 2021. 12. 19]]   |
|bmw         |[[2023 i7 , -, -], [2023 x5 , 12,420, 2022]]                                           |
|benz        |[[2022 AMG GT 4-door coupe , 16,960, 2022. 3. 25], [2022 C Class , 6,800, 2022. 4. 01]]|
+------------+---------------------------------------------------------------------------------------+

df.columns은 중첩된 구조에서 내부 컬럼을 반환하지 않습니다. 그렇기 때문에 DataFrame이 중첩된 구조를 가질 경우 df.schema.simpleString()을 이용하여 중첩 구조의 스키마 컬럼을 검사할 수 있습니다.

df.columns
// Array[String] = Array(manufacturer, model)

df.schema.simpleString()
// String = struct<manufacturer:string,model:array<struct<name:string,price:string,release-date:string>>>

df.schema.simpleString.contains("release-date:")
// true

DataFrame에서 Field 유무 검사

동일한 데이터 유형을 가진 열이 있는지 확인하려면 스파크 스키마 함수 df.schema.fieldNames 또는 df.schema.contain() 함수를 사용합니다.

import org.apache.spark.sql.types.{StringType, StructField}
df.schema.fieldNames.contains("manufacturer")
df.schema.contains(StructField("manufacturer",StringType,true))