11. 열 선택·추가·삭제와 요소 선택

🎯 이 장의 목표
  • 데이터프레임에서 열을 선택·추가·삭제한다
  • .loc(라벨 기반)와 .iloc(위치 기반)로 행·열·값을 정확히 꺼낸다
  • 조건으로 행을 필터링하고, 브로드캐스팅으로 한 번에 값을 바꾼다
💡 팁
실습용 데이터를 먼저 준비합니다. 각 코드 앞에 이 셋업이 있다고 가정하세요.
PYTHON
import pandas as pd

df = pd.DataFrame({
    "이름": ["철수", "영희", "민수", "지수"],
    "나이": [20, 22, 25, 19],
    "도시": ["서울", "부산", "서울", "인천"],
    "점수": [85, 92, 78, 95]
})

열 선택하기

한 개 열 선택 → 시리즈

대괄호 []에 열 이름을 넣으면 그 열(시리즈)이 나옵니다.

PYTHON
print(df["이름"])
print(type(df["이름"]))

실행 결과:

CODE
0    철수
1    영희
2    민수
3    지수
Name: 이름, dtype: object
<class 'pandas.core.series.Series'>

열 하나를 꺼내면 앞서 배운 시리즈가 나온다는 점을 확인하세요.

여러 열 선택 → 데이터프레임

대괄호 안에 열 이름 리스트를 넣으면 여러 열이 데이터프레임으로 나옵니다.

PYTHON
print(df[["이름", "점수"]])

실행 결과:

CODE
   이름  점수
0  철수  85
1  영희  92
2  민수  78
3  지수  95
⚠️ 흔한 실수
흔한 실수 — 대괄호 두 겹
여러 열을 고를 땐 df[["이름", "점수"]]처럼 대괄호가 두 겹입니다. 바깥 []는 "선택", 안쪽 []는 "열 이름들의 리스트"입니다. df["이름", "점수"](한 겹)는 에러가 납니다.

열 추가하기

새 열은 없는 열 이름에 값을 할당하면 자동으로 생깁니다.

PYTHON
df["합격"] = df["점수"] >= 80      # 조건 결과(참/거짓)를 새 열로
df["점수_보정"] = df["점수"] + 5    # 계산 결과를 새 열로
print(df)

실행 결과:

CODE
   이름  나이  도시  점수    합격  점수_보정
0  철수  20  서울  85   True     90
1  영희  22  부산  92   True     97
2  민수  25  서울  78  False     83
3  지수  19  인천  95   True    100
💡 팁
이렇게 기존 데이터로 새 의미 있는 열을 만드는 것기능 엔지니어링(feature engineering)이라 합니다. 분석의 핵심 기술이며 12장에서 더 깊이 다룹니다.

열 삭제하기

drop으로 삭제합니다. 열을 지울 땐 axis=1(또는 columns=)을 줍니다.

PYTHON
df2 = df.drop(columns=["점수_보정"])    # 권장: 명확함
# df2 = df.drop("점수_보정", axis=1)    # 같은 결과
print(df2.columns)

실행 결과:

CODE
Index(['이름', '나이', '도시', '점수', '합격'], dtype='object')
🔑 새 용어 — axis
axis는 "축" 방향입니다. axis=0은 행 방향(세로), axis=1은 열 방향(가로)입니다. 헷갈리면 columns=index=로 명시하는 편이 안전합니다(drop(columns=...), drop(index=...)).

⚠️ drop정렬처럼 새 데이터프레임을 돌려줄 뿐 원본은 그대로입니다. 결과를 쓰려면 다시 변수에 담으세요.

.loc.iloc: 행·열·값을 정확히 꺼내기

이 둘은 데이터프레임에서 데이터를 꺼내는 가장 중요한 도구입니다. 차이를 분명히 해 둡시다.

🔑 핵심 구분
  • .loc : 라벨(이름)로 선택. df.loc[행라벨, 열이름]
  • .iloc : 위치 번호(0,1,2…)로 선택. df.iloc[행번호, 열번호]

"loc = location by label", "iloc = location by integer"로 외우면 됩니다.

.loc — 라벨로 선택

PYTHON
print(df.loc[0])              # 0번 라벨의 행 전체
print("---")
print(df.loc[0, "이름"])       # 0번 행의 '이름' 값
print("---")
print(df.loc[0:2, ["이름", "점수"]])  # 0~2번 행의 두 열

실행 결과:

CODE
이름     철수
나이     20
도시     서울
점수     85
합격    True
Name: 0, dtype: object
---
철수
---
   이름  점수
0  철수  85
1  영희  92
2  민수  78
⚠️ 흔한 실수
.loc의 슬라이싱 0:22번을 포함합니다(라벨 슬라이싱). 9장에서 본 규칙과 같습니다.

.iloc — 위치 번호로 선택

PYTHON
print(df.iloc[0])             # 첫 번째 행
print("---")
print(df.iloc[0, 0])          # 첫 행, 첫 열의 값
print("---")
print(df.iloc[0:2, 0:2])      # 처음 2행, 처음 2열 (2는 제외!)

실행 결과:

CODE
이름     철수
나이     20
도시     서울
점수     85
합격    True
Name: 0, dtype: object
---
철수
---
   이름  나이
0  철수  20
1  영희  22
⚠️ 흔한 실수
.iloc의 슬라이싱 0:22번을 제외합니다(위치 슬라이싱). .loc과 정반대이니 꼭 구분하세요.
.loc.iloc
기준라벨(이름)위치 번호
슬라이싱 끝포함제외
df.loc[0, "이름"]df.iloc[0, 0]

조건으로 행 필터링하기

데이터 분석에서 가장 많이 쓰는 작업입니다. 조건을 대괄호에 넣으면 조건이 참인 행만 남습니다.

PYTHON
print(df[df["점수"] >= 90])           # 점수 90 이상인 행

실행 결과:

CODE
   이름  나이  도시  점수    합격  점수_보정
1  영희  22  부산  92  True     97
3  지수  19  인천  95  True    100

여러 조건은 &(그리고), |(또는)로 묶고, 각 조건을 괄호로 감쌉니다.

PYTHON
print(df[(df["점수"] >= 80) & (df["도시"] == "서울")])

실행 결과:

CODE
   이름  나이  도시  점수   합격  점수_보정
0  철수  20  서울  85  True     90
⚠️ 흔한 실수
흔한 실수 두 가지
1. and/or가 아니라 &/|를 씁니다(Pandas 조건에선 기호를 사용).
2. 각 조건을 괄호로 감싸야 합니다. (df["점수"] >= 80) & (df["도시"] == "서울"). 괄호를 빠뜨리면 엉뚱한 에러가 납니다.

브로드캐스팅: 한 번에 값 바꾸기

NumPy 벡터화처럼, 하나의 값을 여러 칸에 한 번에 퍼뜨리는 것을 브로드캐스팅(broadcasting)이라 합니다.

PYTHON
df["보너스"] = 10          # 모든 행에 10을 한 번에
df["점수"] = df["점수"] * 1.1  # 모든 점수에 10% 가산
print(df[["이름", "점수", "보너스"]])

실행 결과:

CODE
   이름     점수  보너스
0  철수   93.5   10
1  영희  101.2   10
2  민수   85.8   10
3  지수  104.5   10

10이라는 하나의 값이 모든 행에 퍼졌고(보너스), * 1.1이 모든 점수에 적용됐습니다(브로드캐스팅).

특정 조건의 칸만 바꿀 수도 있습니다 (.loc 활용).

PYTHON
# 점수가 100 넘는 사람은 100으로 맞추기
df.loc[df["점수"] > 100, "점수"] = 100
print(df[["이름", "점수"]])

실행 결과:

CODE
   이름     점수
0  철수   93.5
1  영희  100.0
2  민수   85.8
3  지수  100.0

읽는 법: "점수 > 100인 행의 점수 열을 100으로 바꿔라."

🛠 미니 챌린지

아래 데이터로 시작하세요.

PYTHON
import pandas as pd
df = pd.DataFrame({
    "상품": ["연필", "공책", "지우개", "볼펜", "자"],
    "가격": [500, 1200, 300, 800, 600],
    "재고": [50, 20, 0, 35, 10]
})
  1. 가격이 700원 이상인 상품만 골라 출력하세요.
  2. 가격 × 재고를 계산한 재고가치라는 새 열을 만드세요.
  3. 재고가 0인 상품만 골라 출력하세요.

✅ 미니 챌린지 해설

PYTHON
# 1. 조건 필터링
print(df[df["가격"] >= 700])

실행 결과:

CODE
   상품    가격  재고
1  공책  1200  20
3  볼펜   800  35
PYTHON
# 2. 새 열 만들기 (기능 엔지니어링)
df["재고가치"] = df["가격"] * df["재고"]
print(df)

실행 결과:

CODE
    상품    가격  재고   재고가치
0   연필   500  50  25000
1   공책  1200  20  24000
2  지우개   300   0      0
3   볼펜   800  35  28000
4    자   600  10   6000
PYTHON
# 3. 재고 0인 상품
print(df[df["재고"] == 0])

실행 결과:

CODE
    상품   가격  재고  재고가치
2  지우개  300   0     0

이 장에서 배운 것

  • 열 선택은 df["열"](시리즈), df[["열1","열2"]](데이터프레임, 대괄호 두 겹).
  • 없는 열 이름에 값을 할당하면 새 열이 생긴다(기능 엔지니어링의 기초).
  • .loc는 라벨로(끝 포함), .iloc는 위치로(끝 제외) 선택한다.
  • 조건 필터링은 df[조건]이며, 여러 조건은 &·|와 괄호로 묶는다.
  • 브로드캐스팅으로 하나의 값을 여러 칸에 한 번에 적용한다.

✍️ 확인 문제

  1. df["점수"]df[["점수"]]의 결과 타입은 각각 무엇인가요?
  2. .loc.iloc의 슬라이싱에서 "끝 번호 포함 여부"는 어떻게 다른가요?
  3. 두 조건 점수>=80도시=='서울'을 동시에 만족하는 행을 고르는 코드를 쓰세요. (괄호와 & 주의)
데이터프레임을 자유롭게 다루게 됐습니다! 다음 부에서는 현실의 지저분한 데이터를 정리하는 법 — 빈칸(결측치) 처리와 기능 엔지니어링, 타입 변환을 배웁니다.
👉 12. 결측치 처리와 기능 엔지니어링