Code Workspaces의 행과 열 필터
작업공간에 데이터를 모두 올리기 전에 행이나 열을 줄이면 메모리 사용량을 줄일 수 있습니다. 압축을 푼 전체 데이터가 메모리에 들어오면 한 번 로드한 뒤 메모리에서 여러 변환을 하는 방식이 효율적일 수 있습니다.
데이터가 크면 push-down 필터 또는 SQL로 필요한 부분을 가져옵니다. 필터 성능은 데이터 규모와 파티션 구성에 영향을 받습니다. 같은 부분집합을 여러 작업공간에서 반복 사용한다면 Spark transform으로 작은 데이터셋을 미리 만들 수 있습니다. Parquet 다운로드는 재사용할 수 있지만 필터는 로드할 때마다 수행합니다.
지원 조건
- 열 선택은 모든 표 형식 데이터셋에서 사용할 수 있습니다.
- 행 필터는 Parquet 데이터셋에만 적용합니다. CSV 같은 형식은 열 선택은 지원하지만 이 행 필터 경로는 지원하지 않습니다.
- Python에서 columns, row_limit 또는 where 필터를 사용하면 format은 arrow, dataframe, pandas 또는 polars여야 하고 mode는 current여야 합니다.
- 이 필터가 있는 읽기에 lazy-polars 또는 path 출력을 지정하지 않습니다.
복잡한 파일 처리가 필요하면 원본 파일을 다운로드하여 그 형식의 Python/R 라이브러리로 처리할 수 있습니다.
행 수 상한
Python:
from foundry.transforms import Dataset
dogs_subset = Dataset.get("dogs").limit(1000).read_table(format="pandas")
R:
library(foundry)
library(dplyr)
dogs_subset <- Dataset.get("dogs") %>%
head(1000) %>%
collect()
limit 또는 head의 상한은 다른 필터보다 먼저 적용됩니다. 따라서 필터 조건을 만족하는 행 1,000개가 반환된다는 의미는 아닙니다.
가상 예제 데이터
dogs 별칭의 Parquet 데이터셋에 다음 행이 있다고 가정합니다.
| name | weight | color | age | breed |
|---|---|---|---|---|
| Bella | 60 | Brown | 4 | Labrador |
| Max | 75 | Black | 7 | German Shepherd |
| Daisy | 30 | White | 2 | Poodle |
| Buddy | 65 | Yellow | 3 | Labrador |
| Gizmo | 18 | Brown | 1 | Pug |
열 선택
Python:
from foundry.transforms import Dataset
columns_to_load = ["breed", "age"]
breed_and_age_only = (
Dataset.get("dogs").select(*columns_to_load).read_table(format="pandas")
)
weight_and_color_only = (
Dataset.get("dogs").select("weight", "color").read_table(format="pandas")
)
R:
library(foundry)
library(dplyr)
weight_and_color_only <- Dataset.get("dogs") %>%
select(weight, color) %>%
collect()
Python 행 필터
Column.get으로 속성을 참조하고 where를 연결합니다.
from foundry.transforms import Dataset, Column
brown_dogs = (
Dataset.get("dogs")
.where(Column.get("color") == "Brown")
.read_table(format="pandas")
)
brown_labradors = (
Dataset.get("dogs")
.where(Column.get("color") == "Brown")
.where(Column.get("breed") == "Labrador")
.read_table(format="pandas")
)
지원 표현은 다음과 같습니다.
- 같음:
Column.get("color") == "Brown" - 다름:
Column.get("color") != "Brown"또는~(Column.get("color") == "Brown") - 크기 비교:
Column.get("age") > 2,>= 2,< 4,<= 4 - OR:
(Column.get("color") == "Brown") | (Column.get("color") == "White") - AND:
(Column.get("color") == "Brown") & (Column.get("breed") == "Labrador") - null 제외:
~Column.get("age").isnull() - 목록 포함:
Column.get("color").isin(["Brown", "White"]) - 양끝 포함 범위:
Column.get("date_column").between("2024-01-01", "2024-12-31")
마지막 날짜 예는 별도 date_column이 있는 입력을 전제로 합니다. Boolean 조건을 합칠 때는 각 비교식을 괄호로 묶습니다.
R 행 필터
R의 Dataset.get과 dplyr 체인은 collect 전에 지원 필터를 적용합니다. 이름이 같은 다른 패키지 함수와 충돌하지 않도록 foundry::filter를 사용합니다.
library(foundry)
library(dplyr)
brown_dogs <- Dataset.get("dogs") %>%
foundry::filter(color == "Brown") %>%
collect()
brown_labradors <- Dataset.get("dogs") %>%
foundry::filter(color == "Brown") %>%
foundry::filter(breed == "Labrador") %>%
collect()
필터 안의 열 이름은 문자열로 감싸지 않습니다. 지원 비교와 결합은 다음과 같습니다.
- 같음 및 다름:
color == "Brown",age == 4,color != "Brown",!(color == "Brown") - 크기 비교:
age > 2,age >= 2,age < 4,age <= 4 - OR/AND:
color == "Brown" | color == "White",color == "Brown" & breed == "Labrador" - 목록 포함:
color %in% c("Brown", "White") - 결측 제외:
!is.na(age) - 양끝 포함 범위:
between(age, 2, 4)
R에서 collect 전에 select를 사용하면 filter 절이 사용하는 모든 열도 선택에 포함해야 합니다.
행과 열을 함께 제한
다음 예는 weight가 62보다 크고 color가 Brown인 행에서 name, breed와 color를 남깁니다. 위 가상 데이터에서는 조건을 만족하는 행이 없으므로 빈 결과가 맞습니다.
Python:
from foundry.transforms import Dataset, Column
heavy_brown_dogs = (
Dataset.get("dogs")
.where(Column.get("weight") > 62)
.where(Column.get("color") == "Brown")
.select("name", "breed", "color")
.read_table(format="arrow")
.to_pandas()
)
R에서는 원격 필터에 필요한 weight를 collect까지 유지한 뒤 로컬 결과에서 최종 열을 선택합니다.
library(foundry)
library(dplyr)
heavy_brown_dogs <- Dataset.get("dogs") %>%
foundry::filter(weight > 62) %>%
foundry::filter(color == "Brown") %>%
select(name, breed, color, weight) %>%
collect() %>%
select(name, breed, color)
Arrow로 가져온 뒤 추가 변환
단순 조건은 먼저 적용하고, group_by 같은 추가 연산은 Arrow Table로 가져온 뒤 수행할 수 있습니다. 다음 예는 age가 2보다 큰 개를 품종별로 세는 실제 집계입니다.
library(foundry)
library(dplyr)
counts_by_breed <- Dataset.get("dogs") %>%
foundry::filter(age > 2) %>%
collect(as_data_frame = FALSE) %>%
group_by(breed) %>%
summarise(count = n()) %>%
collect()
Arrow 단계의 처리와 Foundry 입력에 적용하는 push-down 필터는 실행 위치가 다르므로 어느 단계에서 데이터가 작업공간으로 들어오는지 구분합니다.