Commit a1c9007a authored by numeroteca's avatar numeroteca

add cartograma ratio 201903, gráficos ratios plazas/hab to Barcelona

parent 9ea65d1c
......@@ -8,6 +8,18 @@ draft: true
{{< docdata doc-url="https://wiki.montera34.com/como-se-concentra-la-oferta-por-barrios-de-airbnb" data-url="#datos" data-date="2018" data-comments="InsideAirbnb, Ayuntamiento de Barcelona" >}}
## TLDR: La presencia de Airbnb se concentra en los distritos de Ciutat Vella y Eixample
Usamos dos indicadores diferentes para medir la presencia de Airbnb:
+ anuncios de Airbnb por cada 100 viviendas
+ plazas de Airbnb por cada 100 habitantes
<iframe title="Presencia de Airbnb en distritos de Barcelona" aria-label="Split Bars" id="datawrapper-chart-pCfVM" src="//datawrapper.dwcdn.net/pCfVM/1/" scrolling="no" frameborder="0" style="width: 0; min-width: 100% !important; border: none;" height="580"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",function(a){if(void 0!==a.data["datawrapper-height"])for(var e in a.data["datawrapper-height"]){var t=document.getElementById("datawrapper-chart-"+e)||document.querySelector("iframe[src*='"+e+"']");t&&(t.style.height=a.data["datawrapper-height"][e]+"px")}})}();</script>
## Paso a paso
Para estudiar la distribución de los anuncios de Airbnb se utilizan muchas veces mapas de puntos, donde cada uno representa a un anuncio. El problema de este tipo de visualizaciones es que son deifíciles de interpretar y no tienen en cuenta la densidad de viviendas.
{{% todo %}}
......@@ -32,7 +44,7 @@ Para hacer un análisis más riguroso tenemos que contar cuántas anuncios hay e
{{< figure src="/images/barcelona/mapa-coropletas-distritos-ratio-anuncios-100viv-barcelona-201903.png" alt="" title="" >}}
{{% /col %}}
{{% col md="6" %}}
{{< figure src="/images/barcelona/ratio-listings-airbnb-anuncios-distritos-barcelona-201903_blues.png" alt="Número de anuncios por distrito y tipo de alojamiento" title="Anuncios porcada 100 viviendas por distrito" >}}
{{< figure src="/images/barcelona/ratio-listings-airbnb-anuncios-distritos-barcelona-201903_blues.png" alt="Número de anuncios por distrito y tipo de alojamiento" title="Anuncios por cada 100 viviendas por distrito" >}}
{{% /col %}}
{{< /cols >}}
......@@ -75,6 +87,7 @@ Su distribución espacial es la siguiente. En el gráfico de barras mostramos ú
{{% /col %}}
{{< /cols >}}
{{% todo %}}
{{< figure src="/images/barcelona/ratio-airbnb-barrios-barcelona-201809.png" alt="Ratio de anuncios de Airbnb por cada 100 domicilios por barrio" title="Ratio de anuncios de Airbnb por cada 100 domicilios por barrio" >}}
{{% /todo %}}
......@@ -83,13 +96,49 @@ Vemos como ahora quien lidera la lista es el Barrio Gótico (17,3), seguido por
1
<iframe src="barcelona/ratio-airbnb-x-viv-coropletas-barcelona-201903.html" style="width: 0; min-width: 100% !important;" height="608">
<iframe src="/barcelona/ratio-airbnb-x-viv-coropletas-barcelona-201903.html" style="width: 0; min-width: 100% !important;" height="608">
2
{{% carto "barcelona/ratio-airbnb-x-viv-coropletas-barcelona-201903.html" %}}Número de alojamientos de Airbnb por número de viviendas por barrio{{% /carto %}}
{{% carto "/barcelona/ratio-airbnb-x-viv-coropletas-barcelona-201903.html" %}}Número de alojamientos de Airbnb por número de viviendas por barrio{{% /carto %}}
{{% carto "/cartograma-valencia/index.html" %}}Número de anuncios de Airbnb por número de viviendas por barrio{{% /carto %}}
## Ratio de plazas de Airbnb por cada 100 habitantes
Si miramos las plazas disponibles en Airbnb por el número de habitantes en cada barrio nos da una distribución espacial similar, que tiene en sus barrios centrales, el Gótico y la Dreta de l'Eixample su zonas calientes. Los dos en cabeza reducen distancias en este indicador. La Dreta (19,8 plazas por cada 100 habitantes) se acerca al Gótico (21,1), probablemente debido a que la mayor parte los anuncios de este último son habitaciones, habitualmente con menos plazas. El orden es parecido en ambos ratios con alguntas diferencias:
+ Sant Pere sigue en tercera pero a ás distancia de la Dreta que en el ratio anuncios / viviendas existentes
+ se conforma un grupo, del 4º al 8º, con valores en torno a 8,5-9 plazas por cada 100 habitantes.
{{< cols >}}
{{% col md="6" %}}
{{< figure src="/images/barcelona/mapa-coropletas-ratio-plazas-100hab-barcelona-201903.png" alt="" title="" >}}
{{% /col %}}
{{% col md="6" %}}
{{< figure src="/images/barcelona/ratio-plazas-100hab-airbnb-barrios-barcelona-201903_top25-oranges.png" alt="Número de plazas por barrio por distrito y tipo de alojamiento" title="Plazas por cada 100 habitantes por barrio " >}}
{{% /col %}}
{{< /cols >}}
{{< cols >}}
{{% col md="6" %}}
{{< figure src="/images/barcelona/mapa-coropletas-ratio-anuncios-100viv-barcelona-201903.png" alt="" title="" >}}
{{% /col %}}
{{% col md="6" %}}
{{< figure src="/images/barcelona/mapa-coropletas-ratio-plazas-100hab-barcelona-201903.png" alt="" title="" >}}
{{% /col %}}
{{< /cols >}}
{{< cols >}}
{{% col md="6" %}}
{{< figure src="/images/barcelona/ratio-listings-airbnb-anuncios-barrios-barcelona-201903_top25-blues.png" alt="" title="" >}}
{{% /col %}}
{{% col md="6" %}}
{{< figure src="/images/barcelona/ratio-plazas-100hab-airbnb-barrios-barcelona-201903_top25-oranges.png" alt="Número de plazas por barrio por distrito y tipo de alojamiento" title="Plazas por cada 100 habitantes por barrio " >}}
{{% /col %}}
{{< /cols >}}
{{% todo %}}
No lo pongo dado el alto número de habitaciones compartidas en Barcelona.
......@@ -130,16 +179,16 @@ Los mapas de coropletas no funcionan bien con cantidades absolutas (número de a
## Cartograma
En [este cartograma](/cartograma-barcelona/index.html) cada barrio está representado por un cuadrado: su área representa la cantidad de viviendas que hay en él y el color es más o menos intenso dependiendo del número de alojamientos de Airbnb que hay respecto al número de viviendas. De este modo evitamos uno de los problemas típicos de muchos mapas que sobrerepresentan a regiones que son poco relevantes pero que son muy extensas. De este modo podemos comparar los ratios de alojamiento por viviendas a la vez que su ubicación relativa en la ciudad y su tamaño.
En [este cartograma](/cartograma-barcelona/ratio-airbnb-domicilios-201903.html) cada barrio está representado por un cuadrado: su área representa la cantidad de viviendas que hay en él y el color es más o menos intenso dependiendo del número de alojamientos de Airbnb que hay respecto al número de viviendas. De este modo evitamos uno de los problemas típicos de muchos mapas que sobrerepresentan a regiones que son poco relevantes pero que son muy extensas. De este modo podemos comparar los ratios de alojamiento por viviendas a la vez que su ubicación relativa en la ciudad y su tamaño.
{{< figure src="/cartograma-barcelona/cartograma-barcelona-ratio-airbnb-domicilios.png" alt="Ratio de anuncios de viviendas completas de Airbnb por cada 100 domicilios por barrio" title="Ratio de anuncios de viviendas completas de Airbnb por cada 100 domicilios por barrio" >}}
[Ver el cartogramainteractivo a pantalla completa.](/cartograma-barcelona/index.html)
[Ver el cartogramainteractivo a pantalla completa.](/cartograma-barcelona/ratio-airbnb-domicilios-201903.html)
{{% carto "/cartograma-barcelona/index.html" %}}Número de anuncios de Airbnb por número de viviendas por barrio{{% /carto %}}
{{% carto "/cartograma-barcelona/ratio-airbnb-domicilios-201903.html" %}}Número de anuncios de Airbnb por número de viviendas por barrio{{% /carto %}}
## Datos
+ [Anuncios de AirBnb en Barcelona](https://github.com/montera34/airbnb.barcelona/tree/master/data/original/airbnb) scrapeados por InsideAirbnb.
+ Contornos barrios https://github.com/montera34/airbnb.barcelona/blob/master/data/original/contornos/barrios_geo.json
+ Número de domicilios por barrios (Padrón 2018) https://github.com/montera34/airbnb.barcelona/blob/master/data/original/demografia-vivienda/habitantes-viviendas-por-barrios_padron2018_ayto-barcelona.csv
+ [Anuncios de AirBnb en Barcelona marzo 2019](https://github.com/montera34/airbnb.barcelona/tree/master/data/original/airbnb) scrapeados por InsideAirbnb.
+ [Contornos barrios](https://github.com/montera34/airbnb.barcelona/blob/master/data/original/contornos/barrios_geo.json).
+ [Número de domicilios por barrios (Padrón 2018)](https://github.com/montera34/airbnb.barcelona/blob/master/data/original/demografia-vivienda/habitantes-viviendas-por-barrios_padron2018_ayto-barcelona.csv).
<!DOCTYPE html>
<html dir="ltr" lang="es-ES">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Anuncios de Airbnb por barrios. Barcelona. Marzo 2019</title>
<!-- Bootstrap -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<!-- basado en http://bl.ocks.org/numeroteca/1941df6cbcb6801cb1299a137ecf891c a su vez basado en cartogramas de Martín González https://martingonzalez.net/ -->
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<style>
body {
margin: 0px;
font-family: "Helvetica Neue", sans-serif;
}
.text-label {
font-size: 14px;
font-weight: 700;
}
.label {
font-size: 20px;
fill: black;
}
.tooltip {
position: absolute;
background: rgba(255, 255, 255, .85);
font-size: 14px;
padding: 10px;
border: 1px solid #ccc;
}
rect:hover {
stroke: black;
stroke-width: 2px;
}
.Gros text, .Centro text{
fill:white !important;
}
.Miracruz-Bidebieta text{
z-index:2;
}
.Ategorrieta-Ulia rect{
z-index:-1;
}
.domain {
display:none;
}
</style>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<script src="https://unpkg.com/d3-composite-projections@1.0.2"></script>
<script>
// Cartograma based on https://bl.ocks.org/martgnz codeand in https://bl.ocks.org/numeroteca/341f4b7e838c8bfd4f9cf6e7d9853514
// More info at http://lab.montera34.com/segregacionescolar/
var width = 960,
height = 690,
padding = 4
//var projection = d3.geoConicConformalSpain()
// .translate([width / 2, height / 2])
// .scale(3500)
// .scale(width / 2 / Math.PI)
// .scale(300)
// .translate([width / 2, height / 2])
// Rectangle size
var rectSize = d3.scaleSqrt()
.range([5, 44])
// Font size scale
var fontSize = d3.scaleLinear()
.range([8, 24])
// Position in x line
// set the ranges
var x = d3.scaleLinear()
.domain([0, 18])
.range([30,300])
// Party
var color = d3.scaleQuantile()
.domain([0, 18])
.range(['#F2FDFC','#C0D7ED','#A2B3E1','#848FD5','#656BC9','#4747BD','#2924B2'])
//console.log(color(0));
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
var tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
var cartograma = svg.append('g').attr('id','cartograma');
var escala = svg.append('g').attr('id','escala');
d3.json("ratios_barrios_simply_topo.json", function(err, data) {
// move projection inside json to be able to get data
var projection = d3.geoMercator()
.fitSize([width, height], topojson.feature(data, data.objects.barrios));
var path = d3.geoPath()
.projection(projection);
// 1. Features we are painting
barrio = topojson.feature(data, data.objects.barrios).features
// Rect size scale
rectSize.domain(d3.extent(barrio, function(d) {return d.properties.Domicilis }))
// 2. Create on each feature the centroid and the positions
barrio.forEach(function(d) {
d.pos = projection(d3.geoCentroid(d))
d.x = d.pos[0]
d.y = d.pos[1]
d.area = rectSize(d.properties.Domicilis) / 0.7// How we scale
})
// Font size scale
fontSize.domain(d3.extent(barrio, function(d) {return d.area }))
// 3. Collide force
var simulation = d3.forceSimulation(barrio)
.force("x", d3.forceX(function(d) { return d.pos[0] }).strength(.1))
.force("y", d3.forceY(function(d) { return d.pos[1] }).strength(.1))
.force("collide", collide)
// 4. Number of simulations
for (var i = 0; i < 120; ++i) simulation.tick()
// 5. Paint the cartogram
var rect = cartograma.selectAll("g")
.data(barrio)
.enter()
.append("g")
.attr("class", function(d) { return "barrio " + d.properties.BAR_DS_O })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")" })
.on("mousemove", showTooltip) // AÑADIR EVENTO SHOW TOOLTIP
.on("mouseout", hideTooltip) // OCULTAR TOOLTIP
rect.append("rect")
.each(function(d) {
d3.select(this)
.attr("width", d.area)
.attr("height", d.area)
.attr("x", -d.area / 2)
.attr("y", -d.area / 2)
.attr("fill", function(d) {
if ( d.properties.ratio2019_listings == null) {
return "#CCC";
} else {
return color(d.properties.ratio2019_listings)
}
})
.attr("stroke-width", "0.5px")
.attr("stroke", "#aaa")
.attr("rx", 1)
})
rect.append("text")
.each(function(d) {
d3.select(this)
.attr("text-anchor", "middle")
.attr("dy", 0)
.text( function(d) {
var punto = (d.properties.N_Barri.length > 5)? "." : "";
return (d.properties.Domicilis > 5000)? d.properties.N_Barri.substring(0,5) + punto : "";
})
.style("fill", function(d) {
return (d.properties.ratio2019_listings > 15)? "#FFFFFF": "#000000";
})
.style("font-size", "13px")
.style("font-family", "Roboto Condensed");
})
rect.append("text")
.each(function(d) {
d3.select(this)
.attr("text-anchor", "middle")
.attr("dy", 11)
.text( function(d) {
return (d.properties.Domicilis > 5000)? d.properties.ratio2019_listings : "";
})
.style("fill", function(d) {
return (d.properties.ratio2019_listings > 15)? "#FFFFFF": "#000000";
})
.style("font-size", "8px")
.style("font-family", "Roboto Condensed")
})
function showTooltip(d) {
// Fill the tooltip
tooltip.html("<div class='table-responsive'><strong>" + d.properties.N_Barri + "</strong> (" +d.properties.N_Distri + ")</div>" +
"<table class='table table-condensed table-striped'>" +
"<tr>" +
"<td style='text-align:right'><strong>"+ d.properties.count +"</strong></td><td>anuncios airbnb</td>" +
"</tr>" +
"<tr>" +
"<td style='text-align:right'><strong>"+ d.properties.ratio2019_listings +"</strong></td><td>anuncios / 100 viviviendas</td>" +
"</tr>" +
"<tr>" +
"<td style='text-align:right'><strong>"+ d.properties.Domicilis +"</strong></td><td>viviviendas</td>" +
"</tr>" +
"</table>")
.style("opacity", 1)
tooltip.style("left", (d3.event.pageX - 20) + "px")
tooltip.style("top", (d3.event.pageY + 23) + "px")
}
function hideTooltip(d) {
// Hide tooltip
tooltip.style("opacity", 0)
}
// x scale
svg.append("g")
.attr("transform", "translate(0,155)")
.call(d3.axisBottom(x))
.style("font-family", "Roboto Condensed");
var vutLine = escala.selectAll("g")
.data(barrio)
.enter()
.append("g")
.attr("class", "barrioline")
.append("circle")
.each(function(d) {
d3.select(this)
.attr("r", 5)
.attr("cx", x(d.properties.ratio2019_listings))
.attr("cy", function(d) { return Math.random() * 80 + 70;})
.attr("fill", color(d.properties.ratio2019_listings))
.attr("stroke", "#000000")
//.attr("opacity","0.5")
})
.on("mousemove", showTooltip) // AÑADIR EVENTO SHOW TOOLTIP
.on("mouseout", hideTooltip) // OCULTAR TOOLTIP
escala.append("text")
.attr("y", 10)
.attr("x", 30)
.attr("dy", ".71em")
.attr("font-size","18")
.text("Anuncios por cada 100 viviendas por barrios")
.style("font-family", "Roboto Condensed");
escala.append("text")
.attr("y", 30)
.attr("x", 30)
.attr("dy", ".71em")
.attr("font-size","12")
.text("Anuncios de Airbnb por barrios. Barcelona. Marzo 2019. Datos: InsideAirbnb")
.style("font-family", "Roboto Condensed");
escala.append("text")
.attr("y", 180)
.attr("x", 30)
.attr("dy", ".71em")
.attr("font-size","12")
.text("Anuncios por cada 100 viviendas")
.style("font-family", "Roboto Condensed");
})
// From http://bl.ocks.org/mbostock/4055889
function collide() {
for (var k = 0, iterations = 4, strength = 0.5; k < iterations; ++k) {
for (var i = 0, n = barrio.length; i < n; ++i) {
for (var a = barrio[i], j = i + 1; j < n; ++j) {
var b = barrio[j],
x = a.x + a.vx - b.x - b.vx,
y = a.y + a.vy - b.y - b.vy,
lx = Math.abs(x),
ly = Math.abs(y),
r = a.area/2 + b.area/2 + padding;
if (lx < r && ly < r) {
if (lx > ly) {
lx = (lx - r) * (x < 0 ? -strength : strength);
a.vx -= lx, b.vx += lx;
} else {
ly = (ly - r) * (y < 0 ? -strength : strength);
a.vy -= ly, b.vy += ly;
}
}
}
}
}
}
</script>
</body>
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment