이론 - Series와 DataFrame 기본 개념

Ryan·2025년 1월 23일

Python/Pandas

목록 보기
2/23

1. Series(시리즈) 기초

1.1 시리즈 생성

python
복사
import pandas as pd
import numpy as np
import random as rd
from faker import Faker

values = list(range(5))
index = [letter for letter in 'abcde']

series = pd.Series(values, index)
print(series)

결과:

css
복사
a    0
b    1
c    2
d    3
e    4
dtype: int64
  • pd.Series(데이터, 인덱스) 형태로 생성합니다.
  • Python의 리스트 혹은 range 객체를 활용할 수 있습니다.
  • 시리즈는 1차원 형태이므로, 각 원소에 대한 인덱스를 지정해줄 수 있습니다.

1.2 시리즈 구조 확인

python
복사
values[0] == series[0]
  • 리스트의 values[0] 값과 시리즈 series[0]의 값이 동일한지 확인합니다.
python
복사
py_dict = dict(zip(index, values))
py_dict
  • zip 함수를 통해 인덱스와 값들의 쌍을 만들고, 이를 dict로 변환한 예시입니다.
python
복사
series_dict = pd.Series(py_dict)
series_dict
  • 딕셔너리를 기반으로 시리즈를 생성할 수도 있습니다.
python
복사
list(py_dict.values()) == series_dict
  • 시리즈 전체를 비교할 때에는 리스트 혹은 NumPy 배열로 변환하는 방식으로 비교할 수 있습니다.
  • 단순히 py_dict.values() == series_dict는 Python 3에서 dict_values와 Series를 바로 비교하므로 False가 나올 수 있습니다.(따라서 리스트나 배열 등 같은 자료형으로 변환해서 비교해야 합니다.)

2. 시리즈 인덱싱 & 슬라이싱

2.1 데이터 생성

python
복사
rd_seed = 42
fake = Faker('ko_KR')
Faker.seed(rd_seed)

names = [fake.name() for _ in range(10)]
ages = [rd.randint(25, 50) for _ in range(10)]
index = [chr(ord('a')+ i) for i in range(10)]

print(names)
print(ages)
print(index)
  • Faker 라이브러리(ko_KR)를 이용해 임의의 한글 이름을 10개 생성합니다.
  • rd.randint(25, 50)을 통해 25~50 사이 임의의 나이 10개를 생성합니다.
  • chr(ord('a') + i)로 알파벳 a부터 10개(a~j) 인덱스를 만듭니다.

2.2 시리즈 생성 및 기본 인덱싱

python
복사
ns = pd.Series(names, index=index)
ns
  • ns 시리즈에 namesindex를 할당했습니다.
python
복사
print(ns[2])           # 정수 형태 인덱스(팬시 인덱싱과 유사)
print(ns.loc['d'])     # 명시적으로 'd' 라벨을 이용
print(ns.iloc[2])      # 정수 위치 기반 인덱싱
print(ns.at['d'])      # 스칼라 접근
print(ns.iat[2])       # 위치 기반 스칼라 접근
  • 시리즈[정수]시리즈.loc['라벨'], 시리즈.iloc[정수]를 혼동하지 않도록 주의합니다.
  • .at/.iat는 단일 스칼라에 빠르게 접근할 때 사용합니다.

2.3 인덱스가 불연속적인 경우

python
복사
tmp = pd.Series(names[:3], index=[0, 2, 5])
display(tmp)
print(tmp[0])
print(tmp.loc[2])
print(tmp.iloc[2])  # 위치 기준으로는 인덱스 5가 세 번째이므로 iloc[2] -> tmp의 index[2] == 5
print(tmp[2])
  • 인덱스 [0, 2, 5]와 실제 위치는 다른 개념이라는 점을 확인할 수 있습니다.
    • tmp.loc[2]는 라벨 기반으로 인덱스가 2인 원소를 반환
    • tmp.iloc[2]는 실제 데이터에서 3번째 원소(인덱스 5)를 반환

2.4 시리즈 슬라이싱

python
복사
ns.loc['b':'e']
ns.iloc[1:5]
  • .loc는 라벨값 ‘b’부터 ‘e’까지(종료점 포함)를 추출합니다.
  • .iloc는 위치 기준 1~4까지(종료점 미포함)를 추출합니다.

3. 시리즈 속성

python
복사
ns.index
ns.values
ns.dtype
ns.shape
ns.size
ns.hasnans
  • index, values : 인덱스와 값
  • dtype : 데이터 타입
  • shape, size : 시리즈 크기(튜플 형태, 원소 수)
  • hasnans : NaN(결측치) 존재 여부
python
복사
ns[0] = np.nan
print(ns.hasnans)  # True
  • ns 시리즈의 첫 번째 값을 NaN으로 변경하면 hasnansTrue로 바뀝니다.
python
복사
ns.is_unique
  • 시리즈 내에 중복 데이터가 있는지 여부를 판단합니다. (모두 유니크하면 True)
python
복사
ns['i':'j'] = '강상구'
ns.is_unique
  • i~j 인덱스 구간의 값을 동일한 문자열로 설정하면 중복된 값이 생길 수 있으므로 is_unique 결과는 False가 될 수 있습니다.
python
복사
ns.name = '시리즈 테스트 - 이름'
ns
  • 시리즈 자체에 대한 이름(Series.name) 속성을 설정할 수 있습니다.

4. 시리즈 활용 예제

python
복사
num = [1, 5, 2, 3]
ans = []
for i in num:
    list(ans.append(str(i)).split(','))

ans
  • 간단히 반복문을 돌며 특정 처리를 하는 예시입니다.
  • ans.append(str(i)) 한 뒤, .split(',') 로 분리해서 쓰는 형태인데, 실제 목적에 따라 가공 방식을 조정할 수 있습니다.

5. DataFrame(데이터프레임) 기초

5.1 데이터프레임 생성

python
복사
names_sr = pd.Series(names, index=index, name='이름')
ages_sr = pd.Series(ages, index=index, name='나이')
display(names_sr, ages_sr)

df1 = pd.DataFrame(names_sr)
df1['나이'] = ages_sr
df1
  • 시리즈 두 개(names_sr, ages_sr)를 합쳐서 데이터프레임 생성
  • df1 = pd.DataFrame(시리즈 객체) 후에 다른 시리즈를 열로 추가할 수 있습니다.
python
복사
extended_ages = [14, 15, *ages]
df1['나이2'] = extended_ages
df1
  • 기존 나이 리스트에 임의로 2개의 값(14, 15)을 앞에 붙여 새로운 열을 만들어 추가한 예시입니다.
python
복사
jobs = [fake.job() for _ in range(10)]
df_dict = {'이름':names_sr,'나이':ages_sr, '직업':jobs}
df2 = pd.DataFrame(df_dict)
df2
  • dict로 한번에 데이터프레임을 생성하는 방법입니다.

5.2 인덱싱 및 슬라이싱

python
복사
df2['나이']
  • 열(column) 인덱싱 (Series 형태 반환)
python
복사
# df2['A']
# 존재하지 않는 열을 조회하면 KeyError 발생
python
복사
df2.loc['a']
df2.iloc[3]
  • df2.loc['a'] : 라벨이 ‘a’인 행 전체 (Series로 반환)
  • df2.iloc[3] : 정수 위치 3인 행 (Series로 반환)
python
복사
df2.loc['a':'f','나이']
df2.iloc[1:4, 2]
  • df2.loc['a':'f','나이'] : 라벨 ‘a’부터 ‘f’까지 인덱스의 ‘나이’ 열
  • df2.iloc[1:4, 2] : 정수 위치 기반으로 1~3행, 2열만 추출
python
복사
age_above_40 = df2['나이'] > 40
df2[age_above_40]
  • 나이가 40 초과인 행만 필터링
python
복사
df2[df2['직업'] == '웹 개발자']
  • '직업''웹 개발자'인 행만 필터링
