Skip to content

Instantly share code, notes, and snippets.

@nstrayer
Last active July 3, 2023 16:22
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nstrayer/4e613a109707f0487da87300097ca502 to your computer and use it in GitHub Desktop.
Save nstrayer/4e613a109707f0487da87300097ca502 to your computer and use it in GitHub Desktop.
Kaplin-Meier Survival Curve with Left-Truncated Data.
license: gpl-3.0

Each bar in the top chart represents an individual's time of entry and exit from a study. The color of the bar indicates which type of exit they had. The bottom chart is a Kaplan-Meier survival curve representing the "survival" of individuals at a given time point. E.g. If the K-M curve = 0.7 at a time of 6 years then 70% of individuals have yet to have the event of study at that time (have survived).

Drag the grey bar across the x-axis to regenerate the K-M curve for the individuals who entered the study past the filter point.

The fact that the survival curve drops to 0 almost immediately when considering all the data illustrates a pitfall of non-parametric methods for generating a survival curve when you have left truncated data. By filtering the data that the curve is generated with, we are generating a conditional survival curve, or he survival curve for an individual given that they have survived to time t.

Data Source

Klein and Moeschberger (1997) Survival Analysis Techniques for Censored and truncated data, Springer. Hyde Biometrika (1977), 225-230.

