18강 / 20강

GSEA ① — 줄을 따라 걸으며 점수 매기기

cumsum 으로 만드는 러닝섬과 ES

GSEA ① — 줄을 따라 걸으며 점수 매기기
순위 줄을 위에서 아래로 걸어가며, 팀원을 만나면 올리고 아니면 내립니다.

순위 리스트가 준비됐습니다. 이제 질문은 이것입니다 — EMT 팀 33명이 이 줄의 어디에 모여 있는가?

GSEA 의 방법은 놀랄 만큼 직관적입니다. 줄의 맨 위에서 아래로 걸어갑니다.

📈
팀원을 만나면
점수를 올린다 (|t| 만큼)
📉
남을 만나면
점수를 조금 내린다
🏔️
ES
걷는 동안의 0에서 가장 먼 지점

팀원이 줄의 위쪽에 몰려 있으면 초반에 점수가 쭉 올라가서 높은 봉우리가 생깁니다 → ES 가 큰 양수.
아래쪽에 몰려 있으면 초반에 계속 내려가다 끝에서야 올라오므로 깊은 골짜기가 생깁니다 → ES 가 큰 음수.
골고루 흩어져 있으면 오르내림이 상쇄되어 0 근처를 맴돕니다.

이 오르내림의 자취를 러닝섬(running sum), 0에서 가장 멀어진 값을 ES(Enrichment Score) 라고 부릅니다.

코드로는 — cumsum 두 번

tag = np.zeros(N); tag[h] = r[h] # 팀원 자리에만 |t| 를 심는다 Ph = np.cumsum(tag) / tag.sum() # 팀원 쪽 누적 비율 (오르는 힘) miss = np.ones(N); miss[h] = 0 # 팀원이 아닌 자리에 1 Pm = np.cumsum(miss) / (N - len(h)) # 남 쪽 누적 비율 (내리는 힘) dd = Ph - Pm # 두 힘의 차이 = 러닝섬 return dd[np.argmax(np.abs(dd))] # 0에서 가장 먼 지점 = ES

cumsum(누적합)이 핵심입니다. [1, 2, 3, 4] 의 cumsum 은 [1, 3, 6, 10] — "여기까지 오는 동안 쌓인 합"이에요. 걸어온 자취를 만드는 데 딱 맞는 도구입니다.

두 누적합을 각각의 총합으로 나누어 0~1 사이 비율로 만든 뒤 빼기 때문에, 세트가 33명이든 300명이든 같은 눈금 위에서 비교할 수 있습니다.

세 가지 경우를 비교하면 ES 의 부호와 크기가 무엇을 뜻하는지 바로 보입니다.
Python 브라우저에서 실행

🎮 러닝섬을 직접 걸어 보기

실제 13,095개 순위 위에서 네 경로의 러닝섬을 그립니다. 세트를 바꿔 가며 봉우리가 어디에 생기는지, 팀원(빨간 눈금)이 어디에 몰려 있는지 확인해 보세요.

러닝섬 실험실 — 경로별 자취와 ES 봉우리
불러오는 중…
EMT · IL6-JAK-STAT3 · TNFA-NFKB 세 팀이 줄의 아래쪽(= KD 에서 내려감)에 몰려 있습니다.
Python 브라우저에서 실행
🤔 확인 문제
np.cumsum([1, 2, 3, 4]) 의 결과는?
🤔 확인 문제
ES 가 큰 음수라는 것은 무슨 뜻인가요?
🤔 확인 문제
팀원 쪽은 |t| 만큼 올리고 남 쪽은 1씩만 내리는 이유는?