Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Madhusuthanan-B/38f3306118c2f751ccf4e0b3e977e8a3 to your computer and use it in GitHub Desktop.
Save Madhusuthanan-B/38f3306118c2f751ccf4e0b3e977e8a3 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Skewness Example - SaaS Subscription Analysis</title>
<script src="https://d3js.org/d3.v6.min.js"></script>
<style>
body {
font-family: Arial, sans-serif;
}
.result {
margin: 20px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
width: 300px;
}
.positive-skew {
background-color: #d4edda;
}
.chart {
margin-top: 20px;
}
</style>
</head>
<body>
<div id="results" class="result"></div>
<div id="chart" class="chart"></div>
<script>
const SubscriptionAnalysis = (function() {
function calculateMean(data) {
const sum = data.reduce((acc, obj) => acc + obj.subscription_price, 0);
return sum / data.length;
}
function calculateMedian(data) {
const prices = data.map(obj => obj.subscription_price).sort((a, b) => a - b);
const mid = Math.floor(prices.length / 2);
return prices.length % 2 === 0 ? (prices[mid - 1] + prices[mid]) / 2 : prices[mid];
}
function calculateMode(data) {
const frequency = {};
data.forEach(obj => {
frequency[obj.tier] = (frequency[obj.tier] || 0) + 1;
});
const maxFreq = Math.max(...Object.values(frequency));
return Object.keys(frequency).filter(key => frequency[key] === maxFreq);
}
function calculateStandardDeviation(data) {
const mean = calculateMean(data);
const squaredDiffs = data.map(obj => Math.pow(obj.subscription_price - mean, 2));
const variance = squaredDiffs.reduce((acc, val) => acc + val, 0) / data.length;
return Math.sqrt(variance);
}
function calculateSkewness(data) {
const mean = calculateMean(data);
const median = calculateMedian(data);
const stdDev = calculateStandardDeviation(data);
return 3 * (mean - median) / stdDev;
}
function renderResults(data) {
const meanPrice = calculateMean(data);
const medianPrice = calculateMedian(data);
const modeTier = calculateMode(data);
const skewness = calculateSkewness(data);
const resultsDiv = document.getElementById('results');
resultsDiv.innerHTML = `
<p>Mean Subscription Price: $${meanPrice.toFixed(2)}</p>
<p>Median Subscription Price: $${medianPrice.toFixed(2)}</p>
<p>Mode Subscription Tier: ${modeTier.join(", ")}</p>
<p>Skewness: ${skewness.toFixed(2)}</p>
`;
if (skewness > 0) {
resultsDiv.classList.add('positive-skew');
}
}
function renderChart(data) {
const meanPrice = calculateMean(data);
const medianPrice = calculateMedian(data);
const margin = {top: 20, right: 30, bottom: 40, left: 40};
const width = 600 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;
const 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})`);
const x = d3.scaleBand()
.domain(data.map(d => d.customer_id))
.range([0, width])
.padding(0.1);
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.subscription_price)])
.nice()
.range([height, 0]);
svg.append("g")
.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("x", d => x(d.customer_id))
.attr("y", d => y(d.subscription_price))
.attr("width", x.bandwidth())
.attr("height", d => height - y(d.subscription_price))
.attr("fill", "steelblue");
svg.append("g")
.attr("class", "x-axis")
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(x).tickFormat(d => `C${d}`));
svg.append("g")
.attr("class", "y-axis")
.call(d3.axisLeft(y));
svg.append("line")
.attr("x1", 0)
.attr("x2", width)
.attr("y1", y(meanPrice))
.attr("y2", y(meanPrice))
.attr("stroke", "red")
.attr("stroke-dasharray", "4")
.attr("stroke-width", 2)
.attr("opacity", 0.7);
svg.append("text")
.attr("x", width - 60)
.attr("y", y(meanPrice) - 10)
.attr("fill", "red")
.text(`Mean: $${meanPrice.toFixed(2)}`);
svg.append("line")
.attr("x1", 0)
.attr("x2", width)
.attr("y1", y(medianPrice))
.attr("y2", y(medianPrice))
.attr("stroke", "green")
.attr("stroke-dasharray", "4")
.attr("stroke-width", 2)
.attr("opacity", 0.7);
svg.append("text")
.attr("x", width - 60)
.attr("y", y(medianPrice) - 10)
.attr("fill", "green")
.text(`Median: $${medianPrice.toFixed(2)}`);
}
return {
renderResults,
renderChart
};
})();
const subscriptions = [
{customer_id: 1, subscription_price: 30, tier: "Basic"},
{customer_id: 2, subscription_price: 50, tier: "Standard"},
{customer_id: 3, subscription_price: 50, tier: "Standard"},
{customer_id: 4, subscription_price: 80, tier: "Premium"},
{customer_id: 5, subscription_price: 30, tier: "Basic"},
{customer_id: 6, subscription_price: 60, tier: "Standard"},
{customer_id: 7, subscription_price: 90, tier: "Premium"},
{customer_id: 8, subscription_price: 50, tier: "Standard"},
{customer_id: 9, subscription_price: 70, tier: "Premium"},
{customer_id: 10, subscription_price: 40, tier: "Basic"}
];
document.addEventListener('DOMContentLoaded', () => {
SubscriptionAnalysis.renderResults(subscriptions);
SubscriptionAnalysis.renderChart(subscriptions);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment