BioPlayground

🧬
목록으로

Python으로 DNA 서열 분석하기

FASTA 파일에서 DNA 서열 GC 비율을 Python으로 계산하는 법. 바이오 연구자 맞춤 코딩 입문.

입문
|
90
|
검증 완료 (2026-06)
GC contentFASTADNA아미노산코돈
트랙 진행률0/6 (0%)

Python으로 DNA 서열 분석하기

이 토픽을 마치면

Python으로 DNA 서열의 GC content를 계산하고, FASTA 파일을 파싱하고, 코돈을 아미노산으로 변환할 수 있습니다.


변수: 데이터를 담는 그릇

실험 노트에 "시료 농도: 2.5 mg/mL"이라고 적듯, Python에서는 변수에 값을 저장합니다.

python
gene_name = "BRCA1"
sequence = "ATGCGATCGATCGATCG"
gc_ratio = 0.529
print(f"유전자: {gene_name}")
print(f"서열 길이: {len(sequence)}bp")
print(f"GC 비율: {gc_ratio:.1%}")
assert gene_name == "BRCA1"
assert len(sequence) == 17

문자열: DNA 서열 다루기

DNA 서열은 A, T, G, C 네 글자로 이루어진 문자열(string)입니다. Python의 문자열 메서드로 서열을 분석할 수 있습니다.

python
sequence = "ATGCGATCGATCGATCG"
# 특정 염기 개수 세기
g_count = sequence.count("G")
c_count = sequence.count("C")
print(f"G: {g_count}개, C: {c_count}개")
# 상보 서열 만들기 (A↔T, G↔C)
complement_table = str.maketrans("ATGC", "TACG")
complement = sequence.translate(complement_table)
print(f"원본: {sequence}")
print(f"상보: {complement}")
print(f"역상보: {complement[::-1]}")
assert complement == "TACGCTAGCTAGCTAGC"
assert complement[::-1] == "CGATCGATCGATCGCAT"

함수: GC Content 계산기

함수(function)는 실험 프로토콜의 한 단계를 재사용 가능하게 포장한 것입니다. 한 번 만들면 어떤 서열에든 적용할 수 있습니다.

python
def calculate_gc_content(sequence: str) -> float:
sequence = sequence.upper()
gc_count = sequence.count("G") + sequence.count("C")
return (gc_count / len(sequence)) * 100
# 테스트
seq1 = "ATGCGATCGATCGATCG"
seq2 = "AAAAAAAAAA"
seq3 = "GGGGGGGGGG"
print(f"seq1 GC: {calculate_gc_content(seq1):.1f}%")
print(f"seq2 GC: {calculate_gc_content(seq2):.1f}%")
print(f"seq3 GC: {calculate_gc_content(seq3):.1f}%")
assert abs(calculate_gc_content(seq1) - 52.9) < 0.1
assert calculate_gc_content(seq2) == 0.0
assert calculate_gc_content(seq3) == 100.0

리스트와 반복문: 여러 서열 한 번에 처리

96-well plate의 모든 well에 같은 처리를 하듯, 반복문(for loop)은 여러 데이터에 같은 작업을 반복합니다.

python
def calculate_gc_content(sequence: str) -> float:
sequence = sequence.upper()
gc_count = sequence.count("G") + sequence.count("C")
return (gc_count / len(sequence)) * 100
genes = {
"BRCA1": "ATGGATTTATCTGCTCTTCGCGTTGAAGAAGTACAAAATGTC",
"TP53": "ATGGAGGAGCCGCAGTCAGATCCTAGCGTGAGTTTGCTGTGA",
"EGFR": "ATGCGACCCTCCGGGACGGCCGGGGCAGCGCTCCTGGCGCTG",
}
results = []
for name, seq in genes.items():
gc = calculate_gc_content(seq)
results.append(gc)
print(f"{name}: GC={gc:.1f}%, 길이={len(seq)}bp")
assert len(results) == 3
assert all(0 <= gc <= 100 for gc in results)

딕셔너리: FASTA 파일 파싱

딕셔너리(dictionary)는 실험 시료에 라벨을 붙이는 것과 같습니다. 유전자 이름(키)으로 서열(값)을 바로 찾을 수 있습니다.

python
def parse_fasta(fasta_text: str) -> dict[str, str]:
sequences: dict[str, str] = {}
current_header = ""
for line in fasta_text.strip().split("\n"):
if line.startswith(">"):
current_header = line[1:].strip()
sequences[current_header] = ""
else:
sequences[current_header] += line.strip()
return sequences
sample_fasta = """>BRCA1_human
ATGGATTTATCTGCTCTTCG
CGTTGAAGAAGTACAAAATGTC
>TP53_human
ATGGAGGAGCCGCAGTCAG
ATCCTAGCGTGAGTTTGCTGTGA"""
result = parse_fasta(sample_fasta)
print(f"파싱된 서열 수: {len(result)}")
for name, seq in result.items():
print(f" {name}: {len(seq)}bp")
assert len(result) == 2
assert result["BRCA1_human"] == "ATGGATTTATCTGCTCTTCGCGTTGAAGAAGTACAAAATGTC"
assert result["TP53_human"] == "ATGGAGGAGCCGCAGTCAGATCCTAGCGTGAGTTTGCTGTGA"

코돈 → 아미노산 변환

DNA 서열 3글자(코돈)가 하나의 아미노산을 지정합니다. 이 변환 테이블을 딕셔너리로 만들 수 있습니다.

python
CODON_TABLE = {
"ATG": "M", # Methionine (시작코돈)
"TTT": "F", "TTC": "F", # Phenylalanine
"TTA": "L", "TTG": "L", "CTT": "L", "CTC": "L", # Leucine
"GAT": "D", "GAC": "D", # Aspartic acid
"GAA": "E", "GAG": "E", # Glutamic acid
"GCT": "A", "GCC": "A", # Alanine
"TAA": "*", "TAG": "*", "TGA": "*", # 종결코돈
}
def translate_sequence(dna: str) -> str:
protein = []
for i in range(0, len(dna) - 2, 3):
codon = dna[i:i+3]
amino_acid = CODON_TABLE.get(codon, "?")
if amino_acid == "*":
break
protein.append(amino_acid)
return "".join(protein)
test_seq = "ATGGATTTTGAA"
protein = translate_sequence(test_seq)
print(f"DNA: {test_seq}")
print(f"Protein: {protein}")
assert protein == "MDFE"

직접 해보기 (Faded Example)

아래 빈칸을 채워 GC content 계산 함수를 완성하세요.

빈칸 채우기python
def gc_content(seq):
seq = seq.upper()
gc = seq.count('G') + seq.count('')
return / len(seq) * 100

흔한 에러 & 해결법

Q: IndentationError: expected an indented block

Python은 들여쓰기(indentation)로 코드 블록을 구분합니다. def, for, if 다음 줄은 반드시 스페이스 4칸 들여쓰기가 필요합니다.

Q: KeyError: 'BRCA1'

딕셔너리에 해당 키가 없을 때 발생합니다. dict.get("BRCA1", "없음")을 사용하면 키가 없어도 에러 없이 기본값을 반환합니다.

Q: 서열에 소문자가 섞여 있어서 count가 안 맞습니다

.upper()로 먼저 대문자 통일 후 처리하세요. 실제 FASTA 파일에서 소문자는 반복 서열(repeat-masked region)을 의미하기도 합니다.


다음 글에서는 Git으로 이 분석 코드를 버전 관리하는 법을 배웁니다.