표현식 API 지도와 불리언(Boolean) 다루기
Spark: The Definitive Guide (Excerpts, Databricks Preview, 2017) — Chapters 2-6 — Bill Chambers & Matei Zaharia Chapter 6: Working with Different Types of Data - Chapter Overview, Where to Look for APIs, Working with Booleans 절 (PDF pp.85-91)
이 모듈을 다 읽으면
- 데이터 타입별 변환 함수를 찾을 때 살펴봐야 할 네 군데(Dataset 메서드, 서브모듈, Column 메서드, functions 패키지)를 구분해 설명할 수 있다
- Scala에서 동등 비교 시 ===/=!=를 써야 하는 이유를 설명할 수 있다
- and로 이어지는 조건과 or로 이어지는 조건을 Spark가 각각 어떻게 처리하는지 설명할 수 있다
이 장은 Boolean, 숫자, 문자열, 날짜/타임스탬프, null, 복합 타입, UDF 등 다양한 데이터 타입을 다루는 표현식(expression) 작성법을 다룬다. 함수를 찾을 때는 Dataset 메서드, DataFrameStatFunctions/DataFrameNaFunctions 같은 서브모듈, Column 메서드, org.apache.spark.sql.functions 패키지 네 군데를 살펴보면 된다. Boolean은 필터링의 기초 단위이며, and로 연결된 조건은 Spark가 하나의 필터로 평탄화(flatten)해 동시에 처리하지만 or 조건은 반드시 같은 표현식 안에 명시해야 한다.
변환 함수는 어디서 찾는가
Spark는 계속 발전하는 프로젝트라 특정 시점의 책이나 문서가 모든 함수를 담을 수 없다. 그래서 저자들은 함수 자체를 암기시키기보다 어디를 찾아봐야 하는지를 알려주는 데 집중한다.
찾아볼 곳은 네 가지다. 첫째, DataFrame(Dataset) 메서드 - DataFrame은 사실 Row 타입의 Dataset이므로 실제로는 Dataset의 메서드를 보게 된다. 둘째, DataFrameStatFunctions(통계 관련)나 DataFrameNaFunctions(null 관련) 같은 도메인 특화 서브모듈. 셋째, alias나 contains처럼 컬럼 하나에 적용하는 Column 메서드. 넷째, 다양한 데이터 타입을 아우르는 함수 모음인 org.apache.spark.sql.functions 패키지 - 워낙 자주 쓰여 통째로 임포트하는 경우가 많다.
이 장의 예제는 소매(retail) 데이터셋을 CSV로 읽어 만든 DataFrame(df)과, 이를 SQL에서 쓰기 위해 등록한 임시 뷰 dfTable을 기준으로 진행된다.
핵심 포인트
- 함수를 찾을 곳은 Dataset 메서드, 도메인 특화 서브모듈(StatFunctions/NaFunctions), Column 메서드, functions 패키지 네 곳이다
- 이 장 전반에서는 CSV로 읽은 소매 데이터 DataFrame df와 그 임시 뷰 dfTable을 예제로 사용한다
불리언 표현식과 필터링
Boolean 문장은 and, or, true, false 네 요소로 구성되며, 이를 조합해 특정 행이 필터를 통과할지(true) 걸러질지(false)를 결정하는 조건식을 만든다.
Scala에서 동등 비교를 할 때는 반드시 ===(equal) 또는 =!=(not equal)를 사용해야 한다. 일반 == 연산자를 쓰면 Scala 고유의 의미 때문에 원하는 동작이 나오지 않을 수 있다. equalTo 메서드나 not 함수를 대신 쓸 수도 있다. Python은 이런 특수 연산자 없이 관례적인 !=, == 표기를 그대로 쓸 수 있다.
import org.apache.spark.sql.functions.col
df.where(col("InvoiceNo") === 536365)
.select("InvoiceNo", "Description")
.show(5, false)
핵심 포인트
- Boolean 표현식은 and·or·true·false 네 요소로 구성되며 필터 통과 여부(true/false)를 결정한다
- Scala에서는 == 대신 ===(equal)/=!=(not equal) 또는 equalTo/not을 써야 하며, Python은 관례적인 ==, != 를 그대로 쓴다
and는 직렬로, or는 한 표현식 안에
여러 조건을 and로 연결할 때는 .where()를 여러 번 순차적으로(직렬로) 체이닝하는 것을 권장한다. 표현식을 순차적으로 나열해도 Spark가 이들을 내부적으로 하나의 필터 문장으로 평탄화(flatten)해 동시에 처리하기 때문에, 성능 손해 없이 가독성만 얻을 수 있다.
반면 or로 연결하는 조건은 반드시 같은 표현식 하나 안에 명시해야 한다. priceFilter.or(descripFilter)처럼 하나의 불리언 컬럼으로 결합한 뒤 where에 넘기는 식이다. 또한 Boolean 표현식은 필터 조건으로만 쓰이는 게 아니라, withColumn으로 새로운 Boolean 컬럼(예: isExpensive)을 만든 뒤 그 컬럼명을 where에 넘겨 필터링할 수도 있다.
Spark SQL 문자열로 필터를 표현하는 것도 프로그래밍 방식 DataFrame 인터페이스와 동등하며 성능 손해가 없다. 예를 들어 expr("NOT UnitPrice <= 250")과 not(col("UnitPrice").leq(250))은 동일하게 동작한다.
핵심 포인트
- and로 묶을 조건은 .where()를 순차적으로 체이닝해도 Spark가 하나의 필터로 평탄화해 동시에 처리한다
- or로 묶을 조건은 반드시 하나의 표현식 안에 명시해야 한다 (예: priceFilter.or(descripFilter))
- Boolean 컬럼을 withColumn으로 만든 뒤 그 컬럼명으로 필터링할 수 있고, SQL 문자열 표현식도 DataFrame API와 동등한 성능을 낸다