이거 3부작입니다... 일단 분석을 하다 말았고, 태블로도 써야됨.
clinvar는 유전적 변이와 인간의 표현형과의 관계에 대한 데이터를 수집하여 보관하는 데이터베이스이다. 이게 데이터가 어떻게 되어있냐면 몇번 염색체 어디에 뭐가 어떻게 뻑나면 어떤 변이더라~ 이런게 들어있는데, vcf파일입니다. 이거 분석하려면 여는것부터 골치아픔. 근데 이게 된다고요?
내가 vcf파일 상태로는 열기도 조작하기도 귀찮아서 아예 거기 안에 있는 내용을 데이터프레임화하고 csv로 만드는 코드를 짰음.
VCF파일 내용물
'1', '66926', '3385321', 'AG', 'A', '.', '.', 'ALLELEID=3544463;CLNDISDB=Human_Phenotype_Ontology:HP:0000547,MONDO:MONDO:0019200,MeSH:D012174,MedGen:C0035334,OMIM:268000,OMIM:PS268000,Orphanet:791;CLNDN=Retinitis_pigmentosa;CLNHGVS=NC_000001.10:g.66927del;CLNREVSTAT=criteria_provided,_single_submitter;CLNSIG=Uncertain_significance;CLNSIGSCV=SCV005419006;CLNVC=Deletion;CLNVCSO=SO:0000159;GENEINFO=OR4F5:79501;MC=SO:0001627|intron_variant;ORIGIN=0'
'1', '66926', '3385321', 'AG', 'A', '.', '.'는 위치 정보다. 1번 염색체 66926번째 염기에 생긴 변이고, clinvar 아이디는 3385321이고, AG가 A로 바뀐 변이라는 얘기. 뒤에 점 두개는 QUAL, FILTER인데… 왜 비었냐…
그 뒤는 INFO로 따로 또 딕셔너리로 묶여있는 공간이다. 그래서 이게 다 뭐냐고?
1. ALLELEID: 대립 유전자 아이디
2. CLNDISDB: 질병 데이터베이스 링크
3. CLNDN: 질병 이름
4. CLNHGVS: HGVS 명명법
5. CLNREVSTAT: 검토 신뢰도
6. CLNSIG: 임상적 유의성
7. CLNVC: 변이 타입
8. GENEINFO: 유전자 정보(이름:Entrez ID)
9. MC: 분자적 영향
10. ORIGIN: 변이의 기원(0: 특정되지 않음)
csv파일로 만들기
일단 저 clinvar가 주기적으로 업데이트되는 데이터베이스입니다. 뭐 하루에 하나씩 바뀌고 그런건 아니고 1~2주마다 바뀌는듯한데, 바뀔때마다 파일명이 같이 바뀌거든요.
vcf_path = 'data/clinvar_20260208.vcf'
f_name = re.search('clinvar_[0-9]{8}', vcf_path).group()
print(f'file name: {f_name}')
근데 저 이름 형식이 바뀌는건 아니라 큐식정(정규표현식)으로 패턴 잡아서 찾아서 이름 추출하면 장땡이긴 해요. 저렇게만 해두면 새 파일을 받았을 때 vcf_path 변수만 새 파일명으로 수정하면 된다.
# 1. VCF 읽기 (이전의 DtypeWarning 해결 버전)
def read_vcf_full(path):
with open(path, 'r') as f:
lines = [l for l in f if not l.startswith('##')]
df = pd.read_csv(
io.StringIO(''.join(lines)),
sep='\t',
dtype={'#CHROM': str},
low_memory=False
).rename(columns={'#CHROM': 'CHROM'})
# 2. INFO 컬럼을 딕셔너리로 파싱하는 함수
def parse_info(info_str):
# 'KEY=VALUE' 쌍들을 분리하여 딕셔너리 생성
info_dict = {}
for item in info_str.split(';'):
if '=' in item:
key, value = item.split('=', 1)
info_dict[key] = value
else:
info_dict[item] = True # 값이 없는 플래그(Flag) 처리
return info_dict
# 3. INFO 파싱 적용 및 데이터프레임 확장
info_df = pd.DataFrame(df['INFO'].apply(parse_info).tolist())
# 4. 기존 컬럼과 합치기 (INFO 원본은 삭제)
final_df = pd.concat([df.drop(columns=['INFO']), info_df], axis=1)
return final_df
# 실행
clinvar_df = read_vcf_full(vcf_path)
데이터프레임을 만드는 과정인데 이게 정말 개같이 오래 걸립니다. 돌려놓고 똥때리고 오십쇼. 왜 오래걸리냐면 쟤가 행만 한 400만개 됨..
clinvar_df.to_csv(f'data/{f_name}.csv', index=False)
print(f'saved: data/{f_name}.csv')
똥때리고 왔더니 데이터프레임이 나왔다... 그럼 csv로 저장하시면 됩니다. 참고로 이거 여는것도 오래 걸림.
근데 태블로가 왜 거기서 나오냐고요? 사람 염색체가 25개입니다. 왜죠? 상염색체 22개+성염색체 두개(XY)+미토콘드리아(얘도 지 유전자가 따로 있음) 해서 25개다. 이걸 하나하나 따로 보는 코딩 자체도 빡세고 귀찮은데 노트북 길어지면 보겠어요? 한 3번염색체까지 보고 에이씨 이거 언제끝나 하겠지. 그리고 저걸 다 시각화하면 그래프가 25개 나오는데 배치도 배치지만 저정도면 그래프 그려도 제대로 안보여요.
그러니까 우리가 할 분석들 중에서 염색체에 대한 시각화를 태블로로 뺄거다. 거기서 대시보드 만들고 필터 만들어서 샥샥 하면 끝남.
'Coding > EDA' 카테고리의 다른 글
| 얘! clinvar도 EDA가 된단다! (3) (0) | 2026.02.18 |
|---|---|
| 얘! clinvar도 EDA가 된단다! (2) (0) | 2026.02.17 |
| Ramen ratings (0) | 2026.02.11 |
| Post-COVID Video Games Worldwide (2021-2025) (0) | 2026.02.10 |
| 또 ChEMBL을 털어보았다 (0) | 2026.01.28 |