data = [3, 5, 7, 2, 4, 1] ← 0이 아닌 값들, 열 순서대로
indices = [1, 4, 2, 3, 0, 3] ← 그 값이 몇 번째 행(유전자)이었나
indptr = [0, 2, 4, 6] ← 각 열이 data 의 몇 번째에서 시작하나
indptr 이 핵심입니다. 세포 k 의 값은 data[indptr[k] : indptr[k+1]] 에 있다 —
이 한 줄이 전부예요. 세포 1을 보고 싶으면 data[2:4] = [7, 2], 그 행 번호는 indices[2:4] = [2, 3].
즉 유전자2에 7, 유전자3에 2. 원래 행렬과 일치합니다.
작은 행렬의 칸을 눌러 값을 바꿔 보세요. data · indices · indptr 세 배열이 실시간으로 다시 만들어집니다.
불러오는 중…
직접 만들어 보면 삼총사가 하나도 신비롭지 않습니다.
Python브라우저에서 실행
3.8% 만 채워져 있습니다. 나머지 96.2% 는 전부 0 이에요.
Python브라우저에서 실행
0이 이렇게 많은 것이 정상인가요?
네, 정상입니다. 그리고 그 0에는 두 가지 다른 의미가 섞여 있습니다.
진짜 0 — 그 유전자가 안 켜졌다
T세포에서 S100a8(호중구 유전자)은 정말로 꺼져 있습니다. 이건 정보입니다.
가짜 0 — 놓쳤다 (dropout)
세포 하나에서 mRNA 를 전부 잡지 못합니다. 10x 는 분자의 10~30% 정도만 포착해요. 켜져 있었는데 못 본 겁니다.
이 둘을 구별할 수 없다는 것이 단일세포 자료의 근본적인 한계입니다.
그래서 "이 세포에 Cd8a 가 0이니 CD8 T세포가 아니다" 라고 단정하면 안 됩니다.
대신 세포를 여럿 묶어서(군집) 평균을 보거나, 여러 표지자를 함께 봅니다.
12~14강에서 하게 될 일이 정확히 이것입니다.
세포 하나가 보여 주는 것은 유전자 전체의 5~10% 남짓입니다.
Python브라우저에서 실행
🤔 확인 문제
CSC 형식에서 indptr 의 길이가 1,201 이라면?
해설indptr 은 열의 경계를 찍으므로 길이 = 열 개수 + 1 입니다. 그리고 indptr[-1] 이 0이 아닌 값의 총 개수예요. 이 두 사실만 알면 형식을 몰라도 파일의 모양을 짐작할 수 있습니다.
🤔 확인 문제
어떤 세포에서 Cd8a 값이 0 이었습니다. 올바른 해석은?
해설 10x 는 세포 안 mRNA 의 일부만 포착합니다. 그래서 0은 '없다'가 아니라 '못 봤다'일 수 있습니다. 개별 세포의 유전자 하나로 판단하지 말고, 비슷한 세포를 묶은 뒤 여러 표지자를 함께 보아야 합니다.
🤔 확인 문제
이 조각 파일에서 X.todense() 를 부르는 것이 그나마 가능한 이유는?
해설 조각은 155 MB 라 아슬아슬하게 가능합니다. 하지만 원본 40,100 세포는 10 GB예요. 크기를 먼저 계산하는 습관이 중요한 이유입니다.