순위 리스트가 준비됐습니다. 이제 질문은 이것입니다 —
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]) 의 결과는?
해설누적합입니다 — 각 자리까지의 합을 차례로 쌓습니다. GSEA 에서는 '줄을 걸어오며 쌓인 점수'를 만드는 데 씁니다.
🤔 확인 문제
ES 가 큰 음수라는 것은 무슨 뜻인가요?
해설 줄의 아래쪽은 t 가 가장 음수인, 즉 KD 에서 크게 내려간 유전자들입니다. 거기에 팀원이 몰리면 러닝섬이 깊은 골짜기를 만들어 ES 가 큰 음수가 됩니다.
🤔 확인 문제
팀원 쪽은 |t| 만큼 올리고 남 쪽은 1씩만 내리는 이유는?
해설 '팀원이다'에는 강약이 있습니다(t 가 클수록 강한 증거). 반면 '팀원이 아니다'에는 강약이 없어 모두 똑같이 1씩 내립니다.