Scaling, Legends, and Color - ๐Ÿจยถ

from IPython.display import HTML, Javascript, display

def configure_d3():
    display(Javascript("""
    require.config({
      paths: {
        d3: "https://d3js.org/d3.v6.min"
      }
    })"""))


configure_d3()
%%html
<script type="text/javascript">   
require(['d3'], function (d3) {
    
    d3.csv('https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/us_state_vaccinations.csv')
        .then(function(data) {
            data = data.filter(d=> (d.location != "United States") && (d.total_vaccinations != ""))
            const dateConverter = d3.timeParse("%Y-%m-%d")
            data = data.map(d=> ({date:dateConverter(d.date),vaccinated:+d.people_vaccinated,location:d.location}))
            console.log(data)
        })
        .catch(function(error){
        //
        })
    
})
</script>

Acknowledgementยถ

Max Roser, Hannah Ritchie, Esteban Ortiz-Ospina and Joe Hasell (2020) - โ€œCoronavirus Pandemic (COVID-19)โ€. Published online at OurWorldInData.org. Retrieved from: โ€˜https://ourworldindata.org/coronavirusโ€™ [Online Resource]

Original Link: https://github.com/owid/covid-19-data (Accessed 3/11/2021) Source Link: https://github.com/owid/covid-19-data/tree/master/public/data/vaccinations

Bostock, M., Ogievetsky, V., & Heer, J. (2011). Dยณ data-driven documents. IEEE transactions on visualization and computer graphics, 17(12), 2301-2309.

All Dataยถ

%%html
<div id="gohere1"></div>
<script type="text/javascript">   
require(['d3'], function (d3) {
    
    d3.csv('https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/us_state_vaccinations.csv')
        .then(function(data) {
            const width = 700
            const height = 400
            const margin = 60 
            data = data.filter(d=> (d.location != "United States") && (d.total_vaccinations != ""))
            const dateConverter = d3.timeParse("%Y-%m-%d")
            data = data.map(d=> ({date:dateConverter(d.date),vaccinated:+d.people_vaccinated,location:d.location}))
            
            const xScale = d3.scaleTime().range([margin , width - margin]).domain(d3.extent(data, (d,i) => d.date))
            const yScale = d3.scaleLinear().range([height-margin , margin]).domain(d3.extent(data, (d,i) => d.vaccinated))
            
            const line = d3.line()
                .x((d,i)=> xScale(d.date)) 
                .y((d,i)=> yScale(d.vaccinated)) 
            
            
            const svg = d3.select("div#gohere1").append("svg")
                .attr("width", width)
                .attr("height", height)
            
            
            const xAxis = d3.axisBottom().scale(xScale).tickFormat(d3.timeFormat("%m-%d"))
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + (height-margin) + ")")
                .call(xAxis) 
            
            svg.append("text")
                .attr("x", width/2)
                .attr("y", height-5)
                .style("text-anchor", "middle")
                .text("Date")
            
            const yAxis = d3.axisLeft().scale(yScale).tickFormat((d,i) => d/100000 )
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + margin + ",0)")
                .call(yAxis)  
            
            svg.append("text")
                .attr("transform", "rotate(-90,15,"+(height/2)+")")
                .attr("x", 15)
                .attr("y", height/2)
                .style("text-anchor", "middle")
                .text("People Vaccinated (x 100000)") 
            
            svg.selectAll("circle")
                .data(data)
                .join("circle")
                .attr("cx", (d,i)=> xScale(d.date))
                .attr("cy", (d,i)=> yScale(d.vaccinated))
                .attr("r", 5)
                .append("title")
                .text(d=> "Location: "+d.location+"\nVaccinated: "+d.vaccinated)
                
            
            
        })
        .catch(function(error){
        
        })
    
})
</script>

Sorting: https://observablehq.com/@d3/d3-ascending

