P2-12.2 선택, 필터링, 집계¶
Section ID:
P2-12.2Version:v2026.07.23
P2-12.1에서는 Pandas DataFrame을 행(row), 열(column), 인덱스(index)가 있는 표 형식 데이터 구조로 봤습니다. 이제 질문이 하나 더 생깁니다.
표를 받았다고 해서 필요한 정보가 바로 보이는 것은 아닙니다. 실제로는 다음과 같은 일을 계속 하게 됩니다.
- 특정 열만 고른다.
- 특정 행만 본다.
- 조건에 맞는 행만 남긴다.
- 숫자 열의 평균이나 개수를 확인한다.
- 범주별로 나누어 요약한다.
Pandas에서 선택(select), 필터링(filtering), 집계(aggregation)는 바로 이 흐름을 다룹니다.
여기서는 Series, 필터링(filtering), 집계(aggregation), groupby, loc, iloc의 기본 구분을 설명합니다. DataFrame 자체의 대표 설명은 P2-12.1과 개념사전에 두고, 여기서는 그 표에서 무엇을 읽고 무엇을 남기고 무엇을 요약할지 설명합니다.
핵심 기준: 선택, 필터링, 집계¶
- 한 열 선택과 여러 열 선택의 결과가 어떻게 다른지 설명할 수 있습니다.
loc는 라벨(label),iloc는 위치(position)를 기준으로 읽는다고 설명할 수 있습니다.- 불리언(Boolean) 조건으로 행을 거른다는 뜻을 설명할 수 있습니다.
- 집계는 원래 표 전체를 더 작은 요약값으로 바꾸는 과정이라고 설명할 수 있습니다.
groupby를 같은 범주끼리 먼저 묶고 나서 요약하는 방식으로 설명할 수 있습니다.
세 가지 기준¶
| 기준 | 왜 중요한가 | 이 절에서 필요한 이해 수준 |
|---|---|---|
| 열 선택과 행 필터의 차이 | 읽을 대상과 남길 대상을 섞지 않게 해 줍니다. | 하나는 무엇을 읽을지 고르고, 다른 하나는 무엇을 남길지 고른다고 이해합니다. |
loc와 iloc가 왜 나뉘는가 | 라벨 기준과 위치 기준을 혼동하지 않게 해 줍니다. | loc는 라벨, iloc는 위치를 기준으로 읽는다고 이해합니다. |
groupby가 무엇을 하는가 | 표 전체를 범주별 요약으로 바꾸는 흐름을 분명하게 해 줍니다. | 같은 범주끼리 묶은 뒤 요약값을 계산하는 방식으로 이해합니다. |
| 용어 | 이 절에서 먼저 잡을 뜻 |
|---|---|
| Series | 인덱스가 붙은 1차원 값 열입니다. |
| 필터링(filtering) | 조건에 맞는 행만 남기는 선택 방식입니다. |
| 집계(aggregation) | 여러 값을 평균, 합, 개수 같은 더 작은 요약값으로 바꾸는 과정입니다. |
groupby | 같은 범주끼리 먼저 묶은 뒤 각 묶음별 요약을 계산하는 방식입니다. |
loc / iloc | 각각 라벨 기준, 위치 기준으로 행과 열을 고르는 도구입니다. |
이 절 다음 흐름도 단순합니다.
P2-12.3에서는 지금 선택하고 요약한 표가 실제 데이터셋 준비와 누수 방지 문맥에서 어떻게 이어지는지 봅니다.- 이후 Pandas 실습과 모델 입력 준비 구간에서는 같은 질문이
어떤 열을 남기고 어떤 요약을 만들 것인가로 반복됩니다.
예제 표를 먼저 고정한다¶
이 절에서는 다음 작은 표를 계속 사용합니다.
문제 상황: 선택, 필터링, 집계 예제를 같은 표로 이어서 보려면 기준이 되는 작은 DataFrame을 먼저 만들어야 합니다. 입력(input): 이름, 점수, 합격 여부, 지역을 담은 네 열. 기대 출력(output): 네 학생이 들어 있는 예제 표가 출력됩니다. 확인할 개념: 이후의 모든 선택과 필터링은 같은 표를 기준으로 질문만 달리하는 흐름입니다.
출력은 다음처럼 읽을 수 있습니다.
이 표를 보고 우리는 “전체를 다 보는 것”에서 시작하지만, 곧바로 “어느 열?”, “어느 행?”, “어떤 조건?”이라는 질문으로 이동합니다.
도식으로 보면 이 절의 흐름은 다음과 같습니다.
flowchart TD
full["전체 표<br/>모든 행, 모든 열"]
col["열 선택<br/>어떤 변수를 볼 것인가"]
row["행 선택<br/>어떤 사례를 볼 것인가"]
cond["필터링<br/>어떤 행을 남길 것인가"]
agg["집계<br/>어떤 요약값이면 충분한가"]
full --> col
full --> row
full --> cond --> agg
한 열을 고르면 Series가 된다¶
Pandas에서는 한 열을 고를 수 있습니다.
문제 상황: 점수 열 하나만 꺼내면 결과가 표가 아니라 어떤 형태로 바뀌는지 확인하고 싶습니다. 입력(input): df["score"]. 기대 출력(output): 점수만 담긴 1차원 Series 출력. 확인할 개념: 한 열 선택은 보통 DataFrame이 아니라 Series를 돌려줍니다.
출력은 대략 다음처럼 보입니다.
여기서 중요한 점은 결과가 DataFrame이 아니라 Series라는 것입니다. Series는 한 줄짜리 표가 아니라, 인덱스가 붙은 1차원 값 열로 읽을 수 있습니다.
여기서는 다음 차이를 먼저 기억해 두면 됩니다.
df["score"]: 한 열을 꺼낸다. 결과는 보통Seriesdf[["name", "score"]]: 여러 열을 고른다. 결과는DataFrame
예를 들어:
문제 상황: 이름과 점수를 함께 남기면 한 열 선택과 결과 형태가 어떻게 달라지는지 비교하고 싶습니다. 입력(input): df[["name", "score"]]. 기대 출력(output): 두 열이 유지된 작은 DataFrame. 확인할 개념: 여러 열을 고르면 원래 표 구조의 일부가 남습니다.
출력은 여전히 표 모양입니다.
즉, 한 열을 고르면 값 열 하나를 읽는 느낌이 강해지고, 여러 열을 고르면 원래 표의 일부를 떼어 보는 느낌이 남습니다.
같은 차이를 표로 보면 더 분명합니다.
| 코드 | 결과 형태 | 읽는 질문 |
|---|---|---|
df["score"] | Series | 점수 열 값만 보고 싶은가 |
df[["name", "score"]] | DataFrame | 이름과 점수를 함께 비교하고 싶은가 |
작은 점검 코드도 useful합니다.
문제 상황: 한 열 선택과 여러 열 선택의 반환 타입을 직접 확인하고 싶습니다. 입력(input): df["score"]와 df[["name", "score"]]. 기대 출력(output): Series, DataFrame이라는 타입 이름 두 줄. 확인할 개념: 같은 선택처럼 보여도 반환 객체는 달라질 수 있습니다.
출력은 대략 다음처럼 읽힙니다.
loc는 라벨, iloc는 위치를 기준으로 읽는다¶
Pandas 공식 문서는 .loc를 라벨 기반(label-based) 선택으로, .iloc를 정수 위치 기반(integer position-based) 선택으로 설명합니다.
여기서는 다음처럼 구분합니다.
loc: 이름표를 보고 고른다.iloc: 몇 번째 위치인지 보고 고른다.
예를 들어 현재 기본 인덱스가 0, 1, 2, 3일 때:
문제 상황: 기본 숫자 인덱스에서는 loc와 iloc가 비슷해 보여 차이를 놓치기 쉽습니다. 입력(input): df.loc[1], df.iloc[1]. 기대 출력(output): 둘 다 두 번째 학생 행을 가리키는 출력. 확인할 개념: 지금 결과가 같아 보여도 기준은 라벨과 위치로 다릅니다.
둘 다 두 번째 행을 가리키는 것처럼 보일 수 있습니다. 지금은 인덱스 라벨도 숫자이고 위치도 숫자이기 때문입니다.
하지만 인덱스를 이름으로 바꾸면 차이가 더 분명해집니다.
문제 상황: 라벨 기준 선택과 위치 기준 선택의 차이를 더 분명하게 보고 싶습니다. 입력(input): name을 인덱스로 바꾼 named, 그리고 loc/iloc 호출. 기대 출력(output): Lee 라벨과 세 번째 위치가 각각 선택됩니다. 확인할 개념: loc는 이름표를 보고, iloc는 순서를 보고 고릅니다.
이때:
named.loc["Lee"]는Lee라는 라벨을 찾습니다.named.iloc[2]는 세 번째 위치의 행을 찾습니다.
이 구분은 매우 중요합니다. 표를 읽을 때 “이름으로 고르는가, 순서로 고르는가”가 다르기 때문입니다.
작은 표로 정리하면:
| 코드 | 기준 | 의미 |
|---|---|---|
df.loc[1] | 라벨 | 인덱스 라벨이 1인 행 |
df.iloc[1] | 위치 | 두 번째 위치의 행 |
named.loc["Lee"] | 라벨 | 이름이 Lee인 행 |
named.iloc[2] | 위치 | 세 번째 위치의 행 |
조건 필터는 행을 남기거나 버린다¶
표를 읽을 때 가장 자주 하는 일 중 하나는 조건에 맞는 행만 남기는 것입니다.
문제 상황: 점수가 80 이상인 학생만 남기고 싶습니다. 입력(input): df["score"] >= 80 조건을 적용한 표. 기대 출력(output): Kim과 Lee만 남은 부분 표. 확인할 개념: 조건 필터는 행 값을 바꾸는 것이 아니라 남길 행을 고르는 일입니다.
출력은 대략 다음처럼 보입니다.
이 코드는 두 단계로 읽을 수 있습니다.
df["score"] >= 80이 각 행마다True또는False를 만든다.True인 행만 남긴다.
중간 결과를 직접 보면 더 분명합니다.
문제 상황: 필터가 내부적으로 어떤 True/False 목록을 만드는지 먼저 보고 싶습니다. 입력(input): df["score"] >= 80에서 만든 mask. 기대 출력(output): 각 행마다 조건 충족 여부가 적힌 불리언 Series. 확인할 개념: 필터링은 먼저 행별 판단 결과를 만들고, 그다음 True만 남깁니다.
이런 불리언 결과를 종종 mask라고 부릅니다. 필터링은 각 행에 질문을 던져서, 맞다(True)고 대답한 행만 남기는 일로 읽으면 됩니다.
조건은 여러 개를 함께 쓸 수도 있습니다.
문제 상황: 점수와 지역 조건을 동시에 만족하는 행만 남기고 싶습니다. 입력(input): 점수 70 이상이면서 region == "Busan"인 복합 조건. 기대 출력(output): 조건을 둘 다 만족하는 Choi 행만 남은 표. 확인할 개념: 불리언 조건은 & 같은 연산자로 결합할 수 있습니다.
이 코드는 점수가 70 이상이면서 지역이 Busan인 행만 남깁니다.
필터 전후를 표로 보면 다음처럼 읽을 수 있습니다.
| 단계 | 남는 행 |
|---|---|
| 원본 표 | Kim, Park, Lee, Choi |
df["score"] >= 80 | Kim, Lee |
(df["score"] >= 70) & (df["region"] == "Busan") | Choi |
즉, 필터는 값을 바꾸기보다 남길 행을 고르는 일에 가깝습니다.
선택과 필터링은 질문 방식이 다르다¶
처음 배울 때는 선택과 필터링이 비슷해 보일 수 있습니다. 하지만 질문이 다릅니다.
| 작업 | 질문 |
|---|---|
| 열 선택 | 어떤 변수만 볼 것인가 |
| 행 선택 | 몇 번째 사례, 어떤 라벨의 사례를 볼 것인가 |
| 조건 필터 | 어떤 조건을 만족하는 사례만 남길 것인가 |
예를 들어:
문제 상황: 열 선택, 한 행 선택, 조건 필터가 표를 서로 다르게 좁힌다는 점을 한 번에 비교하고 싶습니다. 입력(input): df[["name", "score"]], df.loc[2], df[df["passed"] == "yes"]. 기대 출력(output): 열만 줄인 표, 한 행 출력, 조건에 맞는 여러 행 출력. 확인할 개념: 표를 좁히는 동작이라도 질문 방식에 따라 결과 형태가 달라집니다.
이 세 코드는 모두 표를 좁히지만, 좁히는 기준이 서로 다릅니다.
- 첫 번째는 열을 줄입니다.
- 두 번째는 한 행을 집어 봅니다.
- 세 번째는 조건에 맞는 여러 행을 남깁니다.
이 차이를 구분해야 나중에 코드가 길어져도 무엇을 하고 있는지 놓치지 않습니다.
하나의 질문을 세 방식으로 읽어 보면 더 분명합니다.
문제 상황: 같은 데이터라도 열 선택, 행 선택, 조건 필터 후 열 선택이 어떻게 이어지는지 보고 싶습니다. 입력(input): 세 가지 다른 Pandas 선택 코드. 기대 출력(output): 목적에 따라 서로 다른 범위로 좁혀진 결과들. 확인할 개념: Pandas 코드는 질문을 작은 단계로 쪼개어 표 범위를 줄이는 방식입니다.
이 세 줄은 각각 다음을 보여 줍니다.
- 열을 줄여서 본 표
- 한 사례만 떼어 본 행
- 조건에 맞는 사례만 남긴 뒤 필요한 열만 다시 본 표
집계는 표를 더 작은 요약으로 바꾼다¶
집계(aggregation)는 원래 표를 요약값으로 바꾸는 과정입니다.
예를 들어:
문제 상황: 전체 점수 열을 숫자 몇 개로 요약해 보고 싶습니다. 입력(input): score 열에 대한 평균, 최댓값, 개수 집계. 기대 출력(output): 점수 분포를 요약하는 세 개의 숫자. 확인할 개념: 집계는 여러 행을 더 작은 요약 결과로 압축합니다.
출력은 각각 다음 질문에 답합니다.
- 평균(mean): 점수의 중심은 어디쯤인가
- 최댓값(max): 가장 큰 값은 무엇인가
- 개수(count): 값이 몇 개 있는가
표 전체를 그대로 보는 대신, 숫자 몇 개로 요약하는 것이 집계의 핵심입니다.
이 절에서는 집계를 “통계를 계산한다”보다 더 넓게 봅니다. 집계는 많은 행을 더 작은 수의 결과로 압축하는 일로 이해하면 됩니다.
작은 예를 보면:
문제 상황: 평균 하나만 따로 출력하면 집계가 표를 어떻게 단순화하는지 더 쉽게 볼 수 있습니다. 입력(input): df["score"].mean(). 기대 출력(output): 점수 평균 하나. 확인할 개념: 집계 결과는 표 전체를 대체하지 않지만 중심을 빠르게 보여 줍니다.
이 숫자 하나는 표 전체를 대체하지는 못합니다. 하지만 빠르게 중심값을 보는 데는 유용합니다.
집계를 한 번에 묶어 보면 다음처럼 읽을 수도 있습니다.
문제 상황: 평균, 최댓값, 개수를 한 번에 점검하고 싶습니다. 입력(input): df["score"].agg(["mean", "max", "count"]). 기대 출력(output): 여러 집계 결과가 묶인 작은 요약 출력. 확인할 개념: 하나의 열도 여러 집계 기준으로 동시에 읽을 수 있습니다.
출력은 대략 다음처럼 보일 수 있습니다.
이 결과는 score 열 하나를 여러 방식으로 요약한 작은 표처럼 읽을 수 있습니다.
groupby는 같은 범주끼리 묶고 나서 요약한다¶
Pandas 공식 문서는 groupby를 데이터를 어떤 기준으로 나눈 뒤, 각 그룹에 함수를 적용해 결합하는 흐름으로 설명합니다. 여기서는 groupby를 같은 값을 가진 행들끼리 먼저 묶고, 그 묶음마다 집계를 하는 방식으로 읽으면 됩니다.
예를 들어 지역별 평균 점수를 보고 싶다면:
문제 상황: 개별 학생 점수 대신 지역별 평균 점수로 질문 단위를 바꾸고 싶습니다. 입력(input): region으로 묶고 score 평균을 계산하는 groupby 코드. 기대 출력(output): Busan과 Seoul의 평균 점수가 따로 나온 요약 결과. 확인할 개념: groupby는 개별 행을 범주별 묶음으로 바꾼 뒤 그 묶음마다 집계합니다.
출력은 대략 다음처럼 보일 수 있습니다.
이 코드는 이렇게 읽습니다.
region값이 같은 행끼리 묶는다.- 각 묶음에서
score열만 본다. - 각 묶음의 평균을 계산한다.
즉, groupby는 단순 평균보다 “어떤 기준으로 나누어 본 평균인가”를 드러내는 도구입니다.
원래 표와 groupby 결과를 나란히 놓고 보면 변화가 더 잘 보입니다.
| 원래 표의 질문 | groupby 이후 질문 |
|---|---|
| 각 학생의 점수는 얼마인가 | 지역별 평균 점수는 얼마인가 |
| 행이 몇 개인가 | 범주가 몇 개인가 |
| 개별 사례를 본다 | 범주 요약을 본다 |
이 점이 중요합니다. groupby는 데이터를 정렬하는 기능이 아니라, 읽는 단위를 개별 행에서 범주별 묶음으로 바꾸는 기능에 가깝습니다.
표를 읽을 때는 한 행이 곧바로 하나의 완성 사례가 아닐 수도 있습니다. 예를 들어 동작 중 기록된 원시 로그에서는 여러 행이 함께 하나의 동작 기록을 이루기도 합니다. 이때는 먼저 동작 식별자 열로 묶고, 그 안에서 길이, 구간 평균, 마지막 값 같은 정보를 요약해 동작 단위 표를 다시 만드는 편이 더 자연스럽습니다.
| event_id | elapsed_seconds | progress_fraction | signal_a |
|---|---|---|---|
| A-01 | 0.0 | 0.00 | 0.8 |
| A-01 | 1.0 | 0.20 | 1.4 |
| A-01 | 2.0 | 0.40 | 1.9 |
| B-02 | 0.0 | 0.00 | 0.7 |
| B-02 | 1.0 | 0.25 | 1.3 |
| B-02 | 2.0 | 0.50 | 1.5 |
| event_id | total_duration_seconds | signal_a_mean | end_signal_a |
|---|---|---|---|
| A-01 | 2.0 | 1.37 | 1.9 |
| B-02 | 2.0 | 1.17 | 1.5 |
문제 상황: 여러 행으로 기록된 원시 로그를 동작 단위 요약 표로 다시 바꾸고 싶습니다. 입력(input): event_id로 묶은 뒤, 시간 길이와 센서 값 요약을 계산하는 코드. 기대 출력(output): 각 event_id마다 한 행만 남는 요약 DataFrame. 확인할 개념: groupby는 같은 범주끼리 묶는 기능일 뿐 아니라, 여러 행을 한 사례 단위로 다시 읽게 만드는 도구이기도 합니다.
출력은 다음처럼 읽을 수 있습니다.
임계값을 바꾸면 필터와 집계가 함께 움직인다¶
앞의 작은 표는 Pandas 문법을 읽기 위한 설명형 예제입니다. 하지만 실제 표에서는 조건값을 바꾸면 남는 행과 집계가 함께 달라지는지 확인해야 합니다.
입력 파일은 student-progress-samples.csv입니다. 한 행은 학생 한 명의 학습 기록이고, 핵심 열은 region, study_hours, absences, practice_quizzes, score, passed입니다. 여기서는 pass_threshold와 focus_region을 바꾸며 어떤 행이 남고 지역별 요약이 어떻게 달라지는지 봅니다.
문제 상황: 점수 임계값과 지역 조건을 바꾸면 필터 결과와 지역별 요약이 함께 달라지는지 확인하고 싶습니다. 입력(input): 36행 학생 진행도 CSV, pass_threshold, focus_region. 기대 출력(output): 조건에 맞는 행 목록과 지역별 평균 점수, 임계값 이상 학생 수. 확인할 개념: 조건 필터와 groupby 집계는 고정 정답을 확인하는 코드가 아니라, 기준값을 바꿀 때 남는 행과 요약이 어떻게 움직이는지 관찰하는 도구입니다.
같은 코드는 p2_12_2_filter_aggregate_threshold.py로도 실행할 수 있습니다. pass_threshold를 70, 75, 80으로 바꾸면 임계값 이상 학생 수가 바뀌고, focus_region을 다른 지역으로 바꾸면 선택된 행 목록이 달라집니다.
표를 읽는 흐름을 도식으로 보면¶
선택, 필터링, 집계는 대개 다음 흐름으로 이어집니다.
flowchart TD
frame["DataFrame<br/>full table"]
select["select columns<br/>what variables matter?"]
filter["filter rows<br/>which cases stay?"]
agg["aggregate<br/>what summary is enough?"]
group["groupby<br/>summary by category"]
frame --> select --> filter --> agg --> group
실제 작업에서는 이 순서가 항상 고정되지는 않습니다. 그래도 “표를 그대로 들고 있기보다, 질문에 맞게 점점 좁히고 요약한다”는 흐름은 계속 중요합니다.
사례 및 예시¶
사례 1. 불합격 학생만 다시 보고 싶은 성적표¶
교사가 성적표를 보고 누가 불합격했는지, 불합격 학생의 점수와 지역만 다시 보고 싶은지, 지역별 평균 점수는 어떤지를 확인한다고 해 보겠습니다. 사람은 머릿속으로 표를 훑으며 필요한 부분만 다시 볼 수 있지만, 데이터 작업에서는 그 과정을 선택, 필터링, 집계로 명시해야 합니다.
먼저 passed 열로 불합격 학생만 남기면 어떤 행을 볼지 정한 셈입니다. 그다음 name과 score만 다시 고르면 무엇을 읽을지 정한 셈입니다. 마지막으로 groupby("region")["score"].mean()을 하면 개별 학생 표를 지역별 요약으로 압축하게 됩니다.
이 사례는 세 동작의 차이를 한 번에 보여 줍니다. 열 선택은 어떤 변수만 볼 것인가, 행 선택과 필터링은 어떤 사례를 남길 것인가, 집계는 전체를 어떤 요약값으로 읽을 것인가를 정합니다. 표를 다루는 일은 단순히 코드를 외우는 것이 아니라, 질문을 더 작은 단계로 나누는 일에 가깝습니다.
그래서 Pandas 코드는 짧아 보여도 질문 구조를 함께 읽어야 합니다. 같은 성적표라도 한 학생만 보기, 조건에 맞는 여러 학생 보기, 범주별 평균 보기는 서로 다른 읽기 동작이며, 이 차이를 구분해야 이후 데이터셋 준비와 모델 입력 구성도 헷갈리지 않습니다.
체크리스트¶
- 한 열 선택과 여러 열 선택의 차이를 설명할 수 있는가?
loc와iloc가 각각 무엇을 기준으로 고르는지 말할 수 있는가?- 불리언 조건이 행을 남기거나 버리는 방식임을 설명할 수 있는가?
- 평균, 개수, 최댓값 같은 집계가 왜 필요한지 설명할 수 있는가?
groupby를묶고 나서 요약한다는 흐름으로 설명할 수 있는가?- 한 열 선택은
Series, 여러 열 선택은DataFrame으로 읽는 경우가 많다는 점을 설명할 수 있는가?
출처와 참고 자료¶
- pandas Developers, Indexing and selecting data, pandas 3.0.4 documentation, 확인 날짜: 2026-07-20. 열 선택,
loc/iloc, 불리언 인덱싱과 행 필터링 설명 확인에 사용했다. - pandas Developers, Group by: split-apply-combine, pandas 3.0.4 documentation, 확인 날짜: 2026-07-20.
groupby를 split-apply-combine 흐름으로 설명하는 근거로 사용했다. - pandas Developers, 10 minutes to pandas, pandas 3.0.4 documentation, 확인 날짜: 2026-07-20. DataFrame 생성, 선택, 요약 통계, 기본 표 조작 예시 확인에 사용했다.