Как определить обработку пропущенных значений в d c. js? - PullRequest
1 голос
/ 17 января 2020

Я новичок в d c. js, и мне удалось создать несколько гистограмм и ряд рядов линий.

Если я нажму на свой гистограмму, чтобы отфильтровать значения моего возраста,

Несуществующие значения, по-видимому, обрабатываются как нулевые значения вместо NaN или ноль. Если бы я выбрал первое и последнее значение, но не среднее значение, я ожидал бы две точки и одну прямую, соединяющую их.

=> Как я могу указать d c. js на не показывать значения, не прошедшие фильтр?

Я пытался адаптировать средство доступа к значениям из

.valueAccessor(d => d.value)

до

.valueAccessor(d => d.value>0?d.value:null)

или

.valueAccessor(d => d.value>0?d.value:NaN)

но это не помогло. Отсутствующее значение все еще возвращается к нулю.

Я думаю, что мне нужно как-то применить функцию d3. js defined для моих линейных графиков, но не знаю как: Как сделать Я получаю d3, чтобы обрабатывать пропущенные значения как ноль вместо нуля?

Пример кода (Пожалуйста, используйте опцию «Полная страница» после запуска фрагмента. В противном случае вы можете увидеть только некоторые предупреждения):

<html>

	<head>

		<title>dc demo</title>

		<meta http-equiv='content-type' content='text/html; charset=UTF8'>

		<!-- this demo is based on following tuturials:
		   https://www.tutorialspoint.com/dcjs/dcjs_introduction_to_d3js.htm 
		   https://www.codeproject.com/articles/693841/making-dashboards-with-dc-js-part-1-using-crossfil		
	    -->

		 <script src='https://d3js.org/d3.v4.min.js'></script>
		 <script src='https://cdnjs.cloudflare.com/ajax/libs/crossfilter2/1.5.2/crossfilter.min.js'></script>
		 <script src='https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.min.js'></script>
		

	</head>
	
	<body>
	    
	    <div style="font-family:arial;">

			 <div style="float:left;padding:20px;">
				<div >
					<label>Number of colors:</label>
					<div id='color-chart-count'></div>
				</div>

				<div>
					<label>Value sum for colors:</label>
					<div id='color-chart-value-sum'></div>
				</div>

			</div>



			<div style="float:center;padding:20px;">
				<div>
					<label>Number of ages:</label>
					<div id='age-chart-count'></div>
				</div>

				<div>
					<label>Value sum for ages:</label>
					<div id='age-chart-value-sum'></div>
				</div>

			</div>

	    </div>
	    
	    
        <div style="font-family:arial;">
            <label for='value-chart'>Values:</label>
	        <div id='value-chart'></div>
        </div>
	    
	
		<script>
			
			let data = [			              

						  {color: 'red', age: 1, value: 10},
						  {color: 'red', age: 2, value: 11},
						  {color: 'red', age: 3, value: 12},						  

						  {color: 'green', age: 1, value: 20},
						  {color: 'green', age: 2, value: 21},
						  {color: 'green', age: 3, value: 22},

						  {color: 'blue', age: 1, value: 30},
						  {color: 'blue', age: 2, value: 31},
						  {color: 'blue', age: 3, value: 32},
						];

            //create instance of cross filter
			let cf = crossfilter(data);			 

            //define dimensions and groups
            let colorDim = cf.dimension(d=> d.color);
            let colorGroupCount = colorDim.group().reduceCount();
            let colorGroupValueSum = colorDim.group().reduceSum(d => d.value);

            let ageDim = cf.dimension(d=> d.age);
            let ageGroupCount = ageDim.group().reduceCount();
            let ageGroupValueSum = ageDim.group().reduceSum(d => d.value);

            let colorAgeDim = cf.dimension(d => [d.color, d.age]);              
            let colorAgeGroup = colorAgeDim.group().reduceSum( d => d.value);

            let ordinalColors =  ['red','green','blue'];    
            let ordinalAgeColors =  ['lightgray','grey','#666666'];                    

            //color charts

            let rgbColorScale = d3.scaleOrdinal().domain(ordinalColors).range(ordinalColors);

            let colorChartCount = barChart('#color-chart-count')               
				.xAxisLabel('Color')  				   				
				.x(d3.scaleBand().domain(ordinalColors))		
				.dimension(colorDim)		
				.yAxisLabel('Count')					
				.group(colorGroupCount)			
				.defineColors(rgbColorScale);				

			colorChartCount.yAxis().ticks(4);		
				

			barChart('#color-chart-value-sum')               
				.xAxisLabel('Color')  				         				
				.x(d3.scaleBand().domain(ordinalColors))		
				.dimension(colorDim)		
				.yAxisLabel('Value sum')				
				.group(colorGroupValueSum)
				.defineColors(rgbColorScale);				

            //age charts

            let ageColorScale = d3.scaleOrdinal().domain([1,2,3]).range(ordinalAgeColors);

            /*
            dc.pieChart('#age-chart-count')
                .width(100)
				.height(100)
				.ordinalColors(ordinalAgeColors)
				.dimension(ageDim)
				.group(ageGroupCount);
			*/

			let ageChartCount = barChart('#age-chart-count')              
				.xAxisLabel('Age') 				           				
				.x(d3.scaleLinear().domain([1,2,3]))		
				.dimension(ageDim)		
				.yAxisLabel('Count')				
				.group(ageGroupCount)			
				.defineColors(ageColorScale);

			ageChartCount.yAxis().ticks(4);	

			barChart('#age-chart-value-sum')               
				.xAxisLabel('Age')  				   				
				.x(d3.scaleLinear().domain([1,2,3]))	
				.dimension(colorDim)		
				.yAxisLabel('Value sum')				
				.group(ageGroupValueSum)
				.defineColors(ageColorScale);

			function barChart(elementSelector){

				let barChart = dc.barChart(elementSelector)
					.width(200)
					.height(200)				
					.xUnits(dc.units.ordinal)  			
					.margins({top:10,left:30,right:15,bottom:35})	
					.barPadding(0.1)
					.outerPadding(0.1);

					barChart.defineColors = function(colorScale){
						
						this.renderlet(chart=>{
						    chart.selectAll('rect.bar')
							     .each(function(d){
								    d3.select(this).attr('style', 'fill: ' + colorScale(d.x));
							     });
							 	
					    });
					    return this;
					}

					return barChart;
			}	

             
             //value chart
             let chart = dc.seriesChart('#value-chart');

			 chart
				.width(500)
				.height(500)
				.chart( c => 
				       dc.lineChart(c)
				       .renderDataPoints(true)					       
				       	
				)				
				.xAxisLabel('Age')
				.x(d3.scaleLinear().domain([1,3]))
				.dimension(colorAgeDim)				
				.yAxisLabel('Value')
				.elasticY(true)
				.group(colorAgeGroup)					
				.brushOn(false)	
				.clipPadding(10)
				.mouseZoomable(true)
				.seriesAccessor(d => d.key[0])
				.keyAccessor(d => d.key[1])
				.valueAccessor(d => d.value)
				.ordinalColors(['blue','green','red','yellow'])
				.legend(dc.legend().x(430).y(350)); 
			
            
            dc.renderAll();

            //dimensions can also be used for filtering:
            
            //let color_red = colorDim.filter('red');           
            //let filterResult = JSON.stringify(color_red.top(Infinity)).replace('[','[\n\t').replace(/}\,/g,'},\n\t').replace(']','\n]');
            //console.log(filterResult);

            //let functionFilter = ageDim.filter(age => age === 2);  
            //let functionFilterResult = JSON.stringify(functionFilter.top(Infinity)).replace('[','[\n\t').replace(/}\,/g,'},\n\t').replace(']','\n]');
            //console.log(functionFilterResult);


		</script>
	
	
	</body>

</html>

Диаграмма серии линий, если выбран только один возраст , показывающая нежелательные черные области, линии и точки на горизонтальной оси :

enter image description here

1 Ответ

1 голос
/ 17 января 2020

Комментарии Гордона указали мне в правильном направлении. Ниже представлены две измененные версии.

  • Я включил таблицу стилей dc.css для решения проблемы черной области.

  • Вместо group().reduceSum() я использовал пользовательскую операцию уменьшения для Подумайте о пропущенных значениях как ноль вместо 0. Теперь мой метод доступа к значениям правильно возвращает ноль для пропущенных значений.

        function reduceAdd(previous, current) {
    
            if(current){
                if(current.value !== null){
                    if(previous.sum === null){
                        previous.sum = current.value;
                        previous.count = 1;
                    } else {
                        previous.sum += current.value;
                        previous.count += 1;
    
                    }
                } 
            } 
            return previous;                                                
        }
    
        function reduceRemove(previous, current) {                  
            if(current){
                if(current.value !== null){
                    if(previous.sum !== null){
                        previous.sum -= current.value;
                        previous.count -= 1;
                        if(previous.count === 0){
                            previous.sum = null;
                        }
                    } 
                } 
            } 
            return previous;                
        }
    
        function reduceInit() {
                return { 
                        sum: null,
                        count: 0
                       };
        }
    
        let colorAgeGroup = colorAgeDim.group().reduce(reduceAdd, reduceRemove, reduceInit);
    

A. В первом примере применяется метод defined для фильтрации нулевых значений в линейных диаграммах. Пропущенные значения отображаются в виде пробелов:

<html>

	<head>

		<title>dc demo</title>

		<meta http-equiv='content-type' content='text/html; charset=UTF8'>

		<!-- this demo is based on following tuturials:
		   https://www.tutorialspoint.com/dcjs/dcjs_introduction_to_d3js.htm 
		   https://www.codeproject.com/articles/693841/making-dashboards-with-dc-js-part-1-using-crossfil		
	    -->

	     



		 <script src='https://d3js.org/d3.v4.min.js'></script>
		 <script src='https://cdnjs.cloudflare.com/ajax/libs/crossfilter2/1.5.2/crossfilter.min.js'></script>
		 <script src='https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.min.js'></script>
		 <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.css" />

	</head>
	
	<body>
	    
	    <div style="font-family:arial;">

			 <div style="float:left;padding:20px;">
				<div >
					<label>Number of colors:</label>
					<div id='color-chart-count'></div>
				</div>

				<div>
					<label>Value sum for colors:</label>
					<div id='color-chart-value-sum'></div>
				</div>

			</div>



			<div style="float:center;padding:20px;">
				<div>
					<label>Number of ages:</label>
					<div id='age-chart-count'></div>
				</div>

				<div>
					<label>Value sum for ages:</label>
					<div id='age-chart-value-sum'></div>
				</div>

			</div>

	    </div>
	    
	    
        <div style="font-family:arial;">
            <label for='value-chart'>Values:</label>
	        <div id='value-chart'></div>
        </div>
	    
	
		<script>
			
			let data = [			              

						  {color: 'red', age: 1, value: 10},
						  {color: 'red', age: 2, value: 11},
						  {color: 'red', age: 3, value: 12},						  

						  {color: 'green', age: 1, value: 20},
						  {color: 'green', age: 2, value: 21},
						  {color: 'green', age: 3, value: 22},

						  {color: 'blue', age: 1, value: 30},
						  {color: 'blue', age: 2, value: 31},
						  {color: 'blue', age: 3, value: 32},
						];

            //create instance of cross filter
			let cf = crossfilter(data);			 

            //define dimensions and groups
            let colorDim = cf.dimension(d=> d.color);
            let colorGroupCount = colorDim.group().reduceCount();
            let colorGroupValueSum = colorDim.group().reduceSum(d => d.value);

            let ageDim = cf.dimension(d=> d.age);
            let ageGroupCount = ageDim.group().reduceCount();
            let ageGroupValueSum = ageDim.group().reduceSum(d => d.value);

            let colorAgeDim = cf.dimension(d => [d.color, d.age]);


            function reduceAdd(previous, current) {

            	if(current){
            		if(current.value !== null){
            			if(previous.sum === null){
            				previous.sum = current.value;
            				previous.count = 1;
            			} else {
            				previous.sum += current.value;
            				previous.count += 1;

            			}
            		} 
            	} 
            	return previous;            									
			}

			function reduceRemove(previous, current) {					
				if(current){
            		if(current.value !== null){
            			if(previous.sum !== null){
            				previous.sum -= current.value;
            				previous.count -= 1;
            				if(previous.count === 0){
            					previous.sum = null;
            				}
            			} 
            		} 
            	} 
            	return previous; 				
			}

			function reduceInit() {
					return { 
					        sum: null,
					        count: 0
					       };
			}
				              
            let colorAgeGroup = colorAgeDim.group().reduce(reduceAdd, reduceRemove, reduceInit);

            let ordinalColors =  ['red','green','blue'];    
            let ordinalAgeColors =  ['lightgray','grey','#666666'];                    

            //color charts

            let rgbColorScale = d3.scaleOrdinal().domain(ordinalColors).range(ordinalColors);

            let colorChartCount = barChart('#color-chart-count')               
				.xAxisLabel('Color')  				   				
				.x(d3.scaleBand().domain(ordinalColors))		
				.dimension(colorDim)		
				.yAxisLabel('Count')					
				.group(colorGroupCount)							
				.defineColors(rgbColorScale);				

			colorChartCount.yAxis().ticks(4);		
				

			barChart('#color-chart-value-sum')               
				.xAxisLabel('Color')  				         				
				.x(d3.scaleBand().domain(ordinalColors))		
				.dimension(colorDim)		
				.yAxisLabel('Value sum')				
				.group(colorGroupValueSum)
				.defineColors(rgbColorScale);				

            //age charts

            let ageColorScale = d3.scaleOrdinal().domain([1,2,3]).range(ordinalAgeColors);

            /*
            dc.pieChart('#age-chart-count')
                .width(100)
				.height(100)
				.ordinalColors(ordinalAgeColors)
				.dimension(ageDim)
				.group(ageGroupCount);
			*/

			let ageChartCount = barChart('#age-chart-count')              
				.xAxisLabel('Age') 				           				
				.x(d3.scaleLinear().domain([1,2,3]))		
				.dimension(ageDim)		
				.yAxisLabel('Count')				
				.group(ageGroupCount)			
				.defineColors(ageColorScale);

			ageChartCount.yAxis().ticks(4);	

			barChart('#age-chart-value-sum')               
				.xAxisLabel('Age')  				   				
				.x(d3.scaleLinear().domain([1,2,3]))	
				.dimension(colorDim)		
				.yAxisLabel('Value sum')				
				.group(ageGroupValueSum)
				.defineColors(ageColorScale);

			function barChart(elementSelector){

				let barChart = dc.barChart(elementSelector)
					.width(200)
					.height(200)				
					.xUnits(dc.units.ordinal)  			
					.margins({top:10,left:30,right:15,bottom:35})	
					.barPadding(0.1)
					.outerPadding(0.1)					
					.transitionDuration(500);

					barChart.defineColors = function(colorScale){
						
						this.renderlet(chart=>{
						    chart.selectAll('rect.bar')
							     .each(function(d){

                                    let isSelected = this.classList.contains('selected');
                                    if(isSelected){
                                        d3.select(this).attr('style', 'fill: ' + colorScale(d.x) + ';stroke-width:2;stroke:#39ff14');
                                       
                                    } else {
                                    	d3.select(this).attr('style', 'fill: ' + colorScale(d.x));
                                    }

								    
							     });
							 	
					    });
					    return this;
					}

					return barChart;
			}	

             
             //value chart
             let chart = dc.seriesChart('#value-chart');

			 chart
				.width(500)
				.height(500)
				.chart( c => 
				       dc.lineChart(c)
				       .renderDataPoints(true)
				       .defined(d=>{
				       	    if(d.y !== null){
				       	    	return d.y;
				       	    };
				       })      				       
				       	
				)				
				.xAxisLabel('Age')
				.x(d3.scaleLinear().domain([1,3]))
				.dimension(colorAgeDim)				
				.yAxisLabel('Value')
				.elasticY(true)
				.group(colorAgeGroup)					
				.brushOn(false)	
				.clipPadding(10)
				.mouseZoomable(true)
				.seriesAccessor(d => d.key[0])
				.keyAccessor(d => d.key[1])
				.valueAccessor(d => {
					return d.value.sum;
				})
				.ordinalColors(['blue','green','red','yellow'])
				.legend(dc.legend().x(430).y(350)); 
			
            
            dc.renderAll();

            //dimensions can also be used for filtering:
            
            //let color_red = colorDim.filter('red');           
            //let filterResult = JSON.stringify(color_red.top(Infinity)).replace('[','[\n\t').replace(/}\,/g,'},\n\t').replace(']','\n]');
            //console.log(filterResult);

            //let functionFilter = ageDim.filter(age => age === 2);  
            //let functionFilterResult = JSON.stringify(functionFilter.top(Infinity)).replace('[','[\n\t').replace(/}\,/g,'},\n\t').replace(']','\n]');
            //console.log(functionFilterResult);


		</script>
	
	
	</body>