%%html
<div id="gohere2"></div>
<script type="text/javascript">   
require(['d3'], function (d3) {
    
    d3.csv('https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/us_state_vaccinations.csv')
        .then(function(data) {
            const width = 700
            const height = 400
            const margin = 60 
            data = data.filter(d=> (d.location != "United States") && (d.total_vaccinations != ""))
            const dataParse = d3.timeParse("%Y-%m-%d") // creates the date object
            const dataFormat = d3.timeFormat("%Y-%m-%d") // creates a string from the date object
            data = data.map(d=> ({date:dataParse(d.date),vaccinated:+d.people_vaccinated,location:d.location}))
            console.log(data.sort((a, b) => b.date - a.date)[0])
            const lastDate = data.sort((a, b) => b.date - a.date)[0].date
            data = data.filter(d=> dataFormat(d.date) == dataFormat(lastDate) )
            console.log(data)
            
            // Sorting by vaccinated and using a linear scale
            data = data.sort((a, b) => b.vaccinated - a.vaccinated)
            const xScale = d3.scaleLinear().range([margin , width - margin]).domain(d3.extent(data, (d,i) => i))
            const yScale = d3.scaleLinear().range([height-margin , margin]).domain(d3.extent(data, (d,i) => d.vaccinated))
            
            
            const svg = d3.select("div#gohere2").append("svg")
                .attr("width", width)
                .attr("height", height)
            
            
            const xAxis = d3.axisBottom().scale(xScale)
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + (height-margin) + ")")
                .call(xAxis) 
            
            svg.append("text")
                .attr("x", width/2)
                .attr("y", height-5)
                .style("text-anchor", "middle")
                .text("Index ordered by vaccinated")
            
            const yAxis = d3.axisLeft().scale(yScale).tickFormat((d,i) => d/100000 )
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + margin + ",0)")
                .call(yAxis)  
            
            svg.append("text")
                .attr("transform", "rotate(-90,15,"+(height/2)+")")
                .attr("x", 15)
                .attr("y", height/2)
                .style("text-anchor", "middle")
                .text("People Vaccinated (x 100000)") 
            
            svg.selectAll("circle")
                .data(data)
                .join("circle")
                .attr("cx", (d,i)=> xScale(i))
                .attr("cy", (d,i)=> yScale(d.vaccinated))
                .attr("r", 5)
                .append("title")
                .text(d=> "Location: "+d.location+" Vaccinated: "+d.vaccinated)
                
            
            
        })
        .catch(function(error){
        
        })
    
})
</script>

Logยถ

%%html
<div id="gohere3"></div>
<script type="text/javascript">   
require(['d3'], function (d3) {
    
    d3.csv('https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/us_state_vaccinations.csv')
        .then(function(data) {
            const width = 700
            const height = 500
            const margin = 60 
            data = data.filter(d=> (d.location != "United States") && (d.total_vaccinations != ""))
            const dataParse = d3.timeParse("%Y-%m-%d")
            const dataFormat = d3.timeFormat("%Y-%m-%d")
            data = data.map(d=> ({date:dataParse(d.date),vaccinated:+d.people_vaccinated,location:d.location}))
            console.log(data.sort((a, b) => b.date - a.date)[0])
            const lastDate = data.sort((a, b) => b.date - a.date)[0].date
            data = data.filter(d=> dataFormat(d.date) == dataFormat(lastDate) )
            console.log(data)
            
            // Sorting by vaccinated and using a linear scale
            data = data.sort((a, b) => b.vaccinated - a.vaccinated)
            data = data.filter(d=> d.vaccinated != 0 )
            const xScale = d3.scaleLinear().range([margin , width - margin]).domain(d3.extent(data, (d,i) => i))
            const yScale = d3.scaleLog().range([height-margin , margin]).domain(d3.extent(data, (d,i) => d.vaccinated))
            
            
            const svg = d3.select("div#gohere3").append("svg")
                .attr("width", width)
                .attr("height", height)
            
            
            const xAxis = d3.axisBottom().scale(xScale)
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + (height-margin) + ")")
                .call(xAxis) 
            
            svg.append("text")
                .attr("x", width/2)
                .attr("y", height-5)
                .style("text-anchor", "middle")
                .text("Index ordered by vaccinated")
            
            const yAxis = d3.axisLeft().scale(yScale).tickFormat((d,i) => d/100000 )
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + margin + ",0)")
                .call(yAxis)  
            
            svg.append("text")
                .attr("transform", "rotate(-90,15,"+(height/2)+")")
                .attr("x", 15)
                .attr("y", height/2)
                .style("text-anchor", "middle")
                .text("People Vaccinated (x 100000)") 
            
            svg.selectAll("circle")
                .data(data)
                .join("circle")
                .attr("cx", (d,i)=> xScale(i))
                .attr("cy", (d,i)=> yScale(d.vaccinated))
                .attr("r", 5)
                .append("title")
                .text(d=> "Location: "+d.location+" Vaccinated: "+d.vaccinated)
                
            
            
        })
        .catch(function(error){
        
        })
    
})
</script>

Power Scales -ยถ

mx^k + b, where k is the exponent value

https://github.com/d3/d3-scale#scalePow

%%html
<div id="gohere4"></div>
<script type="text/javascript">   
require(['d3'], function (d3) {
    
    d3.csv('https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/us_state_vaccinations.csv')
        .then(function(data) {
            const width = 700
            const height = 500
            const margin = 60 
            data = data.filter(d=> (d.location != "United States") && (d.total_vaccinations != ""))
            const dataParse = d3.timeParse("%Y-%m-%d")
            const dataFormat = d3.timeFormat("%Y-%m-%d")
            data = data.map(d=> ({date:dataParse(d.date),vaccinated:+d.people_vaccinated,location:d.location}))
            console.log(data.sort((a, b) => b.date - a.date)[0])
            const lastDate = data.sort((a, b) => b.date - a.date)[0].date
            data = data.filter(d=> dataFormat(d.date) == dataFormat(lastDate) )
            console.log(data)
            
            // Sorting by vaccinated and using a linear scale
            data = data.sort((a, b) => b.vaccinated - a.vaccinated)

            const xScale = d3.scaleLinear().range([margin , width - margin]).domain(d3.extent(data, (d,i) => i))
            const yScale = d3.scalePow().exponent(.5).range([height-margin , margin]).domain(d3.extent(data, (d,i) => d.vaccinated))
            
            
            const svg = d3.select("div#gohere4").append("svg")
                .attr("width", width)
                .attr("height", height)
            
            
            const xAxis = d3.axisBottom().scale(xScale)
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + (height-margin) + ")")
                .call(xAxis) 
            
            svg.append("text")
                .attr("x", width/2)
                .attr("y", height-5)
                .style("text-anchor", "middle")
                .text("Index ordered by vaccinated")
            
            const yAxis = d3.axisLeft().scale(yScale).tickFormat((d,i) => d/100000 )
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + margin + ",0)")
                .call(yAxis)  
            
            svg.append("text")
                .attr("transform", "rotate(-90,15,"+(height/2)+")")
                .attr("x", 15)
                .attr("y", height/2)
                .style("text-anchor", "middle")
                .text("People Vaccinated (x 100000)") 
            
            svg.selectAll("circle")
                .data(data)
                .join("circle")
                .attr("cx", (d,i)=> xScale(i))
                .attr("cy", (d,i)=> yScale(d.vaccinated))
                .attr("r", 5)
                .append("title")
                .text(d=> "Location: "+d.location+" Vaccinated: "+d.vaccinated)
                
            
            
        })
        .catch(function(error){
        
        })
    
})
</script>

k=.25ยถ

%%html
<div id="gohere5"></div>
<script type="text/javascript">   
require(['d3'], function (d3) {
    
    d3.csv('https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/us_state_vaccinations.csv')
        .then(function(data) {
            const width = 700
            const height = 500
            const margin = 60 
            data = data.filter(d=> (d.location != "United States") && (d.total_vaccinations != ""))
            const dataParse = d3.timeParse("%Y-%m-%d")
            const dataFormat = d3.timeFormat("%Y-%m-%d")
            data = data.map(d=> ({date:dataParse(d.date),vaccinated:+d.people_vaccinated,location:d.location}))
            const lastDate = data.sort((a, b) => b.date - a.date)[0].date
            data = data.filter(d=> dataFormat(d.date) == dataFormat(lastDate) )
            
            // Sorting by vaccinated and using a linear scale
            data = data.sort((a, b) => b.vaccinated - a.vaccinated)

            const xScale = d3.scaleLinear().range([margin , width - margin]).domain(d3.extent(data, (d,i) => i))
            const yScale = d3.scalePow().exponent(.25).range([height-margin , margin]).domain(d3.extent(data, (d,i) => d.vaccinated))
            
            
            const svg = d3.select("div#gohere5").append("svg")
                .attr("width", width)
                .attr("height", height)
            
            
            const xAxis = d3.axisBottom().scale(xScale)
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + (height-margin) + ")")
                .call(xAxis) 
            
            svg.append("text")
                .attr("x", width/2)
                .attr("y", height-5)
                .style("text-anchor", "middle")
                .text("Index ordered by vaccinated")
            
            const yAxis = d3.axisLeft().scale(yScale).tickFormat((d,i) => d/100000 )
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + margin + ",0)")
                .call(yAxis)  
            
            svg.append("text")
                .attr("transform", "rotate(-90,15,"+(height/2)+")")
                .attr("x", 15)
                .attr("y", height/2)
                .style("text-anchor", "middle")
                .text("People Vaccinated (x 100000)") 
            
            svg.selectAll("circle")
                .data(data)
                .join("circle")
                .attr("cx", (d,i)=> xScale(i))
                .attr("cy", (d,i)=> yScale(d.vaccinated))
                .attr("r", 5)
                .append("title")
                .text(d=> "Location: "+d.location+" Vaccinated: "+d.vaccinated)
                
            
            
        })
        .catch(function(error){
        
        })
    
})
</script>

k=.75ยถ

%%html
<div id="gohere6"></div>
<script type="text/javascript">   
require(['d3'], function (d3) {
    
    d3.csv('https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/us_state_vaccinations.csv')
        .then(function(data) {
            const width = 700
            const height = 500
            const margin = 60 
            data = data.filter(d=> (d.location != "United States") && (d.total_vaccinations != ""))
            const dataParse = d3.timeParse("%Y-%m-%d")
            const dataFormat = d3.timeFormat("%Y-%m-%d")
            data = data.map(d=> ({date:dataParse(d.date),vaccinated:+d.people_vaccinated,location:d.location}))
            const lastDate = data.sort((a, b) => b.date - a.date)[0].date
            data = data.filter(d=> dataFormat(d.date) == dataFormat(lastDate) )
            
            // Sorting by vaccinated and using a linear scale
            data = data.sort((a, b) => b.vaccinated - a.vaccinated)

            const xScale = d3.scaleLinear().range([margin , width - margin]).domain(d3.extent(data, (d,i) => i))
            const yScale = d3.scalePow().exponent(1).range([height-margin , margin]).domain(d3.extent(data, (d,i) => d.vaccinated))
            
            
            const svg = d3.select("div#gohere6").append("svg")
                .attr("width", width)
                .attr("height", height)
            
            
            const xAxis = d3.axisBottom().scale(xScale)
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + (height-margin) + ")")
                .call(xAxis) 
            
            svg.append("text")
                .attr("x", width/2)
                .attr("y", height-5)
                .style("text-anchor", "middle")
                .text("Index ordered by vaccinated")
            
            const yAxis = d3.axisLeft().scale(yScale).tickFormat((d,i) => d/100000 )
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + margin + ",0)")
                .call(yAxis)  
            
            svg.append("text")
                .attr("transform", "rotate(-90,15,"+(height/2)+")")
                .attr("x", 15)
                .attr("y", height/2)
                .style("text-anchor", "middle")
                .text("People Vaccinated (x 100000)") 
            
            svg.selectAll("circle")
                .data(data)
                .join("circle")
                .attr("cx", (d,i)=> xScale(i))
                .attr("cy", (d,i)=> yScale(d.vaccinated))
                .attr("r", 5)
                .append("title")
                .text(d=> "Location: "+d.location+" Vaccinated: "+d.vaccinated)
                
            
            
        })
        .catch(function(error){
        
        })
    
})
</script>

Discrete Binsยถ

There is a really nice tutorial about this located here: https://observablehq.com/@d3/quantile-quantize-and-threshold-scales?collection=@d3/d3-scale

%%html
<div id="gohere6b"></div>
<script type="text/javascript">   
require(['d3'], function (d3) {
    
    d3.csv('https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/us_state_vaccinations.csv')
        .then(function(data) {
            const width = 700
            const height = 500
            const margin = 60 
            data = data.filter(d=> (d.location != "United States") && (d.total_vaccinations != ""))
            const dataParse = d3.timeParse("%Y-%m-%d")
            const dataFormat = d3.timeFormat("%Y-%m-%d")
            data = data.map(d=> ({date:dataParse(d.date),vaccinated:+d.people_vaccinated,location:d.location}))

            const lastDate = data.sort((a, b) => b.date - a.date)[0].date
            data = data.filter(d=> dataFormat(d.date) == dataFormat(lastDate) )
            
            // Sorting by vaccinated and using a linear scale
            data = data.sort((a, b) => b.vaccinated - a.vaccinated)

            const xScale = d3.scaleLinear().range([margin , width - margin]).domain(d3.extent(data, (d,i) => i))
            
            const cut1 = 300000
            const cut2 = 3000000
            const yScale = d3.scaleThreshold().range([height-margin, (height-margin)/2, margin]).domain([cut1, cut2])            
               
            const svg = d3.select("div#gohere6b").append("svg")
                .attr("width", width)
                .attr("height", height)
            
            
            const xAxis = d3.axisBottom().scale(xScale)
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + (height-margin) + ")")
                .call(xAxis) 
            
            svg.append("text")
                .attr("x", width/2)
                .attr("y", height-5)
                .style("text-anchor", "middle")
                .text("Index ordered by vaccinated")
            
            const yAxis = d3.axisLeft().scale(yScale).tickFormat((d,i) => d/100000 )
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + margin + ",0)")
                .call(yAxis)  
            
            svg.append("text")
                .attr("transform", "rotate(-90,15,"+(height/2)+")")
                .attr("x", 15)
                .attr("y", height/2)
                .style("text-anchor", "middle")
                .text("People Vaccinated (x 100000)") 
            
            svg.selectAll("circle")
                .data(data)
                .join("circle")
                .attr("cx", (d,i)=> xScale(i))
                .attr("cy", (d,i)=> yScale(d.vaccinated))
                .attr("r", 5)
                .append("title")
                .text(d=> "Location: "+d.location+" Vaccinated: "+d.vaccinated)
                
            
            
        })
        .catch(function(error){
        
        })
    
})
</script>

Quantizeยถ

%%html
<div id="gohere7"></div>
<script type="text/javascript">   
require(['d3'], function (d3) {
    
    d3.csv('https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/us_state_vaccinations.csv')
        .then(function(data) {
            const width = 700
            const height = 500
            const margin = 60 
            data = data.filter(d=> (d.location != "United States") && (d.total_vaccinations != ""))
            const dataParse = d3.timeParse("%Y-%m-%d")
            const dataFormat = d3.timeFormat("%Y-%m-%d")
            data = data.map(d=> ({date:dataParse(d.date),vaccinated:+d.people_vaccinated,location:d.location}))

            const lastDate = data.sort((a, b) => b.date - a.date)[0].date
            data = data.filter(d=> dataFormat(d.date) == dataFormat(lastDate) )
            
            // Sorting by vaccinated and using a linear scale
            data = data.sort((a, b) => b.vaccinated - a.vaccinated)

            const xScale = d3.scaleLinear().range([margin , width - margin]).domain(d3.extent(data, (d,i) => i))
            
            const q1 = d3.quantile(data.map(d=> d.vaccinated).sort(d3.ascending),.33)
            const q2 = d3.quantile(data.map(d=> d.vaccinated).sort(d3.ascending),.66)
            console.log(q1,q2,d3.max(data,d=>d.vaccinated))
            const yScale = d3.scaleQuantize().range([height-margin, (height-margin)/2, margin]).domain(d3.extent(data,d=>d.vaccinated))          
               
            const svg = d3.select("div#gohere7").append("svg")
                .attr("width", width)
                .attr("height", height)
            
            
            const xAxis = d3.axisBottom().scale(xScale)
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + (height-margin) + ")")
                .call(xAxis) 
            
            svg.append("text")
                .attr("x", width/2)
                .attr("y", height-5)
                .style("text-anchor", "middle")
                .text("Index ordered by vaccinated")
            
            const yAxis = d3.axisLeft().scale(yScale).tickFormat((d,i) => d/100000 )
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + margin + ",0)")
                .call(yAxis)  
            
            svg.append("text")
                .attr("transform", "rotate(-90,15,"+(height/2)+")")
                .attr("x", 15)
                .attr("y", height/2)
                .style("text-anchor", "middle")
                .text("People Vaccinated (x 100000)") 
            
            svg.selectAll("circle")
                .data(data)
                .join("circle")
                .attr("cx", (d,i)=> xScale(i))
                .attr("cy", (d,i)=> yScale(d.vaccinated))
                .attr("r", 5)
                .append("title")
                .text(d=> "Location: "+d.location+" Vaccinated: "+d.vaccinated)
                
            
            
        })
        .catch(function(error){
        
        })
    
})
</script>

Quantileยถ

%%html
<div id="gohere8"></div>
<script type="text/javascript">   
require(['d3'], function (d3) {
    
    d3.csv('https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/us_state_vaccinations.csv')
        .then(function(data) {
            const width = 700
            const height = 500
            const margin = 60 
            data = data.filter(d=> (d.location != "United States") && (d.total_vaccinations != ""))
            const dataParse = d3.timeParse("%Y-%m-%d")
            const dataFormat = d3.timeFormat("%Y-%m-%d")
            data = data.map(d=> ({date:dataParse(d.date),vaccinated:+d.people_vaccinated,location:d.location}))

            const lastDate = data.sort((a, b) => b.date - a.date)[0].date
            data = data.filter(d=> dataFormat(d.date) == dataFormat(lastDate) )
            
            // Sorting by vaccinated and using a linear scale
            data = data.sort((a, b) => b.vaccinated - a.vaccinated)

            const xScale = d3.scaleLinear().range([margin , width - margin]).domain(d3.extent(data, (d,i) => i))

            const yScale = d3.scaleQuantile().range([height-margin, (height-margin)/2, margin]).domain(data.map(d=>d.vaccinated))   
            
            const svg = d3.select("div#gohere8").append("svg")
                .attr("width", width)
                .attr("height", height)
            
            
            const xAxis = d3.axisBottom().scale(xScale)
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + (height-margin) + ")")
                .call(xAxis) 
            
            svg.append("text")
                .attr("x", width/2)
                .attr("y", height-5)
                .style("text-anchor", "middle")
                .text("Index ordered by vaccinated")
            
            const yAxis = d3.axisLeft().scale(yScale).tickFormat((d,i) => d/100000 )
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + margin + ",0)")
                .call(yAxis)  
            
            svg.append("text")
                .attr("transform", "rotate(-90,15,"+(height/2)+")")
                .attr("x", 15)
                .attr("y", height/2)
                .style("text-anchor", "middle")
                .text("People Vaccinated (x 100000)") 
            
            svg.selectAll("circle")
                .data(data)
                .join("circle")
                .attr("cx", (d,i)=> xScale(i))
                .attr("cy", (d,i)=> yScale(d.vaccinated))
                .attr("r", 5)
                .append("title")
                .text(d=> "Location: "+d[0]
                      .location+" Vaccinated: "+d.vaccinated)
                
            
            
        })
        .catch(function(error){
            console.log(error)
        })
    
})
</script>

Legendsยถ

D3.js Colors - https://github.com/d3/d3-scale-chromatic

%%html
<div id="legend1"></div>
<script type="text/javascript">   
require(['d3'], function (d3) {
    
    d3.csv('https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/us_state_vaccinations.csv')
        .then(function(data) {
            const width = 800
            const height = 300
            const margin = 40 
            data = data.filter(d=> (d.location != "United States") && (d.total_vaccinations != ""))
            const dataParse = d3.timeParse("%Y-%m-%d") // creates the date object
            const dataFormat = d3.timeFormat("%Y-%m-%d") // creates a string from the date object
            data = data.map(d=> ({date:dataParse(d.date),vaccinated:+d.people_vaccinated,location:d.location}))

            const lastDate = data.sort((a, b) => b.date - a.date)[0].date
            data = data.filter(d=> dataFormat(d.date) == dataFormat(lastDate) )
            data = data.filter(d=> d.vaccinated != 0 )

            data = data.sort((a, b) => b.vaccinated - a.vaccinated)
            const palette = d3.interpolateTurbo
            const scaling = d3.scaleLog().range([margin,width-margin]).domain(d3.extent(data, (d,i) => d.vaccinated))
            const x = d3.scaleLinear().range([width-margin,margin]).domain(d3.extent(data, (d,i) => i))
            const coloringCircles = d3.scaleLog().range([0,1]).domain(d3.extent(data, (d,i) => d.vaccinated))
            
            
            const svg = d3.select("div#legend1").append("svg")
                .attr("width", width)
                .attr("height", height)
            
            
            const xAxis = d3.axisBottom().scale(scaling).ticks(15, "~s")
            
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + (height-margin) + ")")
                .call(xAxis) 

            svg.append("text")
                .attr("x", width/2)
                .attr("y", height-5)
                .style("text-anchor", "middle")
                .text("Vaccinated (Log Scale)")
            
            svg.selectAll("circle")
                .data(data)
                .join("circle")
                .attr("cx", (d,i)=> x(i))
                .attr("cy", (d,i)=> height/2)
                .attr("r", 5)
                .style("fill",d=>palette(coloringCircles(d.vaccinated)))
                .style("stroke","black")
                .style("stroke-width",1)
                .append("title")
                .text(d=> "Location: "+d.location+" Vaccinated: "+d.vaccinated)            
            
            const num = 20
            const values = d3.range(1,num)
            
            const coloring = d3.scaleLinear().range([0,1]).domain(d3.extent(values))
            var defs = svg.append("defs")
            var linearGradient = defs.append("linearGradient")
                .attr("id", "linear-gradient1") 

            linearGradient.selectAll("stop").data(values).join("stop")
                .attr("offset", d=> d/num)
                .attr("stop-color", d=>palette(coloring(d)) )
            svg.append("rect")
                .attr("x", margin)
                .attr("y", (height-margin)-50)
                .attr("width", (width-margin)-(margin))
                .attr("height", 50)
                .style("fill", "url(#linear-gradient1)")

            
        })
        .catch(function(error){
            console.log(error)
        })
    
})
</script>