Life Table Survivorship Calculator
The life table survivorship calculator converts the observed number of cohort members alive in each consecutive age class into standardized survivorship values.
Run — free
Enter the initial cohort count followed by the survivors recorded at later ages, and the calculator divides every count by the initial cohort size. The result includes age, number surviving, survivorship as a proportion, and survivorship as a percentage, making cohorts of different starting sizes easier to compare without changing the original observations.
Prepare survivor counts in age order
Begin with a cohort whose members are followed through successive age classes. Enter the number alive in the first class first, then add the count alive in each later class in chronological order. The initial value must be greater than zero because it supplies the denominator for every survivorship calculation. Counts must be whole, nonnegative numbers, and they must stay the same or decrease as age advances. A cohort life table tracks the same original group, so an increase would normally indicate that observations from another cohort were added, that an age class was entered out of sequence, or that the values represent something other than survivors. Repeated counts are valid and indicate that no recorded deaths occurred across that interval. A final zero is also valid. Use start age to identify the age attached to the first observation and age interval to describe evenly spaced classes, such as yearly, five-year, or half-year intervals. Keep all ages in one consistent unit and document that unit with your analysis because the output deliberately preserves numeric ages without guessing whether they represent days, months, or years.
Understand the survivorship calculation
For each age class x, age-specific survivorship is calculated as l_x = n_x / n_0, where n_x is the number of cohort members alive at that age and n_0 is the initial cohort size. The first row therefore always has survivorship 1, or 100 percent. Every later result lies between zero and one because a closed cohort cannot gain members. For example, if 760 members remain from an initial 1,000, survivorship is 0.76 and the displayed percentage is 76. This is a proportion of the original cohort, not a conditional probability of surviving only the preceding interval. That distinction matters: interval survival would divide one age-class count by the count immediately before it, whereas this calculator always uses the initial count as the denominator. Values are rounded only to remove floating-point noise and remain precise enough for ordinary demographic, ecological, and laboratory life tables. The output retains the original survivor counts beside the normalized values, so readers can verify the denominator, distinguish small samples from large ones, and reproduce each calculation directly.
Interpret and compare the resulting life table
Read down the life table to see how the original cohort is retained across age. A gradual decline indicates that losses are spread across many classes, while a sharp step identifies an interval before which a large share of the original cohort disappeared. A flat segment means that the recorded number surviving did not change. Because survivorship is normalized to the initial cohort, two cohorts with different starting sizes can be compared on the same proportional scale. Comparisons are most meaningful when their age origins, age intervals, inclusion rules, and observation methods match. The calculation does not correct for migration, missed observations, censoring, sampling error, or individuals that enter after the cohort begins. It also does not estimate mortality hazards or life expectancy; those require additional assumptions and, often, information about deaths or person-time within intervals. Treat the table as a transparent transformation of supplied counts rather than an inferential model. Before publishing a comparison, inspect unexpected increases in the source data, confirm that zero counts are genuine, retain the cohort-size field, and state the age unit so another reader can understand exactly what each row represents.
What you can do with it
Build an ecological survivorship curve
Normalize counts of marked organisms remaining alive at successive ages before plotting survivorship against age.
Compare experimental cohorts
Place treatment and control cohorts with different initial sample sizes on a common proportional survivorship scale.
Check a demographic life table
Recalculate l_x values from published survivor counts and retain the counts beside each proportion for an auditable comparison.
FAQ
What does the calculator cost?
It runs free in your browser. An API request costs $0.002.
What is age-specific survivorship?
It is the proportion of the initial cohort still alive at a particular age, calculated by dividing that age's survivor count by the initial survivor count.
Why must survivor counts never increase?
A cohort life table follows one initial group. Without later entrants, the number of its surviving members can remain unchanged or fall, but cannot rise.
Can age classes use intervals longer than one year?
Yes. Set age_interval to any positive finite value and interpret it in a consistent unit, such as days, months, or years.
Is survivorship the same as survival during an interval?
No. Survivorship uses the initial cohort as its denominator. Conditional interval survival uses the survivor count at the beginning of the particular interval.
Can the final survivor count be zero?
Yes. Zero produces survivorship 0 and indicates that none of the initial cohort remains alive at that age class.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/bio/life-table-survivorship \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"survivors":[1000,920,760,410,0]}'const res = await fetch("https://api.kit.forhosting.com/bio/life-table-survivorship", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"survivors": [
1000,
920,
760,
410,
0
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/bio/life-table-survivorship",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"survivors": [
1000,
920,
760,
410,
0
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/bio/life-table-survivorship", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"survivors":[1000,920,760,410,0]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"survivors":[1000,920,760,410,0]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/bio/life-table-survivorship", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"survivors": [
1000,
920,
760,
410,
0
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "bio.life_table_survivorship",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_items | 1000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |