[파이썬 기초] NumPy & Pandas 기초

2026. 6. 18. 19:00·BI&Programming-Tools/Python

NumPy와 Pandas는 파이썬 데이터 분석의 핵심 라이브러리입니다.

NumPy는 수치 계산과 배열 연산을, Pandas는 표 형태의 데이터 처리를 담당합니다.

두 라이브러리 모두 내부적으로 C로 구현되어 있어 순수 파이썬보다 훨씬 빠릅니다.

pip install numpy pandas

NumPy


배열 생성

NumPy의 핵심 자료구조는 ndarray(n차원 배열)입니다.

import numpy as np

# 리스트로 배열 생성
arr = np.array([1, 2, 3, 4, 5])
print(arr)          # [1 2 3 4 5]
print(arr.dtype)    # int64
print(arr.shape)    # (5,)

# 2차원 배열
matrix = np.array([[1, 2, 3],
                   [4, 5, 6]])
print(matrix.shape)    # (2, 3) → 2행 3열
print(matrix.ndim)     # 2
print(matrix.size)     # 6 (전체 원소 수)

 

자주 사용하는 배열 생성 함수입니다.

np.zeros((3, 4))           # 0으로 채운 3×4 배열
np.ones((2, 3))            # 1로 채운 2×3 배열
np.eye(3)                  # 3×3 단위행렬
np.arange(0, 10, 2)        # [0 2 4 6 8]
np.linspace(0, 1, 5)       # [0.   0.25  0.5   0.75  1.]  (균등 간격)
np.random.seed(42)
np.random.rand(3, 3)       # 0~1 균등분포 난수 배열
np.random.randn(3, 3)      # 표준정규분포 난수 배열


인덱싱과 슬라이싱

arr = np.array([10, 20, 30, 40, 50])

print(arr[0])       # 10
print(arr[-1])      # 50
print(arr[1:4])     # [20 30 40]
print(arr[::2])     # [10 30 50]

# 2차원 배열
matrix = np.array([[1, 2, 3],
                   [4, 5, 6],
                   [7, 8, 9]])

print(matrix[0, 1])     # 2 (0행 1열)
print(matrix[1:, :2])   # [[4 5], [7 8]] (1행 이후, 0~1열)
print(matrix[:, 1])     # [2 5 8] (모든 행의 1열)

NumPy 슬라이싱은 복사본이 아닌 뷰(view)를 반환합니다. 슬라이싱된 배열을 수정하면 원본도 바뀝니다. 독립적인 복사본이 필요하면 .copy()를 사용합니다.

sub = matrix[0, :].copy()


불리언 인덱싱

조건으로 원소를 선택합니다. 데이터 필터링에서 자주 사용합니다.

arr = np.array([1.2, 3.5, 0.8, 4.1, 2.9])

mask = arr > 2.0
print(mask)         # [False  True False  True  True]
print(arr[mask])    # [3.5 4.1 2.9]

# 한 줄로 작성
print(arr[arr > 2.0])


연산

NumPy 배열은 원소 단위로 연산이 적용됩니다.

a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])

print(a + b)      # [11 22 33 44]
print(a * b)      # [10 40 90 160]
print(a ** 2)     # [1 4 9 16]
print(a + 10)     # [11 12 13 14] (브로드캐스팅)


브로드캐스팅

크기가 다른 배열 간 연산을 자동으로 확장합니다.

matrix = np.array([[1, 2, 3],
                   [4, 5, 6]])

row = np.array([10, 20, 30])
print(matrix + row)
# [[11 22 33]
#  [14 25 36]]


집계 함수

arr = np.array([[1, 2, 3],
                [4, 5, 6]])

print(arr.sum())          # 21 (전체 합)
print(arr.sum(axis=0))    # [5 7 9] (열 방향 합)
print(arr.sum(axis=1))    # [6 15] (행 방향 합)
print(arr.mean())         # 3.5
print(arr.std())          # 표준편차
print(arr.min(), arr.max())
print(arr.argmin(), arr.argmax())    # 최솟값, 최댓값의 인덱스


배열 변형

arr = np.arange(12)

reshaped = arr.reshape(3, 4)    # 3×4로 변형
print(reshaped.shape)           # (3, 4)

print(reshaped.flatten())       # 1차원으로 펼치기
print(reshaped.T)               # 전치 (transpose)


생물정보학 예시

# 발현량 행렬: 행 = 유전자, 열 = 샘플
expression = np.array([
    [12.5, 11.2, 13.8],    # BRCA1
    [8.3,  9.1,  7.6],     # TP53
    [21.0, 19.8, 22.3],    # EGFR
])

# 각 유전자의 평균 발현량
gene_mean = expression.mean(axis=1)
print(gene_mean)    # [12.5  8.33 21.03]

# 발현량 10 이상인 유전자 필터링
high_expr_idx = np.where(gene_mean >= 10)[0]
print(high_expr_idx)    # [0 2]

# Z-score 정규화 (샘플 간 비교)
mean = expression.mean(axis=1, keepdims=True)
std = expression.std(axis=1, keepdims=True)
z_score = (expression - mean) / std


Pandas


Series와 DataFrame

Pandas의 두 핵심 자료구조는 Series(1차원)와 DataFrame(2차원)입니다.

import pandas as pd

# Series: 인덱스가 있는 1차원 배열
s = pd.Series([12.5, 8.3, 21.0], index=["BRCA1", "TP53", "EGFR"])
print(s)
# BRCA1    12.5
# TP53      8.3
# EGFR     21.0

# DataFrame: 표 형태의 2차원 구조
df = pd.DataFrame({
    "sample_id": ["sample_01", "sample_02", "sample_03"],
    "species":   ["Homo sapiens", "Mus musculus", "Homo sapiens"],
    "coverage":  [30.5, 18.2, 45.8],
    "gc_content":[0.512, 0.488, 0.521]
})
print(df)


파일 읽기·쓰기

# CSV 읽기
df = pd.read_csv("samples.csv")
df = pd.read_csv("samples.csv", index_col=0)        # 첫 번째 열을 인덱스로
df = pd.read_csv("samples.csv", sep="\t")           # TSV 읽기

# 파일 쓰기
df.to_csv("output.csv", index=False)                # 인덱스 제외하고 저장
df.to_csv("output.tsv", sep="\t", index=False)      # TSV로 저장


데이터 탐색

print(df.shape)          # (행 수, 열 수)
print(df.dtypes)         # 각 열의 데이터 타입
print(df.head())         # 상위 5행
print(df.tail(3))        # 하위 3행
print(df.info())         # 열 정보, 결측값 요약
print(df.describe())     # 수치형 열의 기술 통계
print(df.columns)        # 열 이름 목록
print(df.index)          # 인덱스 목록


열 선택과 행 선택

# 열 선택
print(df["coverage"])               # Series 반환
print(df[["sample_id", "coverage"]]) # DataFrame 반환

# loc: 레이블 기반 인덱싱
print(df.loc[0])                    # 인덱스 0인 행
print(df.loc[0, "coverage"])        # 인덱스 0, coverage 열
print(df.loc[0:2, "sample_id":"coverage"])  # 범위 선택

# iloc: 위치 기반 인덱싱
print(df.iloc[0])                   # 첫 번째 행
print(df.iloc[0, 2])                # 첫 번째 행, 세 번째 열
print(df.iloc[:3, :2])              # 0~2행, 0~1열

 

loc은 레이블(인덱스 이름, 열 이름) 기준, iloc은 정수 위치 기준입니다. loc의 슬라이싱은 끝 인덱스를 포함하지만, iloc은 포함하지 않습니다.


조건 필터링

# 단일 조건
high_cov = df[df["coverage"] >= 30]

# 복수 조건 (& : and, | : or)
filtered = df[(df["coverage"] >= 30) & (df["species"] == "Homo sapiens")]

# isin: 특정 값 목록에 포함 여부
target_species = ["Homo sapiens", "Mus musculus"]
df[df["species"].isin(target_species)]

# str 메서드로 문자열 필터링
df[df["sample_id"].str.startswith("sample_0")]

 

Pandas 조건식에서 and, or 대신 &, |를 사용하며, 각 조건을 반드시 괄호로 감싸야 합니다.


열 추가 및 수정

# 새 열 추가
df["gc_percent"] = df["gc_content"] * 100
df["is_human"] = df["species"] == "Homo sapiens"

# apply: 각 원소에 함수 적용
df["coverage_category"] = df["coverage"].apply(
    lambda x: "high" if x >= 30 else "low"
)


결측값 처리

print(df.isnull().sum())           # 열별 결측값 수
print(df.isnull().any())           # 결측값이 있는 열 확인

df.dropna()                        # 결측값이 있는 행 제거
df.dropna(subset=["coverage"])     # 특정 열에 결측값 있는 행 제거
df.fillna(0)                       # 결측값을 0으로 채우기
df["coverage"].fillna(df["coverage"].mean())  # 평균으로 채우기


그룹화와 집계

# groupby: 특정 열 기준으로 그룹화 후 집계
grouped = df.groupby("species")["coverage"].mean()
print(grouped)

# 여러 집계 함수 동시 적용
df.groupby("species")["coverage"].agg(["mean", "std", "min", "max"])

# 여러 열 집계
df.groupby("species").agg({
    "coverage": "mean",
    "gc_content": "std"
})


정렬

df.sort_values("coverage")                          # 오름차순
df.sort_values("coverage", ascending=False)         # 내림차순
df.sort_values(["species", "coverage"], ascending=[True, False])  # 다중 열 정렬


유용한 메서드

df["species"].value_counts()           # 값별 빈도 계산
df["coverage"].unique()                # 고유값 목록
df["coverage"].nunique()               # 고유값 수
df.duplicated()                        # 중복 행 확인
df.drop_duplicates()                   # 중복 행 제거
df.rename(columns={"gc_content": "gc"})  # 열 이름 변경
df.drop(columns=["gc_content"])        # 열 삭제
df.reset_index(drop=True)             # 인덱스 초기화


데이터 병합

# merge: SQL JOIN과 유사
df1 = pd.DataFrame({"id": ["s01", "s02"], "coverage": [30.5, 18.2]})
df2 = pd.DataFrame({"id": ["s01", "s02"], "gc": [0.51, 0.49]})

merged = pd.merge(df1, df2, on="id")                  # inner join (기본)
merged = pd.merge(df1, df2, on="id", how="left")      # left join

# concat: 단순 연결
pd.concat([df1, df2], axis=0)    # 행 방향으로 연결
pd.concat([df1, df2], axis=1)    # 열 방향으로 연결


NumPy와 Pandas 함께 사용하기

# DataFrame의 수치형 열을 NumPy 배열로 변환
values = df[["coverage", "gc_content"]].values    # ndarray 반환
print(type(values))    # <class 'numpy.ndarray'>

# NumPy 연산 후 DataFrame에 추가
df["log_coverage"] = np.log2(df["coverage"])
df["normalized"] = (df["coverage"] - df["coverage"].mean()) / df["coverage"].std()

정리표

항목 Numpy Pandas
핵심 자료구조 ndarray Series, DataFrame
주요 용도 수치 계산, 행렬 연산 표 형태 데이터 처리
인덱싱 arr[행, 열] loc(레이블), iloc(위치)
파일 읽기 - pd.read_csv()
집계 arr.mean(axis=) groupby().agg()
결측값 - fillna(), dropna()

 

'BI&Programming-Tools > Python' 카테고리의 다른 글

[파이썬 기초] 통계 기초 (scipy)  (0) 2026.06.19
[파이썬 기초] Matplotlib / Seaborn 시각화  (0) 2026.06.18
[파이썬 기초] 클래스, 모듈, 예외처리  (0) 2026.06.18
[파이썬 기초] 파일 형식 처리 (CSV, TSV, FASTA)  (0) 2026.06.17
[파이썬 기초] 변수 범위와 파일 읽기·쓰기  (0) 2026.06.17
'BI&Programming-Tools/Python' 카테고리의 다른 글
  • [파이썬 기초] 통계 기초 (scipy)
  • [파이썬 기초] Matplotlib / Seaborn 시각화
  • [파이썬 기초] 클래스, 모듈, 예외처리
  • [파이썬 기초] 파일 형식 처리 (CSV, TSV, FASTA)
데이터로 읽는 생명
데이터로 읽는 생명
is-note 님의 블로그 입니다.
  • 데이터로 읽는 생명
    In Silico Note
    데이터로 읽는 생명
  • 전체
    오늘
    어제
    • 분류 전체보기 (190)
      • Bio-Knowledge (16)
        • 분자생물학 & 유전학 기초 (0)
        • 전사체학 & 유전자 발현 (0)
        • 구조생물학 & 단백질 (0)
        • 싱글셀 & 다중오믹스 (0)
        • 임상유전학 & 질환 데이터 (0)
      • Programming (4)
        • API (4)
      • BI&Programming-Tools (111)
        • File Formats (14)
        • Linux & Bash Script (38)
        • Python (35)
        • R (11)
        • 통계 (8)
        • Pipeline Manager (0)
        • Etc (5)
      • Bio Data Analysis (28)
        • 서열분석개론 (6)
        • WGS(Whole Genome Seq) (11)
        • WES(Whole Exome Seq) (2)
        • RNA-Seq (4)
        • Metagenome (2)
        • Non-human Resequencing (1)
        • 임상유전체 분석 (1)
        • Multi-Omics (1)
      • Bio-Trends & Tech (1)
      • 코딩테스트 연습 (30)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    파이썬연습
    분자생물학
    R기초
    생물정보학
    ngs
    파일포맷
    wgs
    fasta
    GATK
    FASTQ
    bioinformatics
    R
    리눅스기초
    파이썬
    데이터분석
    통계
    코딩테스트
    리눅스
    유전체분석
    파이썬기초
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
데이터로 읽는 생명
[파이썬 기초] NumPy & Pandas 기초
상단으로

티스토리툴바