아래 엑셀 파일의 표table 형식으로 제공되는 2차원 데이터를 효율적으로 처리하는 판다스 데이터프레임 자료형을 간단히 소개한다. 데이터프레임의 다양한 기능은 확률과 통계의 기초를 다루면서 하나씩 활용할 예정이다.

기본 설정
numpy와 pandas 라이브러리를 각각 np와 pd로 불러온다.
import numpy as np
import pandas as pd데이터 저장소
data_url = 'https://raw.githubusercontent.com/codingalzi/code-workout-datasci/refs/heads/master/data/'16.1데이터프레임 생성¶
데이터프레임DataFrame은 인덱스를 공유하는 여러 개의 시리즈가 결합된 2차원 데이터구조다.
pd.concat() 함수 활용
pd.concat() 함수는 여러 개의 시리즈 또는 데이터프레임을 묶어 하나의 데이터프레임을 생성한다.
묶는 방식은 축을 지정함으로써 결정되는데,
옆으로 묶으려면 열 단위로 추가한다는 뜻으로 axis=1을 설정하면 된다.
추가되는 각 열의 이름은 시리즈에 저장된 name 속성으로 지정된다.
series1 = pd.Series([4, 5, 6, 3, 1], name="Mango")
series2 = pd.Series([5, 4, 3, 0, 2], name="Apple")
series3 = pd.Series([2, 3, 5, 2, 7], name="Banana")
fruits1 = pd.concat([series1, series2, series3], axis=1)
fruits1자료형은 pd.DataFrame이다.
type(fruits1)pandas.DataFrame각 시리즈의 행 인덱스를 지정하지 않았기에
0부터 시작하는 정수 인덱스가 행 인덱스로 사용되며,
시리즈의 경우처럼 RangeIndex 객체가 데이터프레임의 index 속성에 저장된다.
fruits1.indexRangeIndex(start=0, stop=5, step=1)넘파이 2차원 어레이 활용
넘파이 2차원 어레이를 이용하여 데이터프레임을 생성할 수 있다. 망고, 사과, 바나나 데이터를 담고 있는 아래 어레이를 이용하여 이전과 동일한 데이터프레임을 생성할 수 있다.
fruits_array = np.array([[4, 5, 2],
[5, 4, 3],
[6, 3, 5],
[3, 0, 2],
[1, 2, 7]])데이터프레임 객체를 생성할 때 어레이를 생성자의 인자로 지정하면 된다.
또한 각 열의 이름을 담은 리스트를 columns의 키워드 인자로 지정한다.
fruits1= pd.DataFrame(fruits_array,
columns=['Mango', 'Apple', 'Banana'])
fruits1데이터프레임의 열별 이름을 열 인덱스라고 부르며,
columns 속성에 Index 객체로 저장된다.
fruits1.columnsIndex(['Mango', 'Apple', 'Banana'], dtype='str')시리즈 객체를 생성할 때처럼 행 인덱스를 지정하면서 데이터프레임 객체를 생성할 수 있다. 아래 코드는 A부터 E까지의 영어 대문자 알파벳을 행 인덱스로 지정한다.
fruits1= pd.DataFrame(fruits_array,
columns=['Mango', 'Apple', 'Banana'],
index=['A', 'B', 'C', 'D', 'E'])
fruits1행 인덱스를 별도로 지정하였기에 시리즈의 경우처럼
라벨 Index 객체가 행 인덱스 객체로 지정된다.
fruits1.indexIndex(['A', 'B', 'C', 'D', 'E'], dtype='str')사전 활용
열 이름을 키key로, 리스트를 키의 값value으로 갖는 사전을 이용해 데이터프레임을 생성할 수 있다. 이때 모든 리스트의 길이가 동일해야 한다.
아래 코드에서 fruits_dict는 Mango, Apple, Banana를 키로,
각각의 키에 할당된 리스트를 갖는 사전을 정의한다.
fruits_dict = {'Mango': [4, 5, 6, 3, 1],
'Apple': [5, 4, 3, 0, 2],
'Banana': [2, 3, 5, 2, 7]}위 사전 객체를 데이터프레임으로 변환하면 다음과 같으며, 사전에 사용된 키가 열 인덱스로 자동 지정된다.
fruits1 = pd.DataFrame(fruits_dict)
fruits1위 코드에서 행 인덱스를 별도로 지정하지 않았기에 이 경우에도
RangeIndex 인덱스 객체가 행 인덱스 객체로 지정된다.
fruits1.indexRangeIndex(start=0, stop=5, step=1)CSV 파일 활용
아래 코드는 피어슨 아버지-아들 키 데이터셋을 데이터프레임으로 불러온다. CSV 파일에 헤더를 지정하면 각 열의 라벨로 함께 불러온다.
pearson_df = pd.read_csv(data_url+"pearson_dataset.csv", header=0)
pearson_dfDatetimeIndex 활용
pd.date_range() 함수는 규칙적인 간격의 날짜와 시간으로 구성된 인덱스 자료형을 생성한다.
아래 함수 호출에 사용된 키워드 인자의 의미는 다음과 같다.
start="20260301": 2026년 3월 1일부터 시작periods=5: 첫째 인자로 지정된 시간부터 5 개의 시간 데이터 샘플 생성freq="D": 간격은 일(Day) 단위로 지정
dates = pd.date_range(start="20260301", periods=5, freq="D")
datesDatetimeIndex(['2026-03-01', '2026-03-02', '2026-03-03', '2026-03-04',
'2026-03-05'],
dtype='datetime64[us]', freq='D')데이터분석에서 DatetimeIndex 객체를 행 인덱스로의 활용은 빈번히 발생한다.
아래 코드는 행 인덱스를 앞서 정의 한 dates가 가리키는 시간 객체로 지정한다.
그러면 마치 날짜별 과일 재고량 또는 판매량을 담은 데이터셋으로 해석될 수 있게 된다.
fruits_date = pd.DataFrame(fruits_dict, index=dates)
fruits_date16.1.1연습문제¶
문제 1
아래 코드는 2026년 3월 1일 0시부터 1시간 단위로 변하는 48개,
즉 이틀 동안의 시간 데이터로 구성된 DatetimeIndex 객체를 활용한다.
two_days = pd.date_range(start="20260301", periods=48, freq="h")
two_daysDatetimeIndex(['2026-03-01 00:00:00', '2026-03-01 01:00:00',
'2026-03-01 02:00:00', '2026-03-01 03:00:00',
'2026-03-01 04:00:00', '2026-03-01 05:00:00',
'2026-03-01 06:00:00', '2026-03-01 07:00:00',
'2026-03-01 08:00:00', '2026-03-01 09:00:00',
'2026-03-01 10:00:00', '2026-03-01 11:00:00',
'2026-03-01 12:00:00', '2026-03-01 13:00:00',
'2026-03-01 14:00:00', '2026-03-01 15:00:00',
'2026-03-01 16:00:00', '2026-03-01 17:00:00',
'2026-03-01 18:00:00', '2026-03-01 19:00:00',
'2026-03-01 20:00:00', '2026-03-01 21:00:00',
'2026-03-01 22:00:00', '2026-03-01 23:00:00',
'2026-03-02 00:00:00', '2026-03-02 01:00:00',
'2026-03-02 02:00:00', '2026-03-02 03:00:00',
'2026-03-02 04:00:00', '2026-03-02 05:00:00',
'2026-03-02 06:00:00', '2026-03-02 07:00:00',
'2026-03-02 08:00:00', '2026-03-02 09:00:00',
'2026-03-02 10:00:00', '2026-03-02 11:00:00',
'2026-03-02 12:00:00', '2026-03-02 13:00:00',
'2026-03-02 14:00:00', '2026-03-02 15:00:00',
'2026-03-02 16:00:00', '2026-03-02 17:00:00',
'2026-03-02 18:00:00', '2026-03-02 19:00:00',
'2026-03-02 20:00:00', '2026-03-02 21:00:00',
'2026-03-02 22:00:00', '2026-03-02 23:00:00'],
dtype='datetime64[us]', freq='h')(1) DatetimeIndex 클래스는 Index 클래스의 자식 클래스며,
Index 객체는 인덱싱과 슬라이싱을 지원한다.
two_days가 가리키는 DatetimeIndex 객체에 포함된 0번과 24번 인덱스의 값을 확인하라.
답:
리스트 인덱싱처럼 적용하면 되며,
Timestamp 자료형의 객체가 생성된다.
0번 인덱스: 2026년 3월 1일 0시
two_days[0]Timestamp('2026-03-01 00:00:00')24번 인덱스: 2026년 3월 2일 0시
two_days[24]Timestamp('2026-03-02 00:00:00')(2) 정수 인덱스로 구성된 리스트를 사용하면
리스트에 포함된 인덱스에 해당하는 시간으로 구성된 DatetimeIndex 객체가 생성된다.
0번과 24번 인덱스의 시간으로 구성된 DatetimeIndex 객체를 생성하라.
답:
[0, 24]를 인덱싱에 활용한다.
two_days[[0, 24]]DatetimeIndex(['2026-03-01', '2026-03-02'], dtype='datetime64[us]', freq=None)이처럼 리스트를 활용한 인덱싱을 팬시 인덱싱이라 부른다. 이후 데이터프레임 인덱싱을 설명할 때 보다 자세히 다룬다.
(3) 2026년 3월 2일 0시부터 3월 2일 오전 11시까지의 시간을 담은 DatetimeIndex 객체를 생성하라.
답:
3월 2일 0시는 24번 인덱스, 3월 2일 오전 11시는 35번 인덱스에 위치하기에 다음과 같이 슬라이싱을 적용한다.
two_days[24:36]DatetimeIndex(['2026-03-02 00:00:00', '2026-03-02 01:00:00',
'2026-03-02 02:00:00', '2026-03-02 03:00:00',
'2026-03-02 04:00:00', '2026-03-02 05:00:00',
'2026-03-02 06:00:00', '2026-03-02 07:00:00',
'2026-03-02 08:00:00', '2026-03-02 09:00:00',
'2026-03-02 10:00:00', '2026-03-02 11:00:00'],
dtype='datetime64[us]', freq='h')문제 2
pd.date_range() 함수를 활용하는 문제다.
(1) one_day 변수가 2026년 4월 1일 0시부터 밤 11시까지,
총 24개의 시간으로 구성된 DatetimeIndex 객체를 가리키도록 하라.
답:
pd.date_range() 함수를 이용한다.
one_day = pd.date_range(start="20260401", periods=24, freq="h")
one_dayDatetimeIndex(['2026-04-01 00:00:00', '2026-04-01 01:00:00',
'2026-04-01 02:00:00', '2026-04-01 03:00:00',
'2026-04-01 04:00:00', '2026-04-01 05:00:00',
'2026-04-01 06:00:00', '2026-04-01 07:00:00',
'2026-04-01 08:00:00', '2026-04-01 09:00:00',
'2026-04-01 10:00:00', '2026-04-01 11:00:00',
'2026-04-01 12:00:00', '2026-04-01 13:00:00',
'2026-04-01 14:00:00', '2026-04-01 15:00:00',
'2026-04-01 16:00:00', '2026-04-01 17:00:00',
'2026-04-01 18:00:00', '2026-04-01 19:00:00',
'2026-04-01 20:00:00', '2026-04-01 21:00:00',
'2026-04-01 22:00:00', '2026-04-01 23:00:00'],
dtype='datetime64[us]', freq='h')(2) one_day를 열 인덱스(columns)로 사용하여 (2, 24) 모양의 데이터프레임을 생성하라.
단, 행 인덱스는 ['온도', '습도']로, 항목은 np.arange() 함수를 활용하여 0부터 시작하는 정수로 채운다.
답:
one_day는 길이가 24인 DatetimeIndex 객체이므로 24개의 열을 갖는 데이터프레임의 열 인덱스로 활용할 수 있다.
항목은 np.arange(48)으로 생성한 뒤 reshape(2, 24)로 모양을 변경한다.
weather_df = pd.DataFrame(np.arange(48).reshape(2, 24),
index=['온도', '습도'],
columns=one_day)
weather_df(3) one_day를 행 인덱스로 사용하여 (24, 2) 모양의 데이터프레임을 생성하라.
단, 열 인덱스는 ['온도', '습도']로, 항목은 np.arange() 함수를 활용하여 0부터 시작하는 정수로 채운다.
답:
one_day는 길이가 24인 DatetimeIndex 객체이므로 24개의 행을 갖는 데이터프레임의 행 인덱스로 활용할 수 있다.
항목은 np.arange(48)으로 생성한 뒤 reshape(24, 2)로 모양을 변경한다.
weather_df = pd.DataFrame(np.arange(48).reshape(24, 2),
columns=['온도', '습도'],
index=one_day)
weather_df문제 3
아래 코드는 피어슨 아버지-아들 키 데이터셋에서 아들 키 데이터만 데이터프레임으로 불러온다. CSV 파일에 헤더를 지정하면 지정된 열의 라벨로 함께 불러온다.
sons_df = pd.read_csv(data_url+"pearson_dataset.csv", header=0, usecols=[1])
sons_df헤더에 포함된 열의 이름으로 구성된 리스트를 usecols의 키워드 인자로 지정해서 불러와도 된다.
sons_df = pd.read_csv(data_url+"pearson_dataset.csv", header=0, usecols=['Son'])
sons_dfsons_df는 비록 하나의 열로 구성되었다 하더라도 시리즈가 아닌 데이터프레임 객체다.
자료형을 확인하라.
답:
type(sons_df)pandas.DataFrame16.2데이터프레임 속성¶
사전 객체가 다음과 같이 주어졌다.
pd.Series(range(5), index=list('abcde'), dtype="float32")a 0.0
b 1.0
c 2.0
d 3.0
e 4.0
dtype: float32
abcd_dict = {"A": 1.0,
"B": pd.Series(range(5), dtype="float32"),
"C": np.array([3] * 5, dtype="int32"),
"D": ["test", "train", "test", "train", "test"],}동일한 길이의 시퀀스(리스트, 어레이, 시리즈) 또는 스칼라를 값으로 갖는 사전이므로 데이터프레임 생성에 활용될 수 있으며, 각각의 키가 열 인덱스로 사용된다.
abcd_df = pd.DataFrame(abcd_dict)
abcd_dfdtypes 속성
데이터프레임은 넘파이 어레이와는 다르게 각 열의 자료형이 다른 것을 허용한다.
다만, 열 별 자료형은 하나로 통일되어야 한다.
데이터프레임 abcd_df의 열별 자료형은 다음과 같이 확인한다.
abcd_df.dtypesA float64
B float32
C int32
D str
dtype: objectshape 속성
shape 속성은 데이터프레임의 행과 열의 개수를 튜플로 저장한다.
abcd_df 변수가 가리키는 데이터프레임은 5개의 행과 4개의 열로 구성된다.
abcd_df.shape(5, 4)columns 속성
columns 속성에 열 이름으로 구성된 Index 객체가 저장된다.
abcd_df.columnsIndex(['A', 'B', 'C', 'D'], dtype='str')columns 속성을 이용하여 열의 순서를 변경할 수 있다.
아래 코드는 알파벳 역순으로 열을 지정한다.
dcba_df = pd.DataFrame(abcd_df, columns=['D', 'C', 'B', 'A'])
dcba_dfindex 속성
데이터프레임 abcd_df의 행 인덱스는 자동 지정되었으므로 RangeIndex 객체가 사용되었다.
abcd_df.indexRangeIndex(start=0, stop=5, step=1)name 특성
데이터프레임은 행 인덱스와 열 인덱스 객체 각각에 대해 name 속성을 지정할 수 있다.
아래 코드는 행과 열의 이름을 각각 '품목'과 '번호'로 지정한다.
abcd_df.columns.name = '품목'
abcd_df.index.name = '번호'
abcd_df행과 열의 이름이 지정한 대로 확인된다.
abcd_df.index.name'번호'abcd_df.columns.name'품목'values 속성
데이터프레임의 values 속성은 항목만으로 이루어진 2차원 어레이를 가리킨다.
열 별 자료형이 다른 경우 object로 dtype이 지정된다.
abcd_df.valuesarray([[1.0, 0.0, 3, 'test'],
[1.0, 1.0, 3, 'train'],
[1.0, 2.0, 3, 'test'],
[1.0, 3.0, 3, 'train'],
[1.0, 4.0, 3, 'test']], dtype=object)16.2.1연습문제¶
문제 1
아래 코드는 피어슨 아버지-아들 키 데이터셋을 데이터프레임으로 불러온다. CSV 파일에 헤더를 지정하면 각 열의 라벨로 함께 불러온다.
pearson_df = pd.read_csv(data_url+"pearson_dataset.csv", header=0)
pearson_df(1) pearson_df의 행 인덱스 객체, 열 인덱스 객체, 그리고 데이터프레임의 모양(shape)을 각각 확인하라.
답:
CSV 파일을 불러올 때 행 인덱스를 별도로 지정하지 않았기에 RangeIndex 객체가 사용되며,
헤더로 지정된 첫째 행의 값이 열 인덱스로 사용된다.
pearson_df.indexRangeIndex(start=0, stop=1078, step=1)열 인덱스는 헤더에 포함된 열 이름으로 구성된다.
pearson_df.columnsIndex(['Father', 'Son'], dtype='str')데이터프레임의 모양은 행과 열의 개수로 지정된다.
pearson_df.shape(1078, 2)(2) pearson_df의 열별 자료형(dtypes)을 확인하고, 항목만으로 이루어진 넘파이 2차원 어레이를 values 속성을 이용하여 추출하라.
답:
두 열 모두 키(cm) 데이터이므로 float64 자료형이다.
pearson_df.dtypesFather float64
Son float64
dtype: objectvalues 속성은 행과 열 인덱스를 제외한 항목만으로 구성된 넘파이 2차원 어레이를 가리킨다.
pearson_df.valuesarray([[165.1, 151.9],
[160.8, 160.5],
[165.1, 160.8],
...,
[182.4, 176. ],
[179.6, 176. ],
[178.6, 170.2]], shape=(1078, 2))문제 2
아래 코드는 붓꽃 데이터셋을 데이터프레임으로 불러온다.
header=0으로 굳이 지정하지 않아도 0번 줄을 헤더로 불러온다.
다만, 경우에 따라 헤더가 없는 파일이 있으니 조심해야 하며,
헤더의 존재 여부를 미리 확인해 두어야 한다.
iris_df = pd.read_csv(data_url+"iris.csv") # header=0이 기본값
iris_df(1) 붓꽃 데이터셋의 열별 자료형을 확인하라.
답:
데이터프레임의 dtypes 속성을 확인하면 된다.
iris_df.dtypessepal.length float64
sepal.width float64
petal.length float64
petal.width float64
variety str
dtype: object(2) iris_df의 모양(shape)과 열 인덱스 객체(columns)를 각각 확인하라.
답:
데이터프레임의 모양은 shape 속성에 저장된다.
iris_df.shape(150, 5)데이터프레임의 열 인덱스는 columns 속성에 저장된다.
iris_df.columnsIndex(['sepal.length', 'sepal.width', 'petal.length', 'petal.width',
'variety'],
dtype='str')(3) iris_df의 항목만으로 이루어진 넘파이 2차원 어레이를 values 속성을 이용하여 추출하라.
단, 처음 10개의 행만 출력한다.
답:
values 속성 결과에 대해 슬라이싱을 적용한다.
이때, 속성 확인이 슬라이싱보다 우선순위가 높기에 굳이 괄호를 사용하지 않아도 된다.
iris_df.values[:10]array([[5.1, 3.5, 1.4, 0.2, 'Setosa'],
[4.9, 3.0, 1.4, 0.2, 'Setosa'],
[4.7, 3.2, 1.3, 0.2, 'Setosa'],
[4.6, 3.1, 1.5, 0.2, 'Setosa'],
[5.0, 3.6, 1.4, 0.2, 'Setosa'],
[5.4, 3.9, 1.7, 0.4, 'Setosa'],
[4.6, 3.4, 1.4, 0.3, 'Setosa'],
[5.0, 3.4, 1.5, 0.2, 'Setosa'],
[4.4, 2.9, 1.4, 0.2, 'Setosa'],
[4.9, 3.1, 1.5, 0.1, 'Setosa']], dtype=object)(4) values 속성에 저장된 어레이의 자료형(dtype)을 확인하라.
답:
variety 열이 문자열이므로 넘파이 어레이는 모든 항목을 object 자료형으로 통일한다.
iris_df.values.dtypedtype('O')16.3데이터프레임 인덱싱¶
데이터프레임의 인덱싱과 슬라이싱은 모두 행과 열에 대해 서로 독립적으로 작동한다. 행과 열 각각에 대한 인덱싱과 슬라이싱의 작동방식은 시리즈의 인덱싱, 슬라이싱 방식과 매우 유사하다. 또한 넘파이 2차원 어레이의 경우처럼 행과 열에 대한 인덱싱, 슬라이싱을 조합할 수도 있다.
설명을 위해 fruits3이 가리키는 데이터프레임을 활용한다.
fruits_array = np.array([[4, 5, 2],
[5, 4, 3],
[6, 3, 5],
[3, 0, 2],
[1, 2, 7]])
fruits3 = pd.DataFrame(fruits_array,
columns=['Mango', 'Apple', 'Banana'],
index=['A', 'B', 'C', 'D', 'E'])
fruits316.3.1열 인덱싱¶
열 인덱싱은 세 가지 방식으로 지원된다.
[]활용.loc[]활용.iloc[]활용
[] 활용
시리즈의 경우와는 다르게 대괄호만 사용하는 인덱싱은 열 라벨에 대해 실행된다. 예를 들어 아래 코드는 망고 열만 시리즈로 추출한다.
fruits3['Mango']A 4
B 5
C 6
D 3
E 1
Name: Mango, dtype: int64대괄호를 사용하지 않으면서 열의 이름을 마치 데이터프레임 객체의 속성인 것처럼 활용할 수 있다.
아래 코드는 Banana 열을 시리즈로 추출한다.
fruits3.BananaA 2
B 3
C 5
D 2
E 7
Name: Banana, dtype: int64.loc[] 활용
넘파이 2차원 어레이의 경우처럼 쉼표를 기준으로 행과, 열에 대한 인덱싱 또는 슬라이싱을 지정한다.
예를 들어 아래 코드는 사과 열만 시리즈로 추출하기 위해, 행에 대해서는 행 전체를 가리키는
슬라이싱 기호 (:)를 쉼표 왼쪽에 위치시켜야 한다.
fruits3.loc[:, 'Apple']A 5
B 4
C 3
D 0
E 2
Name: Apple, dtype: int64.iloc[] 활용
정수 인덱스로 열 인덱싱을 적용할 수 있다. 예를 들어, 사과는 1번 인덱스 열이기에 다음과 같이 추출한다. 행 전체 대상 슬라이싱이 여기서도 필요함에 주의한다.
fruits3.iloc[:, 1]A 5
B 4
C 3
D 0
E 2
Name: Apple, dtype: int6416.3.2데이터프레임 열 추가/업데이트¶
열 라벨 인덱싱을 이용하여 새로운 특성을 추가할 수 있다.
아래 코드는 패션프루트라는 특이한 이름의 과일 목록을 담은
'Passion fruit' 열을 새롭게 추가하면서
각 행의 값을 7로 지정한다.
넘파이 어레이에서 다룬 브로드캐스팅이 작동함에 주의한다.
fruits3['Passion fruit'] = 7
fruits3동일한 방식으로 열의 항목을 업데이트 할 수도 있다. 아래 코드는 패현프루트 열의 각 행의 값을 5로 업데이트 한다.
fruits3['Passion fruit'] = 5
fruits3행 전체의 길이와 동일한 리스트 또는 어레이를 이용하여 새로운 열을 추가하거나 기존에 있던 열의 항목을 업데이트 할 수 있다. 아래 코드는 포도 열을 추가하면서 길이가 5인 레인지 객체를 항목들의 값으로 지정하였다.
fruits3['Grape'] = range(10, 15)
fruits3아래 코드는 패션프루트 열을 길이가 5인 리스트를 이용하여 업데이트 한다.
fruits3['Passion fruit'] = [5, 4, 3, 2, 1]
fruits3참고로 'Passion fruit' 열을 인덱싱하려면 반드시 대괄호 방식을 사용해야 한다.
이유는 공백이 포함되어있기 때문에 변수처럼 취급될 수 없기 때문이다.
fruits3.Passion fruit Cell In[60], line 1
fruits3.Passion fruit
^
SyntaxError: invalid syntax
이런 경우엔 무조건 대괄호를 사용해야 한다.
fruits3['Passion fruit']A 5
B 4
C 3
D 2
E 1
Name: Passion fruit, dtype: int6416.3.3행 인덱싱¶
행 인덱싱은 두 가지 방식으로 지원된다.
.loc[]활용.iloc[]활용
즉, 대괄호만 사용하는 행 인덱싱은 지원되지 않는다.
데이터프레임 fruits3를 계속 활용하여 설명한다.
fruits3.loc[] 활용
아래 코드는 'A' 라벨 행을 시리즈 객체로 추출한다.
생성된 시리즈의 행 인덱스는 데이터프레임의 열 인덱스가 사용된다.
fruits3.loc['A']Mango 4
Apple 5
Banana 2
Passion fruit 5
Grape 10
Name: A, dtype: int64.iloc[] 활용
정수 인덱스로 행 인덱싱을 적용할 수 있다.
예를 들어, 'C' 라벨 행은 2번 인덱스 행이기에 다음과 같이 추출한다.
fruits3.iloc[2]Mango 6
Apple 3
Banana 5
Passion fruit 3
Grape 12
Name: C, dtype: int6416.3.4팬시 인덱싱¶
열 인덱스 또는 행 인덱스로 구성된 리스트를 인덱싱에 활용하는 기법이 팬시 인덱싱fancy indexing이다. 이때, 라벨 또는 정수로만 구성된 리스트를 지정해야 하며, 결과는 지정된 순서의 열 또는 행으로 구성된 데이터프레임 객체다.
열 팬시 인덱싱
열 인덱싱처럼 세 가지 방식이 모두 지원된다. 예를 들어 망고, 바나나, 패션프루트 열로 구성된 데이터프레임을 생성해본다.
아래 세 코드는 모두 망고, 바나나, 패션프루트 열만으로 구성된 데이터프레임을 추출한다.
fruits3[['Mango', 'Banana', 'Passion fruit']]fruits3.loc[:, ['Mango', 'Banana', 'Passion fruit']]fruits3.iloc[:, [0, 2, 3]]길이가 1인 인덱스 리스트를 사용해도 결과는 시리즈가 아닌 데이터프레임이다.
fruits3[['Apple']]type(fruits3[['Apple']])pandas.DataFrame일반 인덱싱의 결과는 시리즈임에 주의한다.
fruits3['Apple']A 5
B 4
C 3
D 0
E 2
Name: Apple, dtype: int64type(fruits3['Apple'])pandas.Series행 팬시 인덱싱
행 인덱싱처럼 두 가지 방식이 지원된다.
예를 들어 'B', 'D', 'E' 세 라벨 인덱스의 행으로 구성된 데이터프레임을 생성해본다.
fruits3.loc[['B', 'D', 'E']]fruits3.iloc[[1, 3, 4]]길이가 1인 인덱스 리스트를 사용해도 결과는 시리즈가 아닌 데이터프레임이다.
fruits3.loc[['A']]fruits3.iloc[[0]]16.3.5연습문제¶
문제 1
아래 코드는 (6, 4) 모양의 데이터프레임을 생성한다.
행 인덱스:
dates변수가 가리키는DatetimeIndex객체항목:
np.arange()함수 활용 후 어레이 모양 변경열 인덱스:
['A', 'B', 'C', 'D']지정
dates = pd.date_range(start="20260301", periods=6, freq="D")
df = pd.DataFrame(np.arange(24).reshape(6, 4), index=dates, columns=list("ABCD"))
df(1) 가능한 모든 방법으로 'A' 열만을 추출하여 시리즈를 생성하라.
답:
열 라벨을 이용한 인덱싱을 적용한다.
df["A"]2026-03-01 0
2026-03-02 4
2026-03-03 8
2026-03-04 12
2026-03-05 16
2026-03-06 20
Freq: D, Name: A, dtype: int64열 라벨을 객체의 속성처럼 이용하는 방식도 가능하다.
df.A2026-03-01 0
2026-03-02 4
2026-03-03 8
2026-03-04 12
2026-03-05 16
2026-03-06 20
Freq: D, Name: A, dtype: int64.loc[]과 .iloc[] 형식도 활용할 수 있다.
df.loc[:, "A"]2026-03-01 0
2026-03-02 4
2026-03-03 8
2026-03-04 12
2026-03-05 16
2026-03-06 20
Freq: D, Name: A, dtype: int64df.iloc[:, 0]2026-03-01 0
2026-03-02 4
2026-03-03 8
2026-03-04 12
2026-03-05 16
2026-03-06 20
Freq: D, Name: A, dtype: int64(2) 첫번째 날짜, 즉 2026년 3월 1일의 데이터를 확인하는 한 줄 표현식을 작성하라.
단, .loc[] 객체와 dates 변수를 이용해야 한다.
답:
2026년 3월 1일은 dates 객체의 0번 인덱스의 값이며,
다음과 같이 .loc[]과 함께 활용하면 된다.
df.loc[dates[0]]A 0
B 1
C 2
D 3
Name: 2026-03-01 00:00:00, dtype: int64정수 인덱스 0을 활용해도 된다.
df.iloc[0]A 0
B 1
C 2
D 3
Name: 2026-03-01 00:00:00, dtype: int64(3) .loc[] 객체를 이용해 'A'와 'B' 두 열만 추출하는 한 줄 표현식을 작성하라.
답:
열에 대한 팬시 인덱싱을 적용하면 된다.
df.loc[:, ["A", "B"]]정수 인덱스를 활용해도 된다.
df.iloc[:, [0, 1]](4) .iloc[] 객체를 이용해 3번 행만 추출하는 한 줄 표현식을 작성하시오.
답:
df.iloc[3]A 12
B 13
C 14
D 15
Name: 2026-03-04 00:00:00, dtype: int64(5) 2026년 3월 1일, 3일, 6일 행의 데이터만 추출하라.
답:
2026년 3월 1일, 3일, 6일은 0번, 2번, 5번 행의 라벨이기에 다음과 같이 행 팬시 인덱싱을 실행한다.
df.iloc[[0, 2, 5]]날짜 라벨로 구성된 리스트를 직접 이용할 수도 있다.
df.loc[['2026-03-01', '2026-03-03', '2026-03-06']]날짜를 적는 것 보다는 dates 객체에 인덱싱을 적용하는 게 실수를 줄인다.
df.loc[[dates[0], dates[2], dates[5]]]dates가 가리키는 DatetimeIndex 객체에 팬시 인덱싱을 적용한 결과를 이용하여
데이터프레임에 대한 행 팬시 인덱싱을 적용할 수도 있다.
df.loc[dates[[0, 2, 5]]](6) .iloc[] 객체를 이용해 홀수 행만 추출하는 한 줄 표현식을 작성하시오.
답:
df.iloc[1::2, :]열 전체를 대상으로 하는 슬라이싱은 생략해도 된다.
df.iloc[1::2](7) .iloc[] 객체를 이용해 1번, 2번 열만 추출하는 한 줄 표현식을 작성하시오.
답:
0번 축에 대해서는 모든 행을 가져오라는 슬라이싱을 명시해야 한다.
df.iloc[:, 1:3]문제 2
아래 코드는 붓꽃 데이터셋을 데이터프레임으로 불러온다.
iris_df = pd.read_csv(data_url+"iris.csv")
iris_df(1) 가능한 모든 방법으로 'variety' 열만 시리즈로 추출하라.
답:
대괄호 인덱싱, 속성 방식, .loc[], .iloc[] 네 가지 방법 모두 가능하다.
iris_df['variety']0 Setosa
1 Setosa
2 Setosa
3 Setosa
4 Setosa
...
145 Virginica
146 Virginica
147 Virginica
148 Virginica
149 Virginica
Name: variety, Length: 150, dtype: striris_df.variety0 Setosa
1 Setosa
2 Setosa
3 Setosa
4 Setosa
...
145 Virginica
146 Virginica
147 Virginica
148 Virginica
149 Virginica
Name: variety, Length: 150, dtype: striris_df.loc[:, 'variety']0 Setosa
1 Setosa
2 Setosa
3 Setosa
4 Setosa
...
145 Virginica
146 Virginica
147 Virginica
148 Virginica
149 Virginica
Name: variety, Length: 150, dtype: striris_df.iloc[:, 4]0 Setosa
1 Setosa
2 Setosa
3 Setosa
4 Setosa
...
145 Virginica
146 Virginica
147 Virginica
148 Virginica
149 Virginica
Name: variety, Length: 150, dtype: str(2) .iloc[] 객체를 이용하여 0번 행의 데이터를 시리즈로 추출하라.
답:
iris_df.iloc[0]sepal.length 5.1
sepal.width 3.5
petal.length 1.4
petal.width 0.2
variety Setosa
Name: 0, dtype: object(3) 'sepal.length'와 'petal.length' 두 열만 추출하는 한 줄 표현식을 작성하라.
단, .loc[] 객체와 팬시 인덱싱을 활용한다.
답:
열에 대한 팬시 인덱싱을 적용하면 된다.
iris_df.loc[:, ['sepal.length', 'petal.length']](4) .iloc[] 객체를 이용하여 0번, 50번, 100번 행의 데이터만 추출하라.
답:
행 팬시 인덱싱을 적용한다. 각 인덱스는 붓꽃 세 품종(setosa, versicolor, virginica)의 첫 번째 데이터에 해당한다.
iris_df.iloc[[0, 50, 100]]16.4데이터프레임 슬라이싱¶
.loc[] 과 .iloc[]을 행과 열에 동시에 적용할 수 있으며,
넘파이 2차원 어레이에 대한 인덱싱/슬라이싱이 작동하는 방식과 거의 동일하다.
설명을 위해 계속해서 fruits3가 가리키는 데이터프레임을 이용한다.
fruits316.4.1열 슬라이싱¶
열에 대해서만 슬라이싱을 적용하려면 행을 전체로 지정한다. 아래 코드는 전체 행을 대상으로 2번 인덱스열 이전까지 추출한다.
fruits3.iloc[:, :2]정수 인덱스가 아닌 열 라벨을 이용한 슬라이싱은 .loc[]함수를 써야하고, 지정한 구간의 끝도 포함됨에 유의한다.
fruits3.loc[:, :'Banana']16.4.2행 슬라이싱¶
행에 대해서만 슬라이싱을 적용하려면 열을 전체로 지정한다. 아래 코드는 2번 인덱스 행부터 모두 가져온다.
fruits3.iloc[2:, :]열 슬라이싱은 지정하지 않아도 된다.
fruits3.iloc[2:]지정된 행 라벨 인덱스를 활용할 수도 있다.
fruits3.loc['C':, :]fruits3.loc['C':]라벨을 이용할 경우 슬라이싱의 끝도 포함하기에 다음도 가능하다.
fruits3.loc['C':'E']스텝 활용
정수 인덱스를 활용하는 경우 스텝step도 사용할 수 있다. 아래 코드는 짝수 인덱스 열 또는 행에 속한 항목만 추출한다.
fruits3.iloc[:, ::2]fruits3.iloc[::2]16.4.3인덱싱과 슬라이싱의 조합¶
인덱싱과 슬라이싱의 어떤 조합도 행과 열에 대해 적용할 수 있다.
아래 코드는 'C'라벨 행의 'Apple'과 'Grape' 열의 항목을 별도의 시리즈로 추출한다.
fruits3.loc['C', ['Apple', 'Grape']]
Apple 3
Grape 12
Name: C, dtype: int64아래 코드는 'C' 라벨 행까지의 모든 행에서 'Banana' 열의 항목을 시리즈로 추출한다.
fruits3.loc[:'C', 'Banana']A 2
B 3
C 5
Name: Banana, dtype: int64아래 코드는 2번 인덱스 행의 1번, 2번 인덱스 열의 항목을 시리즈로 추출한다.
fruits3.iloc[2, [1, 2]]Apple 3
Banana 5
Name: C, dtype: int64아래 코드는 1번, 2번 인덱스 행의 3번, 0번, 1번 인덱스 열의 항목을 별도의 데이터프레임으로 추출한다.
fruits3.iloc[[1, 2], [3, 0, 1]]아래 코드는 'D' 라벨 행까지의 모든 행에서 'Banana' 열부터 이후의 모든 열의 항목을 데이터프레임으로 추출한다.
fruits3.loc[:'D', 'Banana':]16.4.4연습문제¶
문제 1
아래 코드는 (6, 4) 모양의 데이터프레임을 생성한다.
행 인덱스:
dates변수가 가리키는DatetimeIndex객체항목:
np.arange()함수 활용 후 어레이 모양 변경열 인덱스:
['A', 'B', 'C', 'D']지정
dates = pd.date_range(start="20260301", periods=6, freq="D")
df = pd.DataFrame(np.arange(24).reshape(6, 4), index=dates, columns=list("ABCD"))
df(1) 가능한 모든 방법으로 0번 행부터 2번 행까지 포함하는 데이터프레임을 생성하라.
답:
행 인덱스가 날짜 형식이기에 가장 간단한 방식은 정수 인덱스를 활용한 슬라이싱이다.
df.iloc[0:3]슬라이싱 구간의 시작이 0번 인덱스인 경우 0은 생략해도 된다.
df.iloc[:3]날짜를 정확히 적어야 하는 수고가 필요하지만 라벨 인덱스를 활용하여 슬라이싱을 진행할 수도 있다. 위치 인덱스 방식과는 달리 구간의 마지막 라벨도 포함된다.
df.loc["2026-03-01":"2026-03-03"](2) .loc[] 객체를 이용하여 2026년 3월 2일부터 3월 4일까지를 대상으로 A, B 두 열만 추출하는 한 줄 표현식을 작성하시오.
답:
df.loc["20260302":"20260304", ["A", "B"]](3) .loc[] 객체를 이용하여 2026년 3월 2일의 A, B 두 열만 추출하는 한 줄 표현식을 작성하시오.
답:
df.loc["20260302", ["A", "B"]]A 4
B 5
Name: 2026-03-02 00:00:00, dtype: int64(4) .loc[] 객체와 dates 변수를 이용해 2026년 3월 1일의 A 열만 추출하는 한 줄 표현식을 작성하시오.
답:
df.loc[dates[0], "A"]np.int64(0)(5) .iloc[] 객체를 이용해 3번부터 4번 인덱스 행을 대상으로 0번, 1번 인덱스의 열만 추출하는 한 줄 표현식을 작성하시오.
답:
df.iloc[3:5, 0:2](6) 아래 두 리스트에 포함된 행과 열만 순서대로 추출하는 한 줄 표현식을 작성하시오.
단, .iloc[] 객체와 팬시 인덱싱을 활용한다.
행:
[1, 2, 4]열:
[0, 2, 3, 1]
답:
df.iloc[[1, 2, 4], [0, 2, 3, 1]]문제 2
행 인덱스가 정수로 되어 있는 경우 라벨이 정수이기 때문에
.loc[]와 .iloc[] 모두 적용할 수 있지만 인덱싱과 슬라이싱이 서로 다른 결과를 만들 수 있다.
차이점을 확인하기 위해 먼저 RangeIndex를 행 인덱스로 갖는 간단한 데이터프레임을 생성한다.
sample_df = pd.DataFrame({"X": range(10), "Y": range(10, 20)})
sample_df(1) .iloc[3]과 .loc[3]를 각각 적용하고 결과에 차이가 있는지 확인하고 그 이유를 설명하라.
답:
아래 두 코드의 실행 결과가 동일하다. 이유는 정수 3이 정수 3번 인덱스이면서, 라벨로도 네 번째에 위치하기 때문이다.
sample_df.iloc[3]X 3
Y 13
Name: 3, dtype: int64sample_df.loc[3]X 3
Y 13
Name: 3, dtype: int64(2) .iloc[:4]와 .loc[:4]를 각각 적용하고 결과의 차이점을 확인하라.
답:
.iloc[:4]는 위치 기반이므로 0번부터 3번 위치까지 4개의 행을 추출한다.
sample_df.iloc[:4].loc[:4]는 라벨 기반이므로 라벨 0부터 라벨 4까지를 모두 포함하여 5개의 행을 추출한다.
sample_df.loc[:4]RangeIndex의 경우 라벨과 위치 인덱스가 동일한 정수처럼 보이지만,
.loc[]은 구간의 끝을 포함하고 .iloc[]은 포함하지 않기 때문에 결과가 다를 수 있다.
따라서 RangeIndex를 사용하는 데이터프레임에 슬라이싱을 적용할 때
.loc[]과 .iloc[]의 차이에 특히 주의해야 한다.
(3) 아래 데이터프레임에 대해서는 심지어 .iloc[3]과 .loc[3]의 결과도 다름을 확인하고 그 이유를 설명하라.
reversed_sample_df = pd.DataFrame({"X": range(10), "Y": range(10, 20)}, index=range(10, 0, -1))
reversed_sample_dfreversed_sample_df.iloc[3]X 3
Y 13
Name: 7, dtype: int64reversed_sample_df.loc[3]X 7
Y 17
Name: 3, dtype: int64.iloc[3]에서의 3은 위에서 4번째 위치한 항목을 가리키기에 X열, Y열서 각각 3, 13을 추출한다.
반면에 .loc[3]에서의 3은 라벨 3을 가리키기에 X열, Y열서 각각 7, 17을 추출한다.
문제 3
아래 코드는 붓꽃 데이터셋을 데이터프레임으로 불러온다.
iris_df = pd.read_csv(data_url+"iris.csv")
iris_df(1) .iloc[] 객체를 이용하여 처음 10개 행만 추출하는 한 줄 표현식을 작성하라.
답:
행 슬라이싱을 적용한다. 슬라이싱 구간의 시작이 0번 인덱스이므로 생략할 수 있다.
iris_df.iloc[:10](2) .iloc[] 객체를 이용하여 50번 행의 1번부터 3번 인덱스 열까지의 항목을 시리즈로 추출하라.
답:
행에 대해서는 인덱싱을, 열에 대해서는 슬라이싱을 조합한다.
iris_df.iloc[50, 1:4]sepal.width 3.2
petal.length 4.7
petal.width 1.4
Name: 50, dtype: object(3) .loc[] 객체를 이용하여 처음 5개 행에서 'sepal.length'부터 'petal.width'까지의 열만 추출하라.
답:
.loc[]은 라벨 기반이므로 행과 열 모두 라벨 슬라이싱을 적용한다.
.loc[]의 슬라이싱은 구간의 끝을 포함함에 주의한다.
iris_df.loc[:4, 'sepal.length':'petal.width'](4) .iloc[] 객체를 이용하여 짝수 인덱스 행에서 0번, 2번 열만 추출하는 한 줄 표현식을 작성하라.
답:
행에 대해서는 스텝을 활용한 슬라이싱을, 열에 대해서는 팬시 인덱싱을 조합한다.
iris_df.iloc[::2, [0, 2]](5) .iloc[] 객체를 이용하여 마지막 5개 행에서 0번, 2번 열만 추출하는 한 줄 표현식을 작성하라.
답:
행에 대해서는 슬라이싱을, 열에 대해서는 팬시 인덱싱을 조합한다.
iris_df.iloc[-5:, [0, 2]](6) .loc[] 객체를 이용하여 50번부터 54번 행까지에서 'petal.length'와 'variety' 열만 추출하라.
답:
행에 대해서는 라벨 슬라이싱을, 열에 대해서는 팬시 인덱싱을 조합한다.
행 인덱스가 RangeIndex이므로 정수 라벨을 그대로 사용할 수 있다.
iris_df.loc[50:54, ['petal.length', 'variety']](7) .iloc[] 객체를 이용하여 0번, 50번, 100번 행에서 2번 인덱스 열부터 끝까지의 항목을 추출하라.
답:
행에 대해서는 팬시 인덱싱을, 열에 대해서는 슬라이싱을 조합한다.
iris_df.iloc[[0, 50, 100], 2:]