python
복사
df2[['직업']]
df3 = df2[['직업', '이름']]
df3
  • 여러 열을 한꺼번에 조회할 때는 리스트 형태로 열 이름을 전달합니다.

6. 데이터프레임 속성

python
복사
df2.index
df2.columns
df2.values
df2.dtypes
df2.shape
df2.size
df2.T
  • index, columns : 행 인덱스와 열 이름
  • values : 2차원 값(NumPy 배열 형태)
  • dtypes : 각 열의 데이터 타입
  • shape, size : (행 수, 열 수)와 전체 원소 수
  • df2.T : 행열 전치 (transpose)
python
복사
df2.loc['이름']
# KeyError 발생. '이름'은 인덱스가 아니라 열 이름이기 때문
df2.T.loc['이름']
  • 전치된 상태에서 '이름'을 행 라벨로 접근할 수 있습니다.

7. 데이터프레임 주요 기능

python
복사
df2.head(8)
df2.tail(8)
  • head(n): 위에서 n개의 행을, tail(n): 아래에서 n개의 행을 출력
python
복사
df2.loc['i', '나이'] == np.nan
df2['이름']['b'] == '김재호'
df2.loc['j', '이름'] == 'none'
  • 이와 같은 비교문들은 False가 나올 가능성이 높습니다.
    • NaN은 어떤 값과도 같지 않은 특징이 있습니다(NaN == NaN 조차 False).
    • Faker로 생성된 이름이나 특정 값이 실제 존재하지 않는 값일 수도 있습니다.
python
복사
df2.describe(include='all')
df2.info()
df2.isna().sum()
  • describe() : 각 열에 대한 통계 요약 (기본 float/int 열에 대한 통계, include='all'로 범주형/문자열까지 확인)
  • info() : 데이터프레임 기본 정보 (행, 열, 결측치, 데이터 타입 등)
  • isna().sum() : 결측치 개수를 열별로 합산

7.1 결측치 처리

python
복사
df2.fillna('홍길동')
df2.fillna({'이름':'홍길동', '나이':df2['나이'].mean().astype(int)})
  • fillna(값)으로 모든 결측치를 특정 값으로 대체
  • 딕셔너리 형태로 열별 다른 값으로 채우기 가능(예: '이름''홍길동', '나이'는 나이 열 평균)
python
복사
df2.dropna(axis=0)
df2.dropna(subset='이름')
  • dropna() : 결측치가 있는 행이나 열을 제거
  • axis=0은 행, axis=1은 열을 의미
  • subset으로 특정 열에서 결측치가 있는 행만 제거 가능

7.2 행/열 삭제

python
복사
df2.drop('a')
df2.drop(['이름'], axis=1)
df2.drop(index=['a','c'])
df2.drop(columns=['나이'])
  • drop(인덱스/열, axis=...)로 행 또는 열을 삭제
python
복사
df2.reset_index(drop=True)
  • 기존 인덱스를 초기화하고 0부터의 정수 인덱스로 재설정
  • drop=True로 인덱스 열을 따로 보존하지 않도록 함

7.3 정렬

python
복사
df2.sort_values(by=['나이','이름'])
  • '나이', '이름' 순으로 오름차순 정렬
  • 내림차순 정렬시 ascending=False 옵션 사용

정리

위 코드는 Pandas의 SeriesDataFrame에서 자주 쓰이는 기초적인 기능들을 보여줍니다.

  1. Series
    • 1차원 배열 같은 구조
    • 딕셔너리나 리스트 등 다양한 자료구조로부터 생성 가능
    • 인덱싱(.loc, .iloc, [])과 슬라이싱, 속성(.index, .values, .dtype, .shape) 숙지
  2. DataFrame
    • 2차원 표 형식 자료구조
    • 여러 Series를 합쳐서 만들거나, 딕셔너리로 한 번에 만들 수 있음
    • 인덱싱 & 슬라이싱(.loc, .iloc, []), 필터링, 행/열 추가와 삭제
    • 주요 속성(.index, .columns, .dtypes, .shape, .size)과 전처리 메서드(fillna, dropna, drop, reset_index, sort_values 등)

0개의 댓글