</html>

B. Во втором примере используется фильтр для удаления нулевых значений из группы. Пропущенные значения пропускаются, а соседние точки соединяются.

<html>

	<head>

		<title>dc demo</title>

		<meta http-equiv='content-type' content='text/html; charset=UTF8'>

		<!-- this demo is based on following tuturials:
		   https://www.tutorialspoint.com/dcjs/dcjs_introduction_to_d3js.htm 
		   https://www.codeproject.com/articles/693841/making-dashboards-with-dc-js-part-1-using-crossfil		
	    -->

	     



		 <script src='https://d3js.org/d3.v4.min.js'></script>
		 <script src='https://cdnjs.cloudflare.com/ajax/libs/crossfilter2/1.5.2/crossfilter.min.js'></script>
		 <script src='https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.min.js'></script>
		 <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.css" />

	</head>
	
	<body>
	    
	    <div style="font-family:arial;">

			 <div style="float:left;padding:20px;">
				<div >
					<label>Number of colors:</label>
					<div id='color-chart-count'></div>
				</div>

				<div>
					<label>Value sum for colors:</label>
					<div id='color-chart-value-sum'></div>
				</div>

			</div>



			<div style="float:center;padding:20px;">
				<div>
					<label>Number of ages:</label>
					<div id='age-chart-count'></div>
				</div>

				<div>
					<label>Value sum for ages:</label>
					<div id='age-chart-value-sum'></div>
				</div>

			</div>

	    </div>
	    
	    
        <div style="font-family:arial;">
            <label for='value-chart'>Values:</label>
	        <div id='value-chart'></div>
        </div>
	    
	
		<script>
			
			let data = [			              

						  {color: 'red', age: 1, value: 10},
						  {color: 'red', age: 2, value: 11},
						  {color: 'red', age: 3, value: 12},						  

						  {color: 'green', age: 1, value: 20},
						  {color: 'green', age: 2, value: 21},
						  {color: 'green', age: 3, value: 22},

						  {color: 'blue', age: 1, value: 30},
						  {color: 'blue', age: 2, value: 31},
						  {color: 'blue', age: 3, value: 32},
						];

            //create instance of cross filter
			let cf = crossfilter(data);			 

            //define dimensions and groups
            let colorDim = cf.dimension(d=> d.color);
            let colorGroupCount = colorDim.group().reduceCount();
            let colorGroupValueSum = colorDim.group().reduceSum(d => d.value);

            let ageDim = cf.dimension(d=> d.age);
            let ageGroupCount = ageDim.group().reduceCount();
            let ageGroupValueSum = ageDim.group().reduceSum(d => d.value);

            let colorAgeDim = cf.dimension(d => [d.color, d.age]);


            function reduceAdd(previous, current) {

            	if(current){
            		if(current.value !== null){
            			if(previous.sum === null){
            				previous.sum = current.value;
            				previous.count = 1;
            			} else {
            				previous.sum += current.value;
            				previous.count += 1;

            			}
            		} 
            	} 
            	return previous;            									
			}

			function reduceRemove(previous, current) {					
				if(current){
            		if(current.value !== null){
            			if(previous.sum !== null){
            				previous.sum -= current.value;
            				previous.count -= 1;
            				if(previous.count === 0){
            					previous.sum = null;
            				}
            			} 
            		} 
            	} 
            	return previous; 				
			}

			function reduceInit() {
					return { 
					        sum: null,
					        count: 0
					       };
			}
				              
            let colorAgeGroup = colorAgeDim.group().reduce(reduceAdd, reduceRemove, reduceInit);

            let filteredColorAgeGroup = removeMissingEntries(colorAgeGroup);

            function removeMissingEntries(sourceGroup) {
				return {
					all:function () {
						return sourceGroup.all().filter(function(d) {							
							return d.value.sum !== null; 
						});
					}
				};
			}

            let ordinalColors =  ['red','green','blue'];    
            let ordinalAgeColors =  ['lightgray','grey','#666666'];                    

            //color charts

            let rgbColorScale = d3.scaleOrdinal().domain(ordinalColors).range(ordinalColors);

            let colorChartCount = barChart('#color-chart-count')               
				.xAxisLabel('Color')  				   				
				.x(d3.scaleBand().domain(ordinalColors))		
				.dimension(colorDim)		
				.yAxisLabel('Count')					
				.group(colorGroupCount)							
				.defineColors(rgbColorScale);				

			colorChartCount.yAxis().ticks(4);		
				

			barChart('#color-chart-value-sum')               
				.xAxisLabel('Color')  				         				
				.x(d3.scaleBand().domain(ordinalColors))		
				.dimension(colorDim)		
				.yAxisLabel('Value sum')				
				.group(colorGroupValueSum)
				.defineColors(rgbColorScale);				

            //age charts

            let ageColorScale = d3.scaleOrdinal().domain([1,2,3]).range(ordinalAgeColors);

            /*
            dc.pieChart('#age-chart-count')
                .width(100)
				.height(100)
				.ordinalColors(ordinalAgeColors)
				.dimension(ageDim)
				.group(ageGroupCount);
			*/

			let ageChartCount = barChart('#age-chart-count')              
				.xAxisLabel('Age') 				           				
				.x(d3.scaleLinear().domain([1,2,3]))		
				.dimension(ageDim)		
				.yAxisLabel('Count')				
				.group(ageGroupCount)			
				.defineColors(ageColorScale);

			ageChartCount.yAxis().ticks(4);	

			barChart('#age-chart-value-sum')               
				.xAxisLabel('Age')  				   				
				.x(d3.scaleLinear().domain([1,2,3]))	
				.dimension(colorDim)		
				.yAxisLabel('Value sum')				
				.group(ageGroupValueSum)
				.defineColors(ageColorScale);

			function barChart(elementSelector){

				let barChart = dc.barChart(elementSelector)
					.width(200)
					.height(200)				
					.xUnits(dc.units.ordinal)  			
					.margins({top:10,left:30,right:15,bottom:35})	
					.barPadding(0.1)
					.outerPadding(0.1)					
					.transitionDuration(500);

					barChart.defineColors = function(colorScale){
						
						this.renderlet(chart=>{
						    chart.selectAll('rect.bar')
							     .each(function(d){

                                    let isSelected = this.classList.contains('selected');
                                    if(isSelected){
                                        d3.select(this).attr('style', 'fill: ' + colorScale(d.x) + ';stroke-width:2;stroke:#39ff14');
                                       
                                    } else {
                                    	d3.select(this).attr('style', 'fill: ' + colorScale(d.x));
                                    }

								    
							     });
							 	
					    });
					    return this;
					}

					return barChart;
			}	

             
             //value chart
             let chart = dc.seriesChart('#value-chart');

			 chart
				.width(500)
				.height(500)
				.chart( c => 
				       dc.lineChart(c)
				       .renderDataPoints(true)
				           				       
				       	
				)				
				.xAxisLabel('Age')
				.x(d3.scaleLinear().domain([1,3]))
				.dimension(colorAgeDim)				
				.yAxisLabel('Value')
				.elasticY(true)
				.group(filteredColorAgeGroup)					
				.brushOn(false)	
				.clipPadding(10)
				.mouseZoomable(true)
				.seriesAccessor(d => d.key[0])
				.keyAccessor(d => d.key[1])
				.valueAccessor(d => {
					return d.value.sum;
				})
				.ordinalColors(['blue','green','red','yellow'])
				.legend(dc.legend().x(430).y(350)); 
			
            
            dc.renderAll();

            //dimensions can also be used for filtering:
            
            //let color_red = colorDim.filter('red');           
            //let filterResult = JSON.stringify(color_red.top(Infinity)).replace('[','[\n\t').replace(/}\,/g,'},\n\t').replace(']','\n]');
            //console.log(filterResult);

            //let functionFilter = ageDim.filter(age => age === 2);  
            //let functionFilterResult = JSON.stringify(functionFilter.top(Infinity)).replace('[','[\n\t').replace(/}\,/g,'},\n\t').replace(']','\n]');
            //console.log(functionFilterResult);


		</script>
	
	
	</body>

</html>
...