← 학습 카테고리

Learn

Spark

38개 모듈 · 현재 13번째

Spark 모듈 13/38 spark-learn-13

DataFrame 컬럼 조작: select/selectExpr, 리터럴, 추가·이름변경·제거·캐스팅

Spark: The Definitive Guide (Excerpts, Databricks Preview, 2017) — Chapters 2-6 — Bill Chambers & Matei Zaharia Chapter 5: DataFrame Transformations - Creating DataFrames, Select & SelectExpr, Literals, Adding/Renaming/Removing Columns, Casting 절 (PDF pp.63-75)

이 모듈을 다 읽으면

  • select와 selectExpr의 용도 차이와, selectExpr로 집계·표현식을 다루는 방법을 설명할 수 있다
  • withColumn, withColumnRenamed, drop, cast의 용법을 구분해 설명할 수 있다
  • 컬럼명에 예약 문자가 있을 때 백틱 이스케이프가 필요한 경우와 필요 없는 경우를 구분할 수 있다

단일 DataFrame 연산은 행/컬럼 추가, 행/컬럼 제거, 행↔컬럼 변환, 정렬의 네 가지로 요약된다. select와 selectExpr로 컬럼과 표현식을 다루고, lit()으로 상수 리터럴을 표현식화하며, withColumn/withColumnRenamed/drop/cast로 컬럼을 추가·이름변경·제거·타입변환한다. 예약 문자가 포함된 컬럼명은 표현식 내부에서 참조할 때만 백틱 이스케이프가 필요하다.

DataFrame 생성과 4가지 기본 트랜스포메이션 목표

단일 DataFrame을 다루는 작업의 목표는 크게 네 가지로 요약된다: 행이나 컬럼을 추가하는 것, 행이나 컬럼을 제거하는 것, 행을 컬럼으로(또는 그 반대로) 변환하는 것, 컬럼 값을 기준으로 행의 순서를 바꾸는 것이다.

DataFrame은 데이터 소스로부터 읽어서 생성하거나, Row들의 시퀀스와 스키마를 조합해 `spark.createDataFrame`으로 직접 생성할 수도 있다. `createOrReplaceTempView`로 DataFrame을 임시 뷰로 등록해 두면, 같은 데이터를 SQL 쿼리로도 조회할 수 있게 된다.

핵심 포인트

  • 단일 DataFrame 연산은 행/컬럼 추가, 행/컬럼 제거, 행↔컬럼 변환, 정렬의 네 가지로 요약된다
  • createOrReplaceTempView로 DataFrame을 임시 뷰로 등록하면 동일 데이터를 SQL로도 조회할 수 있다

select와 selectExpr

select는 컬럼명 문자열이나 Column 표현식을 받아 SQL의 SELECT 문과 동등하게 동작한다. 다만 한 번의 select 호출 안에서 Column 객체와 순수 문자열을 섞어 쓰면(예: `df.select(col("a"), "b")`) 컴파일 에러가 발생하므로 주의해야 한다.

selectExpr는 select 뒤에 expr을 여러 번 쓰는 흔한 패턴을 축약한 것으로, 문자열로 표현식을 바로 전달할 수 있어 일상적으로 가장 편리한 인터페이스로 꼽힌다. selectExpr에는 컬럼이 정상적으로 resolve되는 한 집계가 아닌(non-aggregating) SQL 문이라면 사실상 무엇이든 넣을 수 있다(예: 두 컬럼을 비교해 새 boolean 컬럼을 만드는 표현식). 더 나아가 `avg(count)`, `count(distinct DEST_COUNTRY_NAME)`처럼 집계 함수 자체도 selectExpr에 바로 넣어 DataFrame 전체에 대한 집계 결과를 얻을 수 있다.

핵심 포인트

  • select 호출 하나에서 Column 객체와 문자열을 섞으면 컴파일 에러가 발생한다
  • selectExpr는 select+expr의 축약형으로, 컬럼이 resolve되는 non-aggregating SQL 문이면 무엇이든 문자열로 전달 가능하다
  • selectExpr에 avg(count)처럼 집계 함수를 바로 넣어 DataFrame 전체에 대한 집계 결과를 얻을 수 있다

리터럴(Literal)

새로운 컬럼이 아니라 상수 값 하나를 Spark에 전달해야 할 때는 리터럴(literal)을 사용한다. `lit()` 함수는 프로그래밍 언어의 리터럴 값을 Spark가 이해하는 값으로 번역해 주며, 리터럴도 표현식의 일종이므로 다른 표현식과 똑같은 방식으로 조합해 쓸 수 있다(예: `lit(1).alias("One")`). 날짜를 특정 상수와 비교해야 하는 경우 등에 자주 쓰인다.

핵심 포인트

  • lit()은 언어 리터럴 값을 Spark가 이해하는 표현식으로 변환하며, 다른 표현식과 동일하게 조합해 쓸 수 있다

컬럼 추가·이름변경·제거·타입 변환

`withColumn(새컬럼명, 표현식)`으로 컬럼을 추가한다. 이 메서드는 두 인자를 받는데, 첫 인자는 컬럼명이고 둘째 인자는 해당 행의 값을 계산하는 표현식이다. 기존 컬럼과 동일한 이름을 첫 인자로 주면 사실상 이름 변경 효과도 낼 수 있지만, 더 읽기 쉬운 전용 방법은 `withColumnRenamed(기존이름, 새이름)`이다.

컬럼 제거는 select로도 흉내 낼 수 있지만, 전용 메서드인 `drop(컬럼명, ...)`을 쓰면 여러 컬럼을 한 번에 제거할 수 있다. 타입 변환은 `cast`를 사용한다(예: `col("count").cast("int")`로 정수형으로 변환).

컬럼명에 공백이나 대시(-) 같은 예약 문자가 있으면, 그 컬럼을 표현식 안에서 참조할 때만 백틱(`)으로 감싸 이스케이프해야 한다. `withColumn`의 첫 인자(새 컬럼명 문자열)나, 표현식이 아닌 명시적 문자열-컬럼 참조(리터럴 문자열로 해석되는 경우)에는 이스케이프가 필요 없다.

핵심 포인트

  • withColumn(name, expr)은 이름과 값 표현식 두 인자를 받아 컬럼을 추가하거나(동일 이름 재사용 시) 대체한다
  • 이름 변경 전용 메서드는 withColumnRenamed(기존이름, 새이름)이고, 제거는 drop(컬럼명, ...)로 여러 개를 한 번에 처리 가능하다
  • 타입 변환은 cast로 하며, 예약 문자가 포함된 컬럼명은 표현식 내부에서 참조할 때만 백틱으로 이스케이프하면 된다