obs death ageentry age time gender
1 1 1 86.8333333333333 97.6666666666667 130 2
2 2 1 76.75 86.6666666666667 119 2
3 3 1 73.75 83.5833333333333 118 2
4 4 1 75.0833333333333 84.8333333333333 117 2
5 5 1 67.3333333333333 77.6666666666667 124 2
6 6 1 76.25 83.6666666666667 89 2
7 7 1 75.0833333333333 85.25 122 2
8 8 1 71 75.6666666666667 56 2
9 9 1 69 72.3333333333333 40 2
10 10 1 80.6666666666667 82.5 22 2
11 11 1 78 86.0833333333333 97 2
12 12 1 81.4166666666667 88 79 2
13 13 1 77.4166666666667 83.25 70 2
14 14 1 78 88.6666666666667 128 2
15 15 1 84.6666666666667 93.5 106 2
16 16 1 75.8333333333333 85 110 2
17 17 1 95 100 60 2
18 18 1 84.5833333333333 88 41 2
19 19 1 70.8333333333333 78.3333333333333 90 2
20 20 1 74.5833333333333 83 101 2
21 21 1 71.1666666666667 80.75 115 2
22 22 1 79.75 90.75 132 2
23 23 1 84.4166666666667 92.9166666666667 102 2
24 24 1 89.4166666666667 99.3333333333333 119 2
25 25 1 81.3333333333333 90.4166666666667 109 2
26 26 1 72.6666666666667 81.3333333333333 104 2
27 27 1 85.5833333333333 95.1666666666667 115 2
28 28 1 89.25 100 129 2
29 29 1 76.5833333333333 84.75 98 2
30 30 1 74.5 83.8333333333333 112 2
31 31 1 73.75 84.3333333333333 127 2
32 32 1 74.0833333333333 83.3333333333333 111 2
33 33 1 73.9166666666667 84.3333333333333 125 2
34 34 1 76.6666666666667 86.6666666666667 120 2
35 35 1 84.5833333333333 85.3333333333333 9 2
36 36 1 78.5 89.1666666666667 128 2
37 37 1 77 84.5 90 2
38 38 1 73.5833333333333 83 113 2
39 39 1 77.5 78.6666666666667 14 2
40 40 1 79.6666666666667 90.4166666666667 129 2
41 41 1 73.8333333333333 82.8333333333333 108 2
42 42 1 82.25 91.4166666666667 110 2
43 43 1 73.5833333333333 80.5 83 2
44 44 1 69.75 79 111 2
45 45 1 79.8333333333333 85.75 71 2
46 46 1 70.8333333333333 80.25 113 2
47 47 1 74.1666666666667 75.4166666666667 15 2
48 48 1 70.5833333333333 80.8333333333333 123 2
49 49 1 76.5833333333333 84.5833333333333 96 2
50 50 1 62.3333333333333 67 56 2
51 51 1 77.8333333333333 86.75 107 2
52 52 1 74.5833333333333 82.5833333333333 96 2
53 53 1 72.8333333333333 81.8333333333333 108 2
54 54 1 73.0833333333333 82.4166666666667 112 2
55 55 1 75 79.9166666666667 59 2
56 56 1 79.75 90.3333333333333 127 2
57 57 1 84.4166666666667 94.25 118 2
58 58 1 80.5833333333333 89 101 2
59 59 0 75.3333333333333 76.5833333333333 15 2
60 60 0 69.0833333333333 70.6666666666667 19 2
61 61 0 70.1666666666667 81.5833333333333 137 2
62 62 0 66.8333333333333 73 74 2
63 63 0 70 78.1666666666667 98 2
64 64 0 66 77.4166666666667 137 2
65 65 0 69.75 70.6666666666667 11 2
66 66 0 78.4166666666667 83.8333333333333 65 2
67 67 0 62.1666666666667 67 58 2
68 68 0 69.5 77.6666666666667 98 2
69 69 0 72.0833333333333 77.6666666666667 67 2
70 70 0 69 80.4166666666667 137 2
71 71 0 74.5 84.25 117 2
72 72 0 72.8333333333333 84.25 137 2
73 73 0 76.4166666666667 87.8333333333333 137 2
74 74 0 82.75 85.6666666666667 35 2
75 75 0 76.5 87.9166666666667 137 2
76 76 0 68.1666666666667 79.5833333333333 137 2
77 77 0 82 84.9166666666667 35 2
78 78 0 83.5 84.1666666666667 8 2
79 79 0 71.4166666666667 82.8333333333333 137 2
80 80 0 68.9166666666667 69.6666666666667 9 2
81 81 0 73.5833333333333 85 137 2
82 82 0 84 86.8333333333333 34 2
83 83 0 79.5 90.9166666666667 137 2
84 84 0 75.4166666666667 86.8333333333333 137 2
85 85 0 69.8333333333333 81.25 137 2
86 86 0 77.8333333333333 78.8333333333333 12 2
87 87 0 72.6666666666667 78.3333333333333 68 2
88 88 0 76.5 76.8333333333333 4 2
89 89 0 70.3333333333333 81.75 137 2
90 90 0 67.0833333333333 77.3333333333333 123 2
91 91 0 76.8333333333333 88.25 137 2
92 92 0 68.4166666666667 79.8333333333333 137 2
93 93 0 69.8333333333333 81.25 137 2
94 94 0 77.8333333333333 80.0833333333333 27 2
95 95 0 73.8333333333333 85.25 137 2
96 96 0 77.8333333333333 85.25 89 2
97 97 0 73.1666666666667 84.1666666666667 132 2
98 98 0 77.9166666666667 89.3333333333333 137 2
99 99 0 66.5833333333333 68.75 26 2
100 100 0 70.75 79.3333333333333 103 2
101 101 0 76.6666666666667 79.4166666666667 33 2
102 102 1 79 83.1666666666667 50 2
103 103 0 80.6666666666667 92.0833333333333 137 2
104 104 0 75.6666666666667 83 88 2
105 105 0 69 80.4166666666667 137 2
106 106 0 74.75 86.1666666666667 137 2
107 107 0 68.5833333333333 78.1666666666667 115 2
108 108 0 79.1666666666667 84 58 2
109 109 0 87.4166666666667 98.8333333333333 137 2
110 110 0 73.1666666666667 84.5833333333333 137 2
111 111 0 71.1666666666667 82.5833333333333 137 2
112 112 0 73.0833333333333 84.5 137 2
113 113 0 68.3333333333333 79.5833333333333 135 2
114 114 0 74.9166666666667 86.3333333333333 137 2
115 115 0 71.25 74.4166666666667 38 2
116 116 0 68.9166666666667 80.3333333333333 137 2
117 117 0 77.0833333333333 80 35 2
118 118 0 75 86.4166666666667 137 2
119 119 0 77.9166666666667 79 13 2
120 120 0 83.75 87.75 48 2
121 121 0 71.25 82.6666666666667 137 2
122 122 0 76.6666666666667 82.6666666666667 72 2
123 123 0 67.5 74.5833333333333 85 2
124 124 0 66 71.4166666666667 65 2
125 125 0 73.5 84.9166666666667 37 2
126 126 0 77.8333333333333 89.25 137 2
127 127 0 75.8333333333333 87.25 137 2
128 128 0 72.0833333333333 81.0833333333333 110 2
129 129 0 74.9166666666667 86.3333333333333 137 2
130 130 0 81.8333333333333 93.25 137 2
131 131 0 71.3333333333333 82.75 137 2
132 132 0 80.0833333333333 80.25 2 2
133 133 0 74.4166666666667 85.8333333333333 137 2
134 134 0 71.75 83.1666666666667 137 2
135 135 0 69.0833333333333 77.6666666666667 103 2
136 136 0 73.5 84.9166666666667 137 2
137 137 0 72.9166666666667 84.3333333333333 137 2
138 138 0 69.4166666666667 80.8333333333333 137 2
139 139 0 81 84.4166666666667 41 2
140 140 0 67.25 78.6666666666667 137 2
141 141 0 77 79.9166666666667 35 2
142 142 0 70.4166666666667 81.8333333333333 137 2
143 143 0 70 81.4166666666667 137 2
144 144 0 72.25 83.6666666666667 137 2
145 145 0 73.4166666666667 76.0833333333333 32 2
146 146 0 75.0833333333333 76.4166666666667 16 2
147 147 0 78.6666666666667 78.9166666666667 3 2
148 148 0 68.4166666666667 68.6666666666667 3 2
149 149 0 67.5833333333333 74.8333333333333 87 2
150 150 0 83.9166666666667 84.5 7 2
151 151 0 76 87.4166666666667 137 2
152 152 0 66.8333333333333 78.25 137 2
153 153 0 77.3333333333333 88.75 137 2
154 154 0 75.9166666666667 78.1666666666667 27 2
155 155 0 70.5833333333333 74.9166666666667 52 2
156 156 0 86.25 97.6666666666667 137 2
157 157 0 74.4166666666667 81.0833333333333 80 2
158 158 0 76.8333333333333 80.9166666666667 49 2
159 159 0 81.4166666666667 82.0833333333333 8 2
160 160 0 78.4166666666667 78.6666666666667 3 2
161 161 0 72.4166666666667 83.8333333333333 137 2
162 162 0 73.75 79.5833333333333 70 2
163 163 0 71.5833333333333 83 137 2
164 164 0 79 90.4166666666667 137 2
165 165 0 74.1666666666667 83.75 115 2
166 166 0 73.9166666666667 74.25 4 2
167 167 0 80.6666666666667 92.0833333333333 137 2
168 168 0 77.25 82.4166666666667 62 2
169 169 0 83.0833333333333 94.5 137 2
170 170 0 70.5 81.9166666666667 137 2
171 171 0 69.25 71.75 30 2
172 172 0 70.1666666666667 81.5833333333333 137 2
173 173 0 64 75.4166666666667 137 2
174 174 0 74.6666666666667 86.0833333333333 137 2
175 175 0 74.5 84.5 120 2
176 176 0 73.75 85.1666666666667 137 2
177 177 0 68.5 79.9166666666667 137 2
178 178 0 77.25 79.5 27 2
179 179 0 74.75 75.3333333333333 7 2
180 180 0 70.6666666666667 82.0833333333333 137 2
181 181 0 76 83.4166666666667 89 2
182 182 0 71.9166666666667 83.3333333333333 137 2
183 183 0 67.75 79.1666666666667 137 2
184 184 0 66.8333333333333 78.25 137 2
185 185 0 79.6666666666667 88.4166666666667 105 2
186 186 0 68.5 78.75 123 2
187 187 0 77.8333333333333 82.75 59 2
188 188 0 85.5 87.8333333333333 28 2
189 189 0 81.75 92.8333333333333 133 2
190 190 0 77.8333333333333 89.25 137 2
191 191 0 69.6666666666667 77.25 91 2
192 192 0 63.3333333333333 74.75 137 2
193 193 0 68.3333333333333 79.75 137 2
194 194 0 75.5833333333333 87 137 2
195 195 0 81.5833333333333 84.6666666666667 37 2
196 196 0 74.5 85.9166666666667 137 2
197 197 0 71 82.4166666666667 137 2
198 198 0 79 80.9166666666667 23 2
199 199 0 67.75 79.1666666666667 137 2
200 200 0 75.1666666666667 85.3333333333333 122 2
201 201 0 73.5 84.9166666666667 137 2
202 202 0 67.9166666666667 79.3333333333333 137 2
203 203 1 81 90.25 111 2
204 204 0 81.0833333333333 82.0833333333333 12 2
205 205 0 79.75 79.75 0 2
206 206 0 84.1666666666667 95.5833333333333 137 2
207 207 0 89.1666666666667 100.583333333333 137 2
208 208 0 74.5833333333333 86 137 2
209 209 0 68.1666666666667 71.6666666666667 42 2
210 210 0 72 83.4166666666667 137 2
211 211 0 71.4166666666667 82.8333333333333 137 2
212 212 0 85.6666666666667 88.5833333333333 35 2
213 213 0 74.3333333333333 85.75 137 2
214 214 0 64.0833333333333 75.5 137 2
215 215 0 73.5833333333333 85 137 2
216 216 0 81 92.4166666666667 137 2
217 217 0 80.4166666666667 90.6666666666667 123 2
218 218 0 77.0833333333333 80.0833333333333 36 2
219 219 0 67.8333333333333 72.6666666666667 58 2
220 220 0 67.0833333333333 78.5 137 2
221 221 0 82.6666666666667 84.1666666666667 18 2
222 222 0 78.5833333333333 90 137 2
223 223 0 79.25 79.8333333333333 7 2
224 224 0 77.1666666666667 82.25 61 2
225 225 0 79.5 80.1666666666667 8 2
226 226 0 78.6666666666667 78.6666666666667 0 2
227 227 0 77.9166666666667 77.9166666666667 0 2
228 228 0 75 76 12 2
229 229 0 63.5 71.1666666666667 92 2
230 230 0 68.5833333333333 73.5 59 2
231 231 1 81.5 84.1666666666667 32 2
232 232 1 80.5 85.5833333333333 61 2
233 233 0 76 76.3333333333333 4 2
234 234 0 68.5833333333333 69.0833333333333 6 2
235 235 0 75.75 77.75 24 2
236 236 1 80.5833333333333 86.75 74 2
237 237 1 70.9166666666667 75.4166666666667 54 2
238 238 1 70.25 71.75 18 2
239 239 1 80.25 85.0833333333333 58 2
240 240 1 74 76.5833333333333 31 2
241 241 0 66.1666666666667 66.5 4 2
242 242 1 75.4166666666667 77.3333333333333 23 2
243 243 1 86.5833333333333 90.5 47 2
244 244 1 75.0833333333333 76.9166666666667 22 2
245 245 1 68.5833333333333 69.1666666666667 7 2
246 246 1 67.4166666666667 68.5 13 2
247 247 0 73.9166666666667 75.4166666666667 18 2
248 248 1 71.5833333333333 77.1666666666667 67 2
249 249 0 83.6666666666667 84.5833333333333 11 2
250 250 1 76.5833333333333 77.5833333333333 12 2
251 251 0 76.0833333333333 87.5 137 2
252 252 0 67.5 67.6666666666667 2 2
253 253 0 70.0833333333333 81.5 137 2
254 254 0 72.9166666666667 84.3333333333333 137 2
255 255 0 70.0833333333333 77.25 86 2
256 256 0 79 84.3333333333333 64 2
257 257 1 71.5833333333333 82.9166666666667 136 2
258 258 0 68.3333333333333 79.75 137 2
259 259 0 71.6666666666667 83.0833333333333 137 2
260 260 0 76.4166666666667 79 31 2
261 261 0 78 89.4166666666667 137 2
262 262 0 79.1666666666667 82.1666666666667 36 2
263 263 0 84.4166666666667 85.9166666666667 18 2
264 264 0 70.5833333333333 82 137 2
265 265 0 64.75 76.1666666666667 137 2
266 266 0 80 82.3333333333333 28 2
267 267 0 76.6666666666667 88.0833333333333 137 2
268 268 0 77.9166666666667 87.5833333333333 116 2
269 269 0 77.75 81.5833333333333 46 2
270 270 0 77.75 82.0833333333333 52 2
271 271 0 66.4166666666667 77.8333333333333 137 2
272 272 0 61.0833333333333 72.5 137 2
273 273 0 72.1666666666667 79.4166666666667 87 2
274 274 0 72.5 77.5 60 2
275 275 0 66.25 72.9166666666667 80 2
276 276 1 75.4166666666667 83.75 100 2
277 277 0 66.3333333333333 74.25 95 2
278 278 0 80.4166666666667 91.8333333333333 137 2
279 279 0 64.5833333333333 76 137 2
280 280 0 78.5 81.4166666666667 35 2
281 281 0 74.5833333333333 77.1666666666667 31 2
282 282 0 81.75 86.5 57 2
283 283 0 82.5833333333333 83.8333333333333 15 2
284 284 0 74.5 76.5 24 2
285 285 0 73.8333333333333 78.5833333333333 57 2
286 286 0 72.5833333333333 77 53 2
287 287 0 69.9166666666667 81.3333333333333 137 2
288 288 0 69.9166666666667 81.3333333333333 137 2
289 289 0 71.5 82.9166666666667 137 2
290 290 0 69.1666666666667 80.5833333333333 137 2
291 291 0 72.3333333333333 83.75 137 2
292 292 0 69.25 77.0833333333333 94 2
293 293 0 65.25 74 105 2
294 294 0 77.0833333333333 88.5 137 2
295 295 0 74.8333333333333 86.25 137 2
296 296 0 75.8333333333333 84.0833333333333 99 2
297 297 0 79.8333333333333 84 50 2
298 298 0 72.1666666666667 83.5833333333333 137 2
299 299 0 70.9166666666667 82.3333333333333 137 2
300 300 0 75.5 86.9166666666667 137 2
301 301 1 79.8333333333333 86.75 83 2
302 302 1 83.5833333333333 91.0833333333333 90 2
303 303 1 72.5833333333333 78.6666666666667 73 2
304 304 1 72 72.75 9 2
305 305 1 83 89.4166666666667 77 2
306 306 1 86.1666666666667 89 34 2
307 307 1 72.75 74.75 24 2
308 308 1 82 87.25 63 2
309 309 1 78.5833333333333 84.25 68 2
310 310 1 83.9166666666667 84.9166666666667 12 2
311 311 1 77.9166666666667 83.8333333333333 71 2
312 312 1 77.4166666666667 83 67 2
313 313 1 78.25 81.5 39 2
314 314 1 64.3333333333333 70 68 2
315 315 0 72.5833333333333 76 41 2
316 316 1 72.75 79.5 81 2
317 317 1 81.75 84.8333333333333 37 2
318 318 0 74.5 77.25 33 2
319 319 1 82.8333333333333 86.6666666666667 46 2
320 320 1 81.3333333333333 82.9166666666667 19 2
321 321 1 70.5833333333333 73.5833333333333 36 2
322 322 1 71.5833333333333 78.4166666666667 82 2
323 323 1 77.75 82.5 57 2
324 324 1 71.75 77.8333333333333 73 2
325 325 1 73.8333333333333 75.6666666666667 22 2
326 326 1 78.5833333333333 82.1666666666667 43 2
327 327 1 77.5833333333333 80.75 38 2
328 328 1 79 84.9166666666667 71 2
329 329 1 79.5833333333333 82.6666666666667 37 2
330 330 1 83.6666666666667 85.25 19 2
331 331 1 69 74.5833333333333 67 2
332 332 1 69.5833333333333 70.4166666666667 10 2
333 333 0 72.3333333333333 72.5 2 2
334 334 1 82.3333333333333 89.5 86 2
335 335 1 71.75 77.5 69 2
336 336 0 79.9166666666667 81.3333333333333 17 2
337 337 1 71.5833333333333 76 53 2
338 338 0 72.5833333333333 72.8333333333333 3 2
339 339 0 70.5833333333333 74.3333333333333 45 2
340 340 1 72.8333333333333 73.75 11 2
341 341 1 82.6666666666667 87 52 2
342 342 1 85.5833333333333 89.3333333333333 45 2
343 343 1 71.4166666666667 75.0833333333333 44 2
344 344 1 82.8333333333333 84.4166666666667 19 2
345 345 1 86.75 86.9166666666667 2 2
346 346 0 75 77.1666666666667 26 2
347 347 1 91.3333333333333 96 56 2
348 348 1 77.5 78 6 2
349 349 1 78.5833333333333 82.8333333333333 51 2
350 350 1 85.3333333333333 88.5833333333333 39 2
351 351 0 66.8333333333333 68.4166666666667 19 2
352 352 0 67.5833333333333 68.25 8 2
353 353 1 77.25 83.4166666666667 74 2
354 354 1 80.5833333333333 81.25 8 2
355 355 1 78.5833333333333 81.8333333333333 39 2
356 356 0 70 75.4166666666667 65 2
357 357 1 81.5833333333333 86.6666666666667 61 2
358 358 0 76.75 77.1666666666667 5 2
359 359 1 82.1666666666667 85.8333333333333 44 2
360 360 1 86.5833333333333 94.3333333333333 93 2
361 361 1 80.6666666666667 82.5 22 2
362 362 1 79.5833333333333 82.5 35 2
363 363 1 69.75 75.9166666666667 74 2
364 364 1 71.75 76.25 54 2
365 365 1 80.5833333333333 81.9166666666667 16 2
366 366 1 65.1666666666667 75.75 127 1
367 367 1 85 94 108 1
368 368 1 71.3333333333333 80.75 113 1
369 369 1 76.25 79.75 42 1
370 370 1 71.9166666666667 81.9166666666667 120 1
371 371 1 75.5 84.3333333333333 106 1
372 372 1 79.5833333333333 87.9166666666667 100 1
373 373 1 78.5833333333333 85.4166666666667 82 1
374 374 1 78.5833333333333 86.9166666666667 100 1
375 375 1 69.75 78.75 108 1
376 376 1 80.5 84.0833333333333 43 1
377 377 1 78 80.9166666666667 35 1
378 378 1 76.5833333333333 86.0833333333333 114 1
379 379 1 71 72.4166666666667 17 1
380 380 1 89.4166666666667 94.9166666666667 66 1
381 381 1 77.0833333333333 86.3333333333333 111 1
382 382 1 80.5833333333333 90.4166666666667 118 1
383 383 0 67.1666666666667 78.5833333333333 137 1
384 384 0 80.75 83.4166666666667 32 1
385 385 0 76.9166666666667 88.3333333333333 137 1
386 386 0 72.0833333333333 83.5 137 1
387 387 0 79.4166666666667 85.9166666666667 78 1
388 388 0 72.5833333333333 78.75 74 1
389 389 0 81.8333333333333 83.8333333333333 24 1
390 390 0 73.5833333333333 79.9166666666667 76 1
391 391 0 68.0833333333333 70.25 26 1
392 392 0 72.9166666666667 84.3333333333333 137 1
393 393 0 68.4166666666667 79.6666666666667 135 1
394 394 0 78 89.4166666666667 137 1
395 395 0 80.9166666666667 92.25 136 1
396 396 0 69.1666666666667 78.3333333333333 110 1
397 397 0 73.75 75.9166666666667 26 1
398 398 0 74.5 85.9166666666667 137 1
399 399 0 74.4166666666667 83 103 1
400 400 0 72.1666666666667 74.5833333333333 29 1
401 401 0 73.1666666666667 84.5833333333333 137 1
402 402 0 68.3333333333333 79.75 137 1
403 403 0 83.9166666666667 86.9166666666667 36 1
404 404 0 73.25 84.6666666666667 137 1
405 405 0 79.6666666666667 91.0833333333333 137 1
406 406 1 71.1666666666667 82.4166666666667 135 1
407 407 0 74.1666666666667 85.5833333333333 137 1
408 408 0 86.75 87 3 1
409 409 0 81.5 83.75 27 1
410 410 0 69.6666666666667 81.0833333333333 137 1
411 411 0 78.1666666666667 88.6666666666667 126 1
412 412 0 73.8333333333333 85.25 137 1
413 413 0 73 84.4166666666667 137 1
414 414 0 79.5833333333333 81.4166666666667 22 1
415 415 0 68.5833333333333 80 137 1
416 416 0 80 87.25 87 1
417 417 0 70.25 78.5833333333333 100 1
418 418 0 71.3333333333333 79.25 95 1
419 419 0 70.5833333333333 82 137 1
420 420 0 85.5833333333333 88.1666666666667 31 1
421 421 0 82.3333333333333 87.0833333333333 57 1
422 422 0 79.4166666666667 79.4166666666667 0 1
423 423 0 81.5 84.8333333333333 40 1
424 424 0 81.75 93.1666666666667 137 1
425 425 0 77.1666666666667 80.8333333333333 44 1
426 426 0 86.3333333333333 89.1666666666667 34 1
427 427 0 84.6666666666667 96.0833333333333 137 1
428 428 0 80.75 92.1666666666667 137 1
429 429 0 75 78 36 1
430 430 0 74.8333333333333 75.5 8 1
431 431 0 70.5 72.1666666666667 20 1
432 432 1 80.3333333333333 85.75 65 1
433 433 1 82 87.75 69 1
434 434 1 87.1666666666667 90 34 1
435 435 1 72.5833333333333 72.6666666666667 1 1
436 436 1 70.5833333333333 74.4166666666667 46 1
437 437 0 80.1666666666667 80.5 4 1
438 438 1 71.0833333333333 74.5 41 1
439 439 1 80.5833333333333 82.0833333333333 18 1
440 440 1 88.5833333333333 91.1666666666667 31 1
441 441 1 71.3333333333333 77.25 71 1
442 442 1 72.0833333333333 79 83 1
443 443 1 87.5833333333333 88.25 8 1
444 444 1 84.1666666666667 84.3333333333333 2 1
445 445 1 73.1666666666667 75.9166666666667 33 1
446 446 1 85.0833333333333 91.1666666666667 73 1
447 447 0 79.9166666666667 81 13 1
448 448 1 76.75 82.75 72 1
449 449 1 69.6666666666667 73 40 1
450 450 1 76.5833333333333 82.75 74 1
451 451 1 62.5833333333333 64.75 26 1
452 452 1 75.5 80.5 60 1
453 453 1 69.5833333333333 75.5833333333333 72 1
454 454 1 78.8333333333333 85.9166666666667 85 1
455 455 1 63.25 65.0833333333333 22 1
456 456 0 75.75 76.1666666666667 5 1
457 457 1 80.1666666666667 83.1666666666667 36 1
458 458 1 82 85.1666666666667 38 1
459 459 1 74.25 77.6666666666667 41 1
460 460 1 69.5833333333333 74.8333333333333 63 1
461 461 1 86.5833333333333 88.3333333333333 21 1
462 462 1 84.1666666666667 87 34 1
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
svg text{
font-family:optima;
}
svg text .title{
font-size: 2em;
}
.lifespan .outside_brush {
fill-opacity: 0.1
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 2px;
}
</style>
<body>
<div id = "chart"></div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
<script>
//load survival data in.
d3.csv("data.csv", function(raw_data){
//Data cleaning:
var data = raw_data.map(function(d){
var new_d = {}
new_d.age_entry_year = +d.ageentry/12; //patient start
new_d.age_year = +d.age/12; //patient end
new_d.death = d.death == "1" ? true : false;
new_d.gender = d.gender == "2" ? "female" : "male"
return new_d;
})
.sort((a,b) => b.age_entry_year - a.age_entry_year)
.filter(d => d.gender == "male")
//charting code goes here.
var chartWidth = 960, // default width
chartHeight = 500;
var margin = {top: 20, right: 40, bottom: 35, left: 30},
width = chartWidth - margin.left - margin.right,
height = chartHeight - margin.top - margin.bottom;
// var svg = d3.select(this).append("svg") //leaving for when packaged up.
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var min_date = d3.min(data, (d) => d.age_entry_year)
var max_date = d3.max(data, (d) => d.age_year)
var x = d3.scaleLinear()
.range([0, width])
.domain([min_date, max_date]);
//y scale for the data chart on top
var y = d3.scaleLinear()
.range([height/2 - 20, 0])
.domain([0,data.length]);
//y scale for the survival plot on bottom
var y_surv = d3.scaleLinear()
.range([height, height/2 + 10])
.domain([0,1]);
var lines = svg.selectAll(".lifespan")
.data(data)
.enter().append("line")
.attr("class", "lifespan")
.attrs({
"x1": (d) => x(d.age_entry_year),
"x2": (d) => x(d.age_entry_year),
"y1": (d,i) => y(i),
"y2": (d,i) => y(i),
"stroke": (d) => d.death ? "steelblue": "orangered",
"stroke-width": 1
})
.on("mouseover", highlight)
.on("mouseout", unhighlight)
.transition().duration(500)
.delay(function(d, i) { return (data.length - i) * 5; })
.attr("x2", (d) => x(d.age_year))
svg.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.append("text")
.attrs({
"class": "axis-title",
"y": 20,
"x": width/2,
"dy": "0.8em"
})
.styles({
"text-anchor": "center",
"fill": "black",
"font-size": 15
})
.text("Time in Years");
//////////////////////////////// Make legend ////////////////////////////////////////////////
var legend = svg.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + width + "," + margin.top + ")");
var titleAttributes = {
"fill": "#636363",
"text-anchor": "end",
"font-size": "2em"
}
var legendAttributes = {
"x": -5,
"text-anchor": "end",
}
legend.append("text")
.text("Data/Individuals")
.attrs(titleAttributes)
legend.append("text")
.text("Event")
.attrs(legendAttributes)
.attrs({
"y": "2.5em",
"fill": "steelblue"
})
legend.append("text")
.text("Censored")
.attrs(legendAttributes)
.attrs({
"y": "3.5em",
"fill": "orangered"
})
svg.append("text")
.text("K-M Survival Curve")
.attrs(titleAttributes)
.attr("transform", "translate(" + width + "," + (height/2 + margin.top*2) + ")");
//////////////// Drawing the Survival Function //////////////
//draw bar above to seperate the two plots from eachother
svg.append("line")
.attrs({
x1: 0, x2: width,
y1: height/2, y2: height/2,
stroke: "black",
"stroke-width": 1,
opacity: 0.3
})
var km_surv = KM_Curve(data);
km_surv.unshift({"t_i": min_date, "d_i": 0, "Y_i": 0, "s_t": 0, "S_t": 1})
var surv_func = svg.append("g")
.attr("class", "survival_function")
var line = d3.line()
.curve(d3.curveStepAfter)
.x(d => x(d.t_i) )
.y(d => y_surv(d.S_t));
surv_func.append("path")
.datum(km_surv)
.attr("class", "line")
.attr("d", line);
function update_survival(newData){
surv_func.select(".line")
.datum(newData)
.transition().duration(500)
.attr("d", line);
}
svg.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y_surv))
////////////// A bar to drag to filter the conditional entry time. //////////////
drag_behavior = d3.drag()
.on("drag", function(){
var x_loc = d3.event.x;
x_loc = x_loc < 0 ? 0 : x_loc,
x_loc = x_loc > width ? width : x_loc,
time_loc = x.invert(x_loc);
//move bar.
d3.select(".drag_bar")
.attr("transform", "translate(" + x_loc + ",0)")
.select("text")
.text("entry ≥ " + time_loc.roundTo(2) + " years");
d3.select(this)
.attr("x", x_loc - 15);
svg.selectAll(".lifespan")
.attr("opacity", (d) => d.age_entry_year < time_loc ? 0.1: 1)
.classed("ignored", (d) => d.age_entry_year < time_loc)
.classed("dragging", true)
} )
.on("end", function(){
svg.selectAll(".lifespan")
.classed("dragging", false)
//generate new KM curve data.
//only include current individuals.
km_data = data.filter((d) => d.age_entry_year >= time_loc)
km_surv = KM_Curve(km_data)
km_surv.unshift({"t_i": time_loc, "d_i": 0, "Y_i": 0, "s_t": 0, "S_t": 1})
update_survival(km_surv);
})
//make grabber bar
//Function javascript should really already have.
Number.prototype.roundTo = function(digits){
return +(Math.round(this + "e+" + digits) + "e-" + digits);
}
//grabber box to do the dragging.
svg.append("rect")
.attrs({
x: -15,
y: height/2 - 25,
rx: 2, ry:2,
width: 15,
height: 25,
fill: "#636363",
class: "drag_screen"
})
.call(drag_behavior);
var drag_bar = svg.append("g")
.attr("class", "drag_bar")
.style("pointer-events", "none")
drag_bar.append("rect")
.attrs({
x: -1,
width: 2,
height: height,
fill: "#636363",
opacity: 0.5,
class: "drag_screen"
})
drag_bar.append("text")
.text("entry ≥ " + min_date.roundTo(2) + " years")
.attrs({
"y": (height/2) - 3,
"x": 3,
"fill": "#636363",
"text-anchor": "start"
})
////////////// End drag bar //////////////
function highlight(){
var individual = d3.select(this);
//dont do behavior for the non-selected individuals or when dragging the bar.
if(individual.classed("ignored") || individual.classed("dragging")) return;
var y_pos = individual.attr("y1")
individual
.attr("stroke-width", "5")
var ind_data = individual.data()
.map(function(d){
return {
"entry": d.age_entry_year,
"exit" : d.age_year
}
})[0]
var bound_bar_data = [
{side: "left", x:individual.attr("x1"), value: ind_data.entry.roundTo(3)},
{side: "right", x:individual.attr("x2"), value: ind_data.exit.roundTo(3)}
]
var bounds_bars = svg.append("g")
.attr("class", "bounds_bars")
bounds_bars.selectAll("line")
.data(bound_bar_data)
.enter().append("line")
.attrs({
"x1": (d) => d.x,
"x2": (d) => d.x,
"y1": y_pos,
"y2": height,
"stroke": "black",
"stroke-width": 1
})
bounds_bars.selectAll("text")
.data(bound_bar_data)
.enter().append("text")
.text( (d) => d.value )
.attrs({
"x": (d) => d.x,
"y": height,
"text-anchor": (d) => d.side == "left" ? "end" : "start",
"font-size": 12
})
}
function unhighlight(){
d3.select(this).attr("stroke-width", 1)
svg.select(".bounds_bars").remove()
}
///////////////////////////// Generate a K-M non-parametric survival curve for data.
function KM_Curve(data){
//Source http://stackoverflow.com/questions/11246758/how-to-get-unique-values-in-an-array
Array.prototype.contains = function(v) {
for(var i = 0; i < this.length; i++) {
if(this[i] === v) return true;
}
return false;
};
Array.prototype.unique = function() {
var arr = [];
for(var i = 0; i < this.length; i++) {
if(!arr.contains(this[i])) {
arr.push(this[i]);
}
}
return arr;
}
//get unique times of death.
death_times = data.filter(d => d.death)
.map(d => d.age_year)
.unique()
.sort()
km_table = death_times.map(t_i => {
//Number of deaths at t_i
var d_i = data.filter(d => d.age_year == t_i && d.death).length
//number at risk. Aka in study, but havent had event yet.
var Y_i = data.filter(d => d.age_entry_year <= t_i && d.age_year >= t_i).length
var s_t = 1 - (d_i/Y_i);
return {"t_i": t_i, "d_i": d_i, "Y_i": Y_i, "s_t": s_t}
})
for (let [i, row] of km_table.entries()) {
var t = row.t_i,
s_t = row.s_t,
last_S_t = i != 0 ? km_table[i-1].S_t : 1;
km_table[i].S_t = last_S_t * s_t;
}
// console.table(km_table)
return km_table;
}
}) //close csv loader
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment