Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Mammal Data Correlations</title> | |
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/regression"></script> | |
<style> | |
body { | |
font-family: Arial, sans-serif; | |
margin: 20px; | |
background-color: #f9f9f9; | |
} | |
.chartContainer { | |
width: 80%; | |
margin: 20px auto; | |
background-color: white; | |
padding: 20px; | |
border-radius: 10px; | |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
} | |
.accuracy { | |
text-align: center; | |
margin-top: 20px; | |
} | |
table { | |
width: 80%; | |
margin: 20px auto; | |
border-collapse: collapse; | |
background-color: white; | |
border-radius: 10px; | |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
} | |
table, th, td { | |
border: 1px solid black; | |
} | |
th, td { | |
padding: 8px; | |
text-align: center; | |
} | |
.background { | |
width: 80%; | |
margin: 20px auto; | |
padding: 20px; | |
background-color: white; | |
border-radius: 10px; | |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
} | |
.attribution { | |
text-align: center; | |
margin-top: 20px; | |
font-style: italic; | |
color: #555; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Mammal Data Correlations</h1> | |
<!-- Background Section --> | |
<div class="background"> | |
<h2>Background</h2> | |
<p> | |
This project investigates the relationship between gestation periods and various biological traits in mammals. | |
The central question is: <strong>How does the time for gestation correlate with brain size, baby size, and baby volume?</strong> | |
By analyzing data from a variety of mammals, we aim to uncover patterns and trends that can help us understand the evolutionary and biological significance of gestation periods. | |
</p> | |
</div> | |
<!-- Chart 1: Gestation vs. Brain Size --> | |
<div class="chartContainer"> | |
<h2>Gestation Period vs. Brain Size</h2> | |
<canvas id="chart1"></canvas> | |
<div class="accuracy"> | |
<p>Best Fit: <span id="bestFit1"></span> (R²: <span id="bestFitAccuracy1"></span>)</p> | |
<p>Equation: <span id="equation1"></span></p> | |
<p>Other Models:</p> | |
<ul> | |
<li>Linear: R² = <span id="linearAccuracy1"></span></li> | |
<li>Exponential: R² = <span id="expAccuracy1"></span></li> | |
<li>Quadratic: R² = <span id="quadAccuracy1"></span></li> | |
</ul> | |
</div> | |
</div> | |
<!-- Chart 2: Gestation vs. Baby Size --> | |
<div class="chartContainer"> | |
<h2>Gestation Period vs. Baby Size</h2> | |
<canvas id="chart2"></canvas> | |
<div class="accuracy"> | |
<p>Best Fit: <span id="bestFit2"></span> (R²: <span id="bestFitAccuracy2"></span>)</p> | |
<p>Equation: <span id="equation2"></span></p> | |
<p>Other Models:</p> | |
<ul> | |
<li>Linear: R² = <span id="linearAccuracy2"></span></li> | |
<li>Exponential: R² = <span id="expAccuracy2"></span></li> | |
<li>Quadratic: R² = <span id="quadAccuracy2"></span></li> | |
</ul> | |
</div> | |
</div> | |
<!-- Chart 3: Gestation vs. Baby Volume --> | |
<div class="chartContainer"> | |
<h2>Gestation Period vs. Baby Volume</h2> | |
<canvas id="chart3"></canvas> | |
<div class="accuracy"> | |
<p>Best Fit: <span id="bestFit3"></span> (R²: <span id="bestFitAccuracy3"></span>)</p> | |
<p>Equation: <span id="equation3"></span></p> | |
<p>Other Models:</p> | |
<ul> | |
<li>Linear: R² = <span id="linearAccuracy3"></span></li> | |
<li>Exponential: R² = <span id="expAccuracy3"></span></li> | |
<li>Quadratic: R² = <span id="quadAccuracy3"></span></li> | |
</ul> | |
</div> | |
</div> | |
<!-- Chart 4: Gestation vs. Brain-to-Baby Size Ratio --> | |
<div class="chartContainer"> | |
<h2>Gestation Period vs. Brain-to-Baby Size Ratio</h2> | |
<canvas id="chart4"></canvas> | |
<div class="accuracy"> | |
<p>Best Fit: <span id="bestFit4"></span> (R²: <span id="bestFitAccuracy4"></span>)</p> | |
<p>Equation: <span id="equation4"></span></p> | |
<p>Other Models:</p> | |
<ul> | |
<li>Linear: R² = <span id="linearAccuracy4"></span></li> | |
<li>Exponential: R² = <span id="expAccuracy4"></span></li> | |
<li>Quadratic: R² = <span id="quadAccuracy4"></span></li> | |
</ul> | |
</div> | |
</div> | |
<!-- Table --> | |
<table> | |
<thead> | |
<tr> | |
<th>Mammal</th> | |
<th>Gestation (Days)</th> | |
<th>Brain Size (grams)</th> | |
<th>Baby Size (kg)</th> | |
<th>Baby Volume (liters)</th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr> | |
<td>African Elephant</td> | |
<td>655</td> | |
<td>2300</td> | |
<td>120</td> | |
<td>90</td> | |
</tr> | |
<tr> | |
<td>Asian Elephant</td> | |
<td>617</td> | |
<td>2000</td> | |
<td>100</td> | |
<td>80</td> | |
</tr> | |
<tr> | |
<td>Sperm Whale</td> | |
<td>535</td> | |
<td>7800</td> | |
<td>1000</td> | |
<td>1000</td> | |
</tr> | |
<tr> | |
<td>Orca</td> | |
<td>532</td> | |
<td>3500</td> | |
<td>180</td> | |
<td>180</td> | |
</tr> | |
<tr> | |
<td>Indian Rhinoceros</td> | |
<td>478</td> | |
<td>400</td> | |
<td>60</td> | |
<td>60</td> | |
</tr> | |
<tr> | |
<td>White Rhinoceros</td> | |
<td>467</td> | |
<td>350</td> | |
<td>50</td> | |
<td>50</td> | |
</tr> | |
<tr> | |
<td>Giraffe</td> | |
<td>430</td> | |
<td>500</td> | |
<td>100</td> | |
<td>100</td> | |
</tr> | |
<tr> | |
<td>Bactrian Camel</td> | |
<td>390</td> | |
<td>300</td> | |
<td>35</td> | |
<td>35</td> | |
</tr> | |
<tr> | |
<td>Bottlenose Dolphin</td> | |
<td>364</td> | |
<td>750</td> | |
<td>15</td> | |
<td>15</td> | |
</tr> | |
<tr> | |
<td>Horse</td> | |
<td>336</td> | |
<td>400</td> | |
<td>50</td> | |
<td>50</td> | |
</tr> | |
<tr> | |
<td>Human</td> | |
<td>270</td> | |
<td>350</td> | |
<td>3.5</td> | |
<td>3.5</td> | |
</tr> | |
<tr> | |
<td>Gorilla</td> | |
<td>257</td> | |
<td>200</td> | |
<td>2</td> | |
<td>2</td> | |
</tr> | |
<tr> | |
<td>Chimpanzee</td> | |
<td>240</td> | |
<td>150</td> | |
<td>1.8</td> | |
<td>1.8</td> | |
</tr> | |
<tr> | |
<td>Polar Bear</td> | |
<td>241</td> | |
<td>25</td> | |
<td>0.6</td> | |
<td>0.6</td> | |
</tr> | |
<tr> | |
<td>Domestic Cat</td> | |
<td>64</td> | |
<td>5</td> | |
<td>0.1</td> | |
<td>0.1</td> | |
</tr> | |
<tr> | |
<td>Domestic Dog</td> | |
<td>61</td> | |
<td>10</td> | |
<td>0.3</td> | |
<td>0.3</td> | |
</tr> | |
<tr> | |
<td>Mouse</td> | |
<td>19</td> | |
<td>0.1</td> | |
<td>0.001</td> | |
<td>0.001</td> | |
</tr> | |
<tr> | |
<td>Rat</td> | |
<td>22</td> | |
<td>0.2</td> | |
<td>0.005</td> | |
<td>0.005</td> | |
</tr> | |
<tr> | |
<td>Virginia Opossum</td> | |
<td>12</td> | |
<td>0.05</td> | |
<td>0.002</td> | |
<td>0.002</td> | |
</tr> | |
<tr> | |
<td>Kangaroo</td> | |
<td>42</td> | |
<td>5</td> | |
<td>0.8</td> | |
<td>0.8</td> | |
</tr> | |
</tbody> | |
</table> | |
<!-- Attribution --> | |
<div class="attribution"> | |
<p>Made by Julian Herrera for 2025 Bio Class - Jan 14</p> | |
</div> | |
<script> | |
// Data from the table | |
const data = { | |
mammals: [ | |
"African Elephant", "Asian Elephant", "Sperm Whale", "Orca", "Indian Rhinoceros", | |
"White Rhinoceros", "Giraffe", "Bactrian Camel", "Bottlenose Dolphin", "Horse", | |
"Human", "Gorilla", "Chimpanzee", "Polar Bear", "Domestic Cat", "Domestic Dog", | |
"Mouse", "Rat", "Virginia Opossum", "Kangaroo" | |
], | |
gestation: [ | |
655, 617, 535, 532, 478, 467, 430, 390, 364, 336, 270, 257, 240, 241, 64, 61, 19, 22, 12, 42 | |
], | |
brainSize: [ | |
2300, 2000, 7800, 3500, 400, 350, 500, 300, 750, 400, 350, 200, 150, 25, 5, 10, 0.1, 0.2, 0.05, 5 | |
], | |
babySize: [ | |
120, 100, 1000, 180, 60, 50, 100, 35, 15, 50, 3.5, 2, 1.8, 0.6, 0.1, 0.3, 0.001, 0.005, 0.002, 0.8 | |
], | |
babyVolume: [ | |
90, 80, 1000, 180, 60, 50, 100, 35, 15, 50, 3.5, 2, 1.8, 0.6, 0.1, 0.3, 0.001, 0.005, 0.002, 0.8 | |
] | |
}; | |
// Function to remove outliers using IQR | |
function removeOutliers(xData, yData) { | |
const combinedData = xData.map((x, i) => ({ x, y: yData[i] })); | |
// Calculate quartiles and IQR for yData | |
const sortedY = yData.slice().sort((a, b) => a - b); | |
const Q1 = sortedY[Math.floor(sortedY.length * 0.25)]; | |
const Q3 = sortedY[Math.floor(sortedY.length * 0.75)]; | |
const IQR = Q3 - Q1; | |
const lowerBound = Q1 - 1.5 * IQR; | |
const upperBound = Q3 + 1.5 * IQR; | |
// Filter out outliers | |
const filteredData = combinedData.filter(point => point.y >= lowerBound && point.y <= upperBound); | |
// Separate x and y data | |
const filteredX = filteredData.map(point => point.x); | |
const filteredY = filteredData.map(point => point.y); | |
return { filteredX, filteredY }; | |
} | |
// Function to format the equation | |
function formatEquation(type, coefficients) { | |
if (type === 'Linear') { | |
return `y = ${coefficients[0].toFixed(2)}x + ${coefficients[1].toFixed(2)}`; | |
} else if (type === 'Exponential') { | |
return `y = ${coefficients[0].toFixed(2)}e^(${coefficients[1].toFixed(2)}x)`; | |
} else if (type === 'Quadratic') { | |
return `y = ${coefficients[0].toFixed(2)}x² + ${coefficients[1].toFixed(2)}x + ${coefficients[2].toFixed(2)}`; | |
} | |
return ''; | |
} | |
// Function to create a chart with best-fit regression | |
function createChart(canvasId, xData, yData, xLabel, yLabel, bestFitId, bestFitAccuracyId, equationId, linearAccuracyId, expAccuracyId, quadAccuracyId) { | |
// Remove outliers | |
const { filteredX, filteredY } = removeOutliers(xData, yData); | |
const chartData = filteredX.map((x, index) => ({ x, y: filteredY[index] })); | |
// Perform regressions | |
const linear = regression.linear(chartData.map(point => [point.x, point.y])); | |
const exp = regression.exponential(chartData.map(point => [point.x, point.y])); | |
const quad = regression.polynomial(chartData.map(point => [point.x, point.y]), { order: 2 }); | |
// Determine the best fit (highest R²) | |
const regressions = [ | |
{ type: 'Linear', r2: linear.r2, points: linear, coefficients: [linear.equation[1], linear.equation[0]] }, | |
{ type: 'Exponential', r2: exp.r2, points: exp, coefficients: [exp.equation[0], exp.equation[1]] }, | |
{ type: 'Quadratic', r2: quad.r2, points: quad, coefficients: [quad.equation[2], quad.equation[1], quad.equation[0]] } | |
]; | |
const bestFit = regressions.reduce((best, current) => (current.r2 > best.r2 ? current : best)); | |
// Generate points for the best-fit regression | |
const bestFitPoints = chartData.map(point => ({ | |
x: point.x, | |
y: bestFit.points.predict(point.x)[1] | |
})); | |
// Render the chart | |
const ctx = document.getElementById(canvasId).getContext('2d'); | |
const chart = new Chart(ctx, { | |
type: 'scatter', | |
data: { | |
datasets: [ | |
{ | |
label: 'Data Points', | |
data: chartData, | |
backgroundColor: 'rgba(75, 192, 192, 0.6)', | |
borderColor: 'rgba(75, 192, 192, 1)', | |
pointRadius: 5 | |
}, | |
{ | |
label: `${bestFit.type} Regression`, | |
data: bestFitPoints, | |
backgroundColor: 'rgba(255, 99, 132, 0)', | |
borderColor: 'rgba(255, 99, 132, 1)', | |
type: 'line', | |
pointRadius: 0 | |
} | |
] | |
}, | |
options: { | |
scales: { | |
x: { | |
type: 'linear', | |
position: 'bottom', | |
title: { | |
display: true, | |
text: xLabel | |
} | |
}, | |
y: { | |
type: 'linear', | |
title: { | |
display: true, | |
text: yLabel | |
} | |
} | |
} | |
} | |
}); | |
// Display best fit, accuracy, and equation | |
document.getElementById(bestFitId).textContent = bestFit.type; | |
document.getElementById(bestFitAccuracyId).textContent = bestFit.r2.toFixed(4); | |
document.getElementById(equationId).textContent = formatEquation(bestFit.type, bestFit.coefficients); | |
// Display accuracy for all models | |
document.getElementById(linearAccuracyId).textContent = linear.r2.toFixed(4); | |
document.getElementById(expAccuracyId).textContent = exp.r2.toFixed(4); | |
document.getElementById(quadAccuracyId).textContent = quad.r2.toFixed(4); | |
} | |
// Create charts | |
createChart('chart1', data.gestation, data.brainSize, 'Gestation Period (Days)', 'Brain Size (grams)', 'bestFit1', 'bestFitAccuracy1', 'equation1', 'linearAccuracy1', 'expAccuracy1', 'quadAccuracy1'); | |
createChart('chart2', data.gestation, data.babySize, 'Gestation Period (Days)', 'Baby Size (kg)', 'bestFit2', 'bestFitAccuracy2', 'equation2', 'linearAccuracy2', 'expAccuracy2', 'quadAccuracy2'); | |
createChart('chart3', data.gestation, data.babyVolume, 'Gestation Period (Days)', 'Baby Volume (liters)', 'bestFit3', 'bestFitAccuracy3', 'equation3', 'linearAccuracy3', 'expAccuracy3', 'quadAccuracy3'); | |
createChart('chart4', data.gestation, data.brainSize.map((brain, i) => brain / data.babySize[i]), 'Gestation Period (Days)', 'Brain-to-Baby Size Ratio', 'bestFit4', 'bestFitAccuracy4', 'equation4', 'linearAccuracy4', 'expAccuracy4', 'quadAccuracy4'); | |
</script> | |
</body> | |
</html> |