function scale( arr, a, b ) {
	const minimum = min( arr );
	const maximum = max( arr );
	const range = maximum - minimum;
	const out = new Array( arr.length );
	for ( let i = 0; i < out.length; i++ ) {
		out[ i ] = ( ( b - a ) * ( arr[ i ] - minimum ) / range ) + a;
	}
	return out;
}
Beispiel #2
0
function getBins( data ) {
	var h = 2 * iqr( data ) * pow( data.length, -1/3 );
	var bmax = max( data );
	var bmin = min( data );
	var nBins = round( ( bmax - bmin ) / h ) + 1;
	var out = new Array( nBins );
	inmap( out, x => {
		return { 'y': 0, 'y0': 0 };
	});
	for ( let i = 0; i < data.length; i++ ) {
		let idx = bidx( bmin, h, data[ i ]);
		out[ idx ][ 'y' ] += 1;
	}
	for ( let i = 0; i < nBins; i++ ) {
		let bc = bmin + ( h*i );
		out[ i ][ 'x' ] = bc;
	}
	return out;
}
export function generateScatterplotConfig({ data, xval, yval, text, color, type, size, regressionLine, regressionMethod, lineBy, smoothSpan }) {
	let nColors;
	let traces;

	let mode = 'markers';
	if ( text ) {
		mode += '+text';
	}
	if ( color && type ) {
		const colors = data[ color ];
		const types = data[ type ];
		const uniqueColors = colors.slice();
		unique( uniqueColors );
		nColors = uniqueColors.length;
		const uniqueTypes = types.slice();
		unique( uniqueTypes );

		traces = [];
		const xgrouped = groupBy( data[ xval ], ( v, i ) => {
			return colors[ i ] + ':' + types[ i ];
		});
		const ygrouped = groupBy( data[ yval ], ( v, i ) => {
			return colors[ i ] + ':' + types[ i ];
		});
		let texts;
		if ( text ) {
			texts = groupBy( data[ text ], ( v, i ) => {
				return colors[ i ] + ':' + types[ i ];
			});
		}
		let sizegrouped;
		if ( size ) {
			sizegrouped = groupBy( data[ size ], ( v, i ) => {
				return colors[ i ] + ':' + types[ i ];
			});
			sizegrouped = mapValues( sizegrouped, ( value ) => {
				return scale( value, 5.0, 10.0 );
			});
		}
		for ( let i = 0; i < uniqueColors.length; i++ ) {
			for ( let j = 0; j < uniqueTypes.length; j++ ) {
				const grouping = uniqueColors[ i ] + ':' + uniqueTypes[ j ];
				const trace = {
					x: xgrouped[ grouping ],
					y: ygrouped[ grouping ],
					type: 'scatter',
					mode: mode,
					name: grouping,
					marker: {
						symbol: SYMBOLS[ j ],
						size: size ? sizegrouped[ grouping ] : 5.0,
						autocolorscale: false,
						color: CAT20[ i ]
					}
				};
				if ( text ) {
					trace.text = texts[ grouping ];
					trace.textposition = 'bottom';
				}
				traces.push( trace );
			}
		}
	}
	else if ( type ) {
		const groups = data[ type ].slice();
		unique( groups );
		const xgrouped = group( data[ xval ], data[ type ]);
		const ygrouped = group( data[ yval ], data[ type ]);
		let texts;
		if ( text ) {
			texts = group( data[ text ], data[ type ]);
		}
		traces = new Array( groups.length );
		for ( let i = 0; i < groups.length; i++ ) {
			traces[ i ] = {
				x: xgrouped[ groups[ i ] ],
				y: ygrouped[ groups[ i ] ],
				type: 'scatter',
				mode: mode,
				name: groups[ i ],
				marker: {
					symbol: SYMBOLS[ i ],
					size: size ? scale( group( data[ size ], data[ type ])[ groups[ i ] ], 5.0, 10.0 ) : 5.0,
					autocolorscale: false,
					color: 'rgba(0,0,0,1)'
				}
			};
			if ( text ) {
				traces[ i ].text = texts[ groups[ i ] ];
				traces[ i ].textposition = 'bottom';
			}
		}
	}
	else if ( color ) {
		const groups = data[ color ].slice();
		unique( groups );
		nColors = groups.length;
		const xgrouped = group( data[ xval ], data[ color ]);
		const ygrouped = group( data[ yval ], data[ color ]);
		let texts;
		if ( text ) {
			texts = group( data[ text ], data[ color ]);
		}
		traces = new Array( nColors );
		for ( let i = 0; i < nColors; i++ ) {
			traces[ i ] = {
				x: xgrouped[ groups[ i ] ],
				y: ygrouped[ groups[ i ] ],
				type: 'scatter',
				mode: mode,
				name: groups[ i ],
				marker: {
					symbol: 'circle',
					size: size ? scale( group( data[ size ], data[ color ])[ groups[ i ] ], 5.0, 10.0 ) : 5.0,
					autocolorscale: false,
					color: CAT20[ i ]
				}
			};
			if ( text ) {
				traces[ i ].text = texts[ groups[ i ] ];
				traces[ i ].textposition = 'bottom';
			}
		}
	} else {
		traces = [ {
			x: data[ xval ],
			y: data[ yval ],
			type: 'scatter',
			mode: mode,
			name: 'Points',
			marker: {
				symbol: 'circle',
				size: size ? scale( data[ size ], 5.0, 10.0 ) : 5.0
			}
		} ];
		if ( text ) {
			traces[ 0 ].text = data[ text ];
			traces[ 0 ].textposition = 'bottom';
		}
	}

	if ( regressionLine ) {
		if ( lineBy ) {
			const groups = data[ lineBy ].slice();
			unique( groups );
			const xgrouped = group( data[ xval ], data[ lineBy ]);
			const ygrouped = group( data[ yval ], data[ lineBy ]);
			let colorOffset = 0;
			if ( color && color !== lineBy ) {
				colorOffset += nColors;
			}
			for ( let i = 0; i < groups.length; i++ ) {
				let xvals = xgrouped[ groups[ i ] ];
				let yvals = ygrouped[ groups[ i ] ];
				let xc = [];
				let yc = [];
				for ( let j = 0; j < xvals.length; j++ ) {
					let x = xvals[ j ];
					let y = yvals[ j ];
					if ( isNumber( x ) && isNumber( y ) ) {
						xc.push( x );
						yc.push( y );
					}
				}
				xvals = xc;
				yvals = yc;
				let predictedLinear;
				let predictedSmooth;
				let values;
				if ( contains( regressionMethod, 'linear' ) ) {
					values = linspace( min( xvals ), max( xvals ), 100 );
					const coefs = calculateCoefficients( xvals, yvals );
					predictedLinear = values.map( x => coefs[ 0 ] + coefs[ 1 ]*x );
					traces.push({
						x: values,
						y: predictedLinear,
						mode: 'lines',
						name: groups[ i ],
						type: 'line',
						line: {
							color: CAT20[ colorOffset+i ],
							width: 1.5
						}
					});
				}
				if ( contains( regressionMethod, 'smooth' ) ) {
					const out = lowess( xvals, yvals, { 'f': smoothSpan } );
					values = out.x;
					predictedSmooth = out.y;
					traces.push({
						x: values,
						y: predictedSmooth,
						mode: 'lines',
						name: groups[ i ],
						type: 'line',
						line: {
							color: CAT20[ colorOffset+i ],
							width: 1.5
						}
					});
				}
			}
		} else {
			let xvals = data[ xval ];
			let yvals = data[ yval ];
			let xc = [];
			let yc = [];
			for ( let j = 0; j < xvals.length; j++ ) {
				let x = xvals[ j ];
				let y = yvals[ j ];
				if ( isNumber( x ) && isNumber( y ) ) {
					xc.push( x );
					yc.push( y );
				}
			}
			xvals = xc;
			yvals = yc;
			let predictedLinear;
			let predictedSmooth;
			let values;
			if ( contains( regressionMethod, 'linear' ) ) {
				values = linspace( min( xvals ), max( xvals ), 100 );
				const coefs = calculateCoefficients( xvals, yvals );
				predictedLinear = values.map( x => coefs[ 0 ] + coefs[ 1 ]*x );
				traces.push({
					x: values,
					y: predictedLinear,
					text: `${roundn( coefs[ 0 ], -6 )} + x * ${roundn( coefs[ 1 ], -6 )}`,
					mode: 'lines',
					name: 'Linear Fit',
					type: 'line'
				});
			}
			if ( contains( regressionMethod, 'smooth' ) ) {
				const out = lowess( xvals, yvals, { 'f': smoothSpan } );
				values = out.x;
				predictedSmooth = out.y;
				traces.push({
					x: values,
					y: predictedSmooth,
					mode: 'lines',
					name: 'Smoothed Fit',
					type: 'line'
				});
			}
		}
	}
	return {
		data: traces,
		layout: {
			hovermode: 'closest',
			xaxis: {
				title: xval
			},
			yaxis: {
				title: yval
			},
			legend: {
				traceorder: 'normal',
				font: {
					family: 'sans-serif',
					size: 10,
					color: '#000'
				},
				bordercolor: '#E2E2E2',
				borderwidth: 2
			},
			title: `${xval} against ${yval}`
		}
	};
}
Beispiel #4
0
	generateSamples = ( times ) => {
		const histogram = this.state.histogram.slice();
		const enlarged = this.state.enlarged.slice();
		const xbars = this.state.xbars.slice();
		for ( let j = 0; j < times; j++ ) {
			let vals;
			switch ( this.state.activeDistribution ) {
			default:
			case 1:
				vals = drawUniform( this.state.n, this.state.a, this.state.b );
				break;
			case 2:
				vals = drawExponential( this.state.n, this.state.lambda );
				break;
			case 3:
				vals = drawNormal( this.state.n, this.state.mu, this.state.sigma );
				break;
			}
			const xbar = mean( vals );
			const plot = <div style={{ cursor: 'zoom-in' }}>
				<TeX raw={`\\bar x = ${xbar.toFixed( 2 )}`} />
				<VictoryChart domainPadding={20} padding={60} >
					<VictoryAxis style={{
						axisLabel: {
							fontSize: 22
						},
						tickLabels: {
							fontSize: 15, padding: 5
						}
					}} />
					<VictoryAxis dependentAxis style={{
						axisLabel: {
							fontSize: 22
						},
						tickLabels: {
							fontSize: 15, padding: 5
						}
					}} />
					<VictoryArea
						data={getBins( vals )}
						interpolation="step"
					/>
				</VictoryChart>
			</div>;
			histogram.push( plot );
			enlarged.push( false );
			xbars.push( xbar );
		}
		const layout = histogram.map( ( x, i ) => {
			return {
				i: String( i ),
				x: i*4 % 12,
				y: floor( i / 3 ) * 3,
				w: 4,
				h: 3,
				static: true
			};
		});

		const avgXBars = mean( xbars );
		const stdevXBars = stdev( xbars );
		const densityX = linspace( min( xbars ), max( xbars ), 512 );
		const densityY = densityX.map( x => dnorm( x, avgXBars, stdevXBars ) );

		this.setState({
			histogram,
			layout,
			xbars,
			enlarged,
			avgXBars,
			stdevXBars,
			densityX,
			densityY
		});
	}