import React, { useState } from 'react'; const DataModifierWidget: React.FC = () => { const initialData = [10, 12, 13, 15, 16, 18, 20]; const [data, setData] = useState(initialData); const calculateStats = (arr: number[]) => { const sorted = [...arr].sort((a, b) => a - b); const sum = sorted.reduce((a, b) => a + b, 0); const mean = sum / sorted.length; const min = sorted[0]; const max = sorted[sorted.length - 1]; const range = max - min; // Median const mid = Math.floor(sorted.length / 2); const median = sorted.length % 2 !== 0 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2; // SD (Population) const variance = sorted.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0) / sorted.length; const sd = Math.sqrt(variance); return { mean, median, range, sd, sorted }; }; const stats = calculateStats(data); // Operations const reset = () => setData(initialData); const addConstant = (k: number) => { setData(prev => prev.map(n => n + k)); }; const multiplyConstant = (k: number) => { setData(prev => prev.map(n => n * k)); }; const addOutlier = (val: number) => { setData(prev => [...prev, val]); }; // Visual scaling const minDisplay = Math.min(0, ...data) - 5; const maxDisplay = Math.max(Math.max(...data), 100) + 10; const getX = (val: number) => ((val - minDisplay) / (maxDisplay - minDisplay)) * 100; return (
{/* Controls */}

Apply Transformation

{/* Visualization */}
{/* Stats Panel */}
Mean
{stats.mean.toFixed(1)}
Median
{stats.median.toFixed(1)}
Range
{stats.range.toFixed(0)}
SD
{stats.sd.toFixed(1)}
{/* Dot Plot */}
{stats.sorted.map((val, idx) => (
))} {/* Mean Marker */}
{/* Median Marker */}
M
{data.length > 7 ? ( Notice how the Mean is pulled towards the outlier, while the Median barely moves! ) : ( "Experiment with adding constants and multipliers to see which stats change." )}
); }; export default DataModifierWidget;