数据可视化

动态散点图

数据

date,country,confirmed,recovered,death
1/31/20,IND,1,0,0
1/31/20,BRA,0,0,0
1/31/20,FRA,5,0,0
1/31/20,RUS,2,0,0
1/31/20,TUR,0,0,0
1/31/20,ARG,0,0,0
1/31/20,ITA,2,0,0
1/31/20,COL,0,0,0
1/31/20,ESP,0,0,0
1/31/20,GER,5,0,0
2/29/20,IND,3,3,0
2/29/20,BRA,2,0,0
2/29/20,FRA,100,12,2
2/29/20,RUS,2,2,0
2/29/20,TUR,0,0,0
2/29/20,ARG,0,0,0
2/29/20,ITA,1128,46,29
2/29/20,COL,0,0,0
2/29/20,ESP,45,2,0
2/29/20,GER,79,16,0
3/31/20,IND,1397,123,35
3/31/20,BRA,5717,127,201
3/31/20,FRA,51579,9444,3517
3/31/20,RUS,2337,121,17
3/31/20,TUR,13531,243,214
3/31/20,ARG,1054,240,27
3/31/20,ITA,105792,15729,12428
3/31/20,COL,906,31,16
3/31/20,ESP,95923,19259,8464
3/31/20,GER,71808,16100,775
4/30/20,IND,34863,9068,1154
4/30/20,BRA,87187,35935,6006
4/30/20,FRA,167326,48572,24315
4/30/20,RUS,106498,11619,1073
4/30/20,TUR,120204,48886,3174
4/30/20,ARG,4428,1256,218
4/30/20,ITA,205463,75945,27967
4/30/20,COL,6507,1439,293
4/30/20,ESP,213435,112050,24543
4/30/20,GER,163009,123500,6623
5/31/20,IND,190609,91852,5408
5/31/20,BRA,514849,206555,29314
5/31/20,FRA,187817,66123,28751
5/31/20,RUS,405843,171883,4693
5/31/20,TUR,163942,127973,4540
5/31/20,ARG,16851,5336,539
5/31/20,ITA,232997,157507,33415
5/31/20,COL,29383,7032,939
5/31/20,ESP,239479,150376,27127
5/31/20,GER,183410,165352,8540
6/30/20,IND,585481,347912,17400
6/30/20,BRA,1402041,788318,59594
6/30/20,FRA,196554,71714,29763
6/30/20,RUS,646929,411973,9306
6/30/20,TUR,199906,173111,5131
6/30/20,ARG,64530,22028,1307
6/30/20,ITA,240578,190248,34767
6/30/20,COL,97846,40021,3334
6/30/20,ESP,249271,150376,28355
6/30/20,GER,195418,178100,8990
7/31/20,IND,1695988,1094374,36511
7/31/20,BRA,2662485,2008854,92475
7/31/20,FRA,215135,71656,30150
7/31/20,RUS,838461,637217,13939
7/31/20,TUR,230873,214535,5691
7/31/20,ARG,191302,83780,3543
7/31/20,ITA,247537,199974,35141
7/31/20,COL,295508,154387,10105
7/31/20,ESP,288522,150376,28445
7/31/20,GER,210399,191992,9147
8/31/20,IND,3691166,2839882,65288
8/31/20,BRA,3908272,3268591,121381
8/31/20,FRA,304349,73537,30501
8/31/20,RUS,992402,807339,17128
8/31/20,TUR,270133,244926,6370
8/31/20,ARG,417735,301195,8660
8/31/20,ITA,269214,207653,35483
8/31/20,COL,615094,459460,19662
8/31/20,ESP,462858,150376,29094
8/31/20,GER,244802,216795,9303
9/30/20,IND,6312584,5273201,98678
9/30/20,BRA,4810935,4274774,143952
9/30/20,FRA,578769,79128,31761
9/30/20,RUS,1170799,954788,20630
9/30/20,TUR,318663,279749,8195
9/30/20,ARG,751001,594645,16937
9/30/20,ITA,314861,227704,35894
9/30/20,COL,829679,743653,25998
9/30/20,ESP,769188,150376,31791
9/30/20,GER,292913,256861,9495
10/31/20,IND,8184082,7491513,122111
10/31/20,BRA,5535605,5005161,159884
10/31/20,FRA,1374691,97475,36495
10/31/20,RUS,1606267,1208440,27787
10/31/20,TUR,375367,323971,10252
10/31/20,ARG,1166924,973939,31002
10/31/20,ITA,679430,289426,38618
10/31/20,COL,1074184,969230,31314
10/31/20,ESP,1185678,150376,35878
10/31/20,GER,531790,356410,10483
11/30/20,IND,9462809,8889585,137621
11/30/20,BRA,6335878,5597802,173120
11/30/20,FRA,2223393,139810,52383
11/30/20,RUS,2275936,1763493,39491
11/30/20,TUR,638847,404727,13746
11/30/20,ARG,1424533,1257227,38730
11/30/20,ITA,1601554,757507,55576
11/30/20,COL,1316806,1210489,36766
11/30/20,ESP,1648187,150376,45069
11/30/20,GER,1069912,749219,16694
12/31/20,IND,10286709,9883461,148994
12/31/20,BRA,7675973,6848844,194949
12/31/20,FRA,2616902,170426,64267
12/31/20,RUS,3127347,2527722,56271
12/31/20,TUR,2208652,2100650,20881
12/31/20,ARG,1625514,1426676,43245
12/31/20,ITA,2107166,1463111,74159
12/31/20,COL,1642775,1508419,43213
12/31/20,ESP,1928265,150376,50837
12/31/20,GER,1760520,1350708,33791
1/31/21,IND,10757610,10434983,154392
1/31/21,BRA,9204731,8176373,224504
1/31/21,FRA,3186354,199589,75673
1/31/21,RUS,3808348,3264611,72029
1/31/21,TUR,2477463,2362415,25993
1/31/21,ARG,1927239,1721650,47974
1/31/21,ITA,2553032,2010548,88516
1/31/21,COL,2094884,1938322,53983
1/31/21,ESP,2743119,150376,58319
1/31/21,GER,2225659,1940046,57163
2/28/21,IND,11112241,10786452,157157
2/28/21,BRA,10551259,9382316,254942
2/28/21,FRA,3732426,228299,85980
2/28/21,RUS,4198400,3769025,84700
2/28/21,TUR,2701588,2572234,28569
2/28/21,ARG,2107365,1905021,51965
2/28/21,ITA,2925265,2405199,97699
2/28/21,COL,2251690,2148249,59766
2/28/21,ESP,3188553,150376,69142
2/28/21,GER,2450295,2259548,70152
3/31/21,IND,12221665,11474683,162927
3/31/21,BRA,12748747,11181371,321515
3/31/21,FRA,4611392,264511,95052
3/31/21,RUS,4494234,4118709,97219
3/31/21,TUR,3317182,3014226,31537
3/31/21,ARG,2348821,2102616,55858
3/31/21,ITA,3584899,2913045,109346
3/31/21,COL,2406377,2285515,63422
3/31/21,ESP,3284353,150376,75459
3/31/21,GER,2843644,2539660,76589
4/30/21,IND,19164969,15684406,211853
4/30/21,BRA,14659011,12991951,403781
4/30/21,FRA,5571804,305692,103815
4/30/21,RUS,4750755,4377504,108290
4/30/21,TUR,4820591,4323897,40131
4/30/21,ARG,2977363,2634306,63865
4/30/21,ITA,4022653,3465576,120807
4/30/21,COL,2859724,2669308,73720
4/30/21,ESP,3524077,150376,78216
4/30/21,GER,3405365,3008640,83097
5/31/21,IND,28175044,25947629,331895
5/31/21,BRA,16545554,14586009,462791
5/31/21,FRA,5609558,332474,108700
5/31/21,RUS,5013512,4630461,119464
5/31/21,TUR,5249404,5114624,47527
5/31/21,ARG,3781784,3350602,78093
5/31/21,ITA,4217821,3858019,126128
5/31/21,COL,3406456,3169573,88774
5/31/21,ESP,3678390,150376,79953
5/31/21,GER,3689921,3498580,88601
6/30/21,IND,30411634,29488918,399459
6/30/21,BRA,18557141,16299258,518066
6/30/21,FRA,5707142,340159,110161
6/30/21,RUS,5449594,4942283,132973
6/30/21,TUR,5425652,5294285,49732
6/30/21,ARG,4470374,4076921,94304
6/30/21,ITA,4259909,4081902,127566
6/30/21,COL,4240982,3936156,106544
6/30/21,ESP,3808960,150376,80875
6/30/21,GER,3736205,3623800,90945

