当前位置:   article > 正文

数据可视化【五】 Scatter Plot_scotplot x str

scotplot x str

Scatter Plot

vizhub上实现的代码:

https://vizhub.com/Edward-Elric233/53807a1b35d94329b3689081cd2ea945

https://vizhub.com/Edward-Elric233/b9647d50899a4a0e8e917f913cd0a53a

https://vizhub.com/Edward-Elric233/8c6b50cd81a04f048f490f48e4fe6264

由前面的柱状图,我们对图形进行一定的修改就可以得到散点图

在这里插入图片描述只要将绑定数据以后enter进行添加矩形的操作换成圆形就可以了,不过需要注意的是不能够y坐标再使用scaleBand了,而应该使用scalePoint,如果继续使用scaleBand的话需要调整圆的坐标(y坐标是Categorical的)。注意圆形的属性是cx,cy,r分别表示圆心的坐标和半径。

index.html

<!DOCTYPE html>
<html>

<head>
    <title>Scatter Plot</title>
    <link rel="stylesheet" href="./styles.css">
    <script src="https://unpkg.com/d3@5.7.0/dist/d3.min.js"></script>
    <!-- find D3 file on UNPKG d3.min.js-->
</head>

<body>
    <svg width="960" height="500"></svg>
    <script src="./index.js">
        // console.log(d3); test whether you have imported d3.js or not
    </script>

</body>

</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

index.js

const svg = d3.select('svg');
// svg.style('background-color', 'red'); test
const width = +svg.attr('width');
const height = +svg.attr('height');


const render = data => {
    const xValue = d => d.population;
    const yValue = d => d.country;
    const margin = { top: 60, right: 20, bottom: 80, left: 150 };
    const innerWidth = width - margin.left - margin.right;
    const innerHeight = height - margin.top - margin.bottom;

    const xScale = d3.scaleLinear()
        .domain([0, d3.max(data, xValue)])
        .range([0, innerWidth])
        .nice(); //作用是如果值域的最大值不够整齐可以变得整齐


    // const yScale = scaleBand()
    const yScale = d3.scalePoint()
        .domain(data.map(yValue))
        .range([0, innerHeight])
        .padding(0.5);

    const xAxisTickFormat = number => d3.format('.3s')(number).replace('G', 'B');

    const yAxis = d3.axisLeft(yScale)
        .tickSize(-innerWidth);;
    const xAxis = d3.axisBottom(xScale)
        .tickFormat(xAxisTickFormat)
        .tickSize(-innerHeight); //设置tick-line的长度



    const g = svg.append('g')
        .attr('transform', `translate(${margin.left},${margin.top})`);

    //yAxis(g.append('g'));
    const yAxisG = g.append('g').call(yAxis).selectAll('.domain').remove();
    const xAxisG = g.append('g').call(xAxis)
        .attr('transform', `translate(0,${innerHeight})`);
    xAxisG.selectAll('.domain').remove();

    xAxisG.append('text')
        .attr('class', 'axis-label')
        .attr('y', 60)
        .attr('x', innerWidth / 2)
        .attr('fill', 'black')
        .text('populiation');

    let colorSet = ['#eb2617', '#ffaa00', '#4dff00', '#00fbff', '#bb00ff', '#eeff00'];

    const createGetColor = (idx) => {
        var i = idx || -1;
        return {
            get: () => { i = (i + 1) % colorSet.length; return colorSet[i]; }
        };
    };

    const getColor = createGetColor();

    g.selectAll('circle').data(data)
        .enter().append('circle')
        .attr('cy', d => yScale(yValue(d)))
        .attr('cx', d => xScale(xValue(d)))
        .attr('r', 15)
        .attr('fill', getColor.get);

    g.append('text')
        .attr('class', 'title')
        .attr('y', -20)
        .text('Top 10 Most Population Countries');
};

d3.csv("https://gist.githubusercontent.com/Edward-Elric233/23f3024c472ffd7e34e6a5ac04bad26c/raw/6ced2249ea6f5d12f72c1eb00b8c1278d2c86e95/every%2520countries'%2520population").then(data => {
    data.forEach(d => {
        d.population = +d.population * 1000;
    });
    render(data);
    // console.log(data);
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

styles.css

body {
    margin: 0px;
    overflow: hidden;
    font-family: manosapce;
}

text {
    font-family: sans-serif;
}

.tick text {
    font-size: 2em;
    fill: #8E8883
}

.axis-label {
    fill: #8E8883;
    font-size: 2.5em
}

.title {
    font-size: 3em;
    fill: #8E8883
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

虽然大概实现了散点图,但是上面的数据不适合用散点图来进行表示。因此我们不妨更换数据,使用更适合的数据。

在这里插入图片描述这里因为y坐标也是Quantitative的,所以应该使用scaleLinear。画的时候注意坐标的方向,如果方向不对应的画可以调整scaleLineardomain或者range(反向即可)。这里因为圆形比较密集就设置了一下圆形的透明度opacity,看起来比较好看。

index.html

<!DOCTYPE html>
<html>

<head>
    <title>Cars Scatter Plot</title>
    <link rel="stylesheet" href="./styles.css">
    <script src="https://unpkg.com/d3@5.7.0/dist/d3.min.js"></script>
    <!-- find D3 file on UNPKG d3.min.js-->
</head>

<body>
    <svg width="960" height="500"></svg>
    <script src="./index.js">
        // console.log(d3); test whether you have imported d3.js or not
    </script>
</body>

</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

index.js

const svg = d3.select('svg');
// svg.style('background-color', 'red'); test
const width = +svg.attr('width');
const height = +svg.attr('height');

//mpg	cylinders	displacement	horsepower	weight	acceleration	year	origin	name


const render = data => {
    const title = 'Cars: Mpg vs. Horsepower';
    const xValue = d => d.mpg;
    const xAxisLabel = 'Mpg';
    const yValue = d => d.horsepower;
    const yAxisLabel = 'Horsepower';
    const margin = { top: 60, right: 20, bottom: 80, left: 100 };
    const innerWidth = width - margin.left - margin.right;
    const innerHeight = height - margin.top - margin.bottom;
    const circleRadius = 10;

    const xScale = d3.scaleLinear()
        //.domain([min(data, xValue), max(data, xValue)])	//和下面的写法等价
        .domain(d3.extent(data, xValue))
        .range([0, innerWidth])
        .nice(); //作用是如果值域的最大值不够整齐可以变得整齐


    // const yScale = scaleBand()
    const yScale = d3.scaleLinear()
        .domain([d3.max(data, yValue), d3.min(data, yValue)])
        .range([0, innerHeight])
        .nice();

    //const xAxisTickFormat = number => format('.3s')(number).replace('G','B');

    const yAxis = d3.axisLeft(yScale)
        .tickSize(-innerWidth)
        .tickPadding(15);
    const xAxis = d3.axisBottom(xScale)
        //.tickFormat(xAxisTickFormat)
        .tickSize(-innerHeight) //设置tick-line的长度
        .tickPadding(15); //通过设置Padding让x轴的数字离远一点



    const g = svg.append('g')
        .attr('transform', `translate(${margin.left},${margin.top})`);

    //yAxis(g.append('g'));
    const yAxisG = g.append('g').call(yAxis);
    yAxisG.selectAll('.domain').remove();

    yAxisG.append('text')
        .attr('class', 'axis-label')
        .attr('y', -70)
        .attr('x', -innerHeight / 2)
        .attr('fill', 'black')
        .attr('transform', `rotate(-90)`)
        .attr('text-anchor', 'middle') //设置锚点在中心
        .text(yAxisLabel);

    const xAxisG = g.append('g').call(xAxis)
        .attr('transform', `translate(0,${innerHeight})`);
    xAxisG.selectAll('.domain').remove();

    xAxisG.append('text')
        .attr('class', 'axis-label')
        .attr('y', 60)
        .attr('x', innerWidth / 2)
        .attr('fill', 'black')
        .text(xAxisLabel);

    let colorSet = ['#eb2617', '#ffaa00', '#4dff00', '#00fbff', '#bb00ff', '#eeff00'];

    const createGetColor = (idx) => {
        var i = idx || -1;
        return {
            get: () => { i = (i + 1) % colorSet.length; return colorSet[i]; }
        };
    };

    const getColor = createGetColor();

    g.selectAll('circle').data(data)
        .enter().append('circle')
        .attr('cy', d => yScale(yValue(d)))
        .attr('cx', d => xScale(xValue(d)))
        .attr('r', circleRadius)
        .attr('fill', getColor.get);

    g.append('text')
        .attr('class', 'title')
        .attr('y', -20)
        .attr('x', innerWidth / 2)
        .attr('text-anchor', 'middle')
        .text(title);
};

d3.csv('https://vizhub.com/curran/datasets/auto-mpg.csv').then(data => {
    data.forEach(d => {
        //得到的数据默认每个属性的值都是字符串,因此需要进行转换
        d.mpg = +d.mpg;
        d.cylinders = +d.cylinders;
        d.displacement = +d.displacement;
        d.horsepower = +d.horsepower;
        d.weight = +d.weight;
        d.acceleration = +d.acceleration;
        d.year = +d.year;
    });
    render(data);
    // console.log(data);
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111

styles.css

body {
    margin: 0px;
    overflow:hidden;
    font-family: manosapce;
  }
  
  circle {
    opacity : 0.5;
  }
  
  
  text {
    
    font-family : sans-serif;
  }
  
  .tick text {
    font-size : 2em;
      fill : #8E8883
  }
  
  .tick line {
      stroke : #E5E2E0
  }
  
  .axis-label {
      fill : #8E8883;
    font-size: 2.5em
  }
  
  .title {
      font-size : 3em;
    fill : #8E8883
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

对于时间轴的处理可以使用scaleTime
在这里插入图片描述
index.html

<!DOCTYPE html>
<html>

<head>
    <title>Temperature in San Francisc Scatter Plot</title>
    <link rel="stylesheet" href="./styles.css">
    <script src="https://unpkg.com/d3@5.7.0/dist/d3.min.js"></script>
    <!-- find D3 file on UNPKG d3.min.js-->
</head>

<body>
    <svg width="960" height="500"></svg>
    <script src="./index.js">
        // console.log(d3); test whether you have imported d3.js or not
    </script>

</body>

</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

html.js

const svg = d3.select('svg');
// svg.style('background-color', 'red'); test
const width = +svg.attr('width');
const height = +svg.attr('height');

const render = data => {
    const title = 'A week in San Francisco';
    const xValue = d => d.timestamp;
    const xAxisLabel = 'Time';
    const yValue = d => d.temperature;
    const yAxisLabel = 'Temperature';
    const margin = { top: 60, right: 20, bottom: 80, left: 100 };
    const innerWidth = width - margin.left - margin.right;
    const innerHeight = height - margin.top - margin.bottom;
    const circleRadius = 6;

    const xScale = d3.scaleTime()
        //.domain([min(data, xValue), max(data, xValue)])	//和下面的写法等价
        .domain(d3.extent(data, xValue))
        .range([0, innerWidth])
        .nice(); //作用是如果值域的最大值不够整齐可以变得整齐


    // const yScale = scaleBand()
    const yScale = d3.scaleLinear()
        .domain([d3.max(data, yValue), d3.min(data, yValue)])
        .range([0, innerHeight])
        .nice();

    //const xAxisTickFormat = number => format('.3s')(number).replace('G','B');

    const yAxis = d3.axisLeft(yScale)
        .tickSize(-innerWidth)
        .tickPadding(15);
    const xAxis = d3.axisBottom(xScale)
        //.tickFormat(xAxisTickFormat)
        .tickSize(-innerHeight) //设置tick-line的长度
        .tickPadding(15); //通过设置Padding让x轴的数字离远一点



    const g = svg.append('g')
        .attr('transform', `translate(${margin.left},${margin.top})`);

    //yAxis(g.append('g'));
    const yAxisG = g.append('g').call(yAxis);
    yAxisG.selectAll('.domain').remove();

    yAxisG.append('text')
        .attr('class', 'axis-label')
        .attr('y', -70)
        .attr('x', -innerHeight / 2)
        .attr('fill', 'black')
        .attr('transform', `rotate(-90)`)
        .attr('text-anchor', 'middle') //设置锚点在中心
        .text(yAxisLabel);

    const xAxisG = g.append('g').call(xAxis)
        .attr('transform', `translate(0,${innerHeight})`);
    xAxisG.selectAll('.domain').remove();

    xAxisG.append('text')
        .attr('class', 'axis-label')
        .attr('y', 60)
        .attr('x', innerWidth / 2)
        .attr('fill', 'black')
        .text(xAxisLabel);

    let colorSet = ['#eb2617', '#ffaa00', '#4dff00', '#00fbff', '#bb00ff', '#eeff00'];

    const createGetColor = (idx) => {
        var i = idx || -1;
        return {
            get: () => { i = (i + 1) % colorSet.length; return colorSet[i]; }
        };
    };

    const getColor = createGetColor();

    g.selectAll('circle').data(data)
        .enter().append('circle')
        .attr('cy', d => yScale(yValue(d)))
        .attr('cx', d => xScale(xValue(d)))
        .attr('r', circleRadius)
        .attr('fill', 'red');

    g.append('text')
        .attr('class', 'title')
        .attr('y', -20)
        .attr('x', innerWidth / 2)
        .attr('text-anchor', 'middle')
        .text(title);
};

d3.csv('https://vizhub.com/curran/datasets/temperature-in-san-francisco.csv').then(data => {
    // console.log(data);
    data.forEach(d => {
        //得到的数据默认每个属性的值都是字符串,因此需要进行转换
        d.temperature = +d.temperature;
        d.timestamp = new Date(d.timestamp);
    });
    render(data);
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103

styles.css

body {
    margin: 0px;
    overflow: hidden;
    font-family: manosapce;
}

circle {
    opacity: 0.5;
}

text {
    font-family: sans-serif;
}

.tick text {
    font-size: 2em;
    fill: #8E8883
}

.tick line {
    stroke: #E5E2E0
}

.axis-label {
    fill: #8E8883;
    font-size: 2.5em
}

.title {
    font-size: 3em;
    fill: #8E8883
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/97932
推荐阅读
相关标签
  

闽ICP备14008679号