d3.js代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type='text/javascript' src='../Resources/lib/d3.js'></script>
</head>
<body>
    <svg width='1200px' height='800px'></svg>
    <script type='text/javascript'>
      const margin = { top: 200, left: 500 }
      const svg = d3.select('svg')
      const g = svg.append('g').attr('transform', `translate(${margin.left}, ${margin.top})`)//整体变换

      const dataset=new Array()//将数据处理后的一维数组
      const shuju=new Array()//每个相同时间的10个国家数据放在一起的二维数组

      d3.csv('../Resources/data/covid19.csv').then(async function (data) {
        dataProcess(data)//数据处理函数
    
            const barHeight = 400//条形图绘图区高度
            const recovered=d3.map(dataset,d=>d.recovered) 
            const death=d3.map(dataset,d=>d.death) 
            const confirmed=d3.map(dataset,d=>d.confirmed)
            const maxconfirmed=d3.max(confirmed)
            const maxrecovered=d3.max(recovered)
            const maxdeath=d3.max(death)
            //绘制X轴和Y轴坐标系
            const xScale = d3.scaleLinear([0, maxrecovered+5000000], [0, 600]).nice()
            const yScale = d3.scaleLinear([0,maxdeath+100000], [barHeight,0])
            const rScale=d3.scaleLinear([0,maxconfirmed], [0,50])
            const xAxis = d3.axisBottom(xScale).ticks(7).tickSize(0).tickFormat(d3.format('.2s'))//X轴
            const yAxis = d3.axisLeft(yScale).ticks(6).tickSize(0).tickFormat(d3.format('.2s'))//Y轴
            g.append('g').attr('transform',`translate(0,${barHeight})`).call(xAxis)
            g.append('g').call(yAxis);
            //给坐标轴设置Recovered和Death文本
            g.append('text').attr('transform',`translate(250,450)`).text('Recovered').call(xScale)
            g.append('text').text('Death').attr('writing-mode','vertical-lr').attr('transform','translate(-80,190)').call(yScale)
          
            //更新绘图函数
            for(let i=0;i<shuju.length;i++){
                await update(shuju[i])
            }
            //修改字体样式
            d3.selectAll('text').attr('font-size', '14px').attr('font-weight','700')

            function update(currData){
    
            const transition = d3.transition().duration(5000).ease(d3.easeLinear)
            //绘制散点并更新散点
            const updatecircle=g.selectAll('circle').data(currData)
            
            const entercircle=updatecircle.enter().append('circle')
                  .attr('cx',0)
                  .attr('cy',400)
                  .attr('r',0)
                  .attr('fill', (d, i) => d3.schemeCategory10[i])

            updatecircle.merge(entercircle).transition(transition)
                .attr('cx', d =>xScale(d.recovered))
                .attr('cy', d =>yScale(d.death))
                .attr('r',d=>rScale(d.confirmed))
            //text文本并更新文本坐标
            const updatetext=g.selectAll('#countrytext').data(currData)
            const entertext=updatetext.enter()
                  .append('text')
                  .attr('id','countrytext')
                  .attr('x',0)
                  .attr('y',400)

            const mergeText=updatetext.merge(entertext).transition(transition)
                 .attr('x', d =>xScale(d.recovered))
                 .attr('y', d =>yScale(d.death))
                 .text(d=>d.country)
            }
      })
    
      function dataProcess(data){
        let k=0,i=0
        for(let i=0;i<18;i++) shuju[i]=new Array()
        data.forEach(row => {//数组遍历
                i++
                const { confirmed, country, date, death, recovered } = row//解构赋值
                const obj = {}
                obj.date = new Date(date)//生成日期对象
                obj.country = country
                obj.confirmed = +confirmed//转换为数值
                obj.recovered = +recovered
                obj.death = +death
                dataset.push(obj)
                shuju[k].push(obj)
                if(i>9) {i=0,k++;}
            })
      }
       
      </script>
</body>
</html>
上一篇:双数组字典树


下一篇:获取np数组前N大值索引