[R-es] RV: Mapa de Calor con Google Maps de fondo

Gilsanz, Jose Luis jluis.gilsanz en eu.jll.com
Lun Oct 26 16:17:18 CET 2015


Hola :

De momento el problema lo he resuelto, en parte, fuera de R, aunque quiero ver a fondo las soluciones que me propones, sobre datos reales, porque tienen una pinta estupenda. ;-)

Como lo que busco es convertir una serie de coordenadas geográficas (puntos) en una “malla” de superficies el usar el método MBA me va bien.
Jugando con la resolución del MBA obtengo una malla más o menos detallada según necesito, luego utilizo un código html (de ahí que diga que lo he resuelto fuera de R) para superponer el png generado a partir de la malla MBA sobre GoogleMaps.
De esta manera obtengo un html dinámico que me permite, entre otras cosas, hacer zoom sobre el mapa de calor.

El código que uso para generar el png es básicamente el que tu indicas al principio:
##Cargamos datos
datos <- readWorksheet(wb,'Datos',colTypes = c('numeric','numeric','numeric','character','character','character','character'),header=TRUE)

##Calculamos aproximacion de superficies segun coordenadas y valores
d <- datos[, c(1,2,3)]
superf <- mba.surf(d, resolucion, resolucion,extend=FALSE)$xyz.est

##Mapa de calor segun valores de Z en (x,y) con leyenda, sin  ejes y sin fondo
png(filename = paste(fichero,sep=''),width = ancho , height = alto, units='px')

##Ajustamos parametros graficos y generamos PNG
x<-par()
par(mar=c(0,0,1.1,0.2))
image.plot(superf, bg= NULL, axes=FALSE, nlevel = niveles,  main = 'Titulo de Pruebas')
par(x)

dev.off()


La aproximación que indicas por densidad, replicando en frecuencias, el valor de la z  también la había sopesado, pero me temo que va a haber una fase 2 de esto en la que necesitare los datos sin transformar, además de que no me parece una solución muy elegante.
Estoy seguro de que hay alguna manera de obtener esto sin tener que “emular” la distribución de densidad a partir de los valores de z, pero esto lo dejo para cuando ande un poquito menos saturado de trabajo.

Muchas gracias por vuestros aportes a todos.

PD: Para los que controlen de javascript y html Google dispone de una API para generar “directamente” mapas de calor, lo podeis ver aquí;
https://developers.google.com/maps/documentation/javascript/heatmaplayer



De: Javier Villacampa González [mailto:javier.villacampa.gonzalez en gmail.com]
Enviado el: sábado, 24 de octubre de 2015 17:34
Para: r-help-es-request en r-project.org<mailto:r-help-es-request en r-project.org>; Gilsanz, Jose Luis
Asunto: Re: Mapa de Calor con Google Maps de fondo

Le he estado dando vueltas a tu problema, yo en su día lo que hacía era crear tantos puntos como había en x e y. Con MBA lo que estas creando es el spline que pasa por las tres coordenas. Si quieres esa aproximación no he encontrado nada para tu problema. Aunque dudo mucho que quieras dibujar un spline, o más bien creo que te da lo mismo dibujar un spline o una densidad.

Para solventar el problema con densidades lo que he hecho yo clásicamente ha sido repetir los puntos (x,y) tantas veces como aparezca z. No es la mejor solución , pero creo que te puede valer y depende lo que quieras representar en el mapa es mejor solución que un spline.
No se si esta solución te valdrá (pruebala y nos cuentas, entiendo que nada es optimo pero algo espero ayudarte):


###################################################
library(dplyr)
library(data.table)
library(jpeg)
library(ggplot2)
library(png)
library(grid)

x_coord <- c(1,2,3,4)
y_coord <- c(1,2,3,4)
value <- c(12,15,19,30)
foo <- data.frame(x_coord, y_coord, value)
library(MBA)
foo=foo[ order(foo[,1], foo[,2],foo[,3]), ]
mba.int<http://mba.int> <- mba.surf(foo, 300, 300, extend=T)$xyz.est
library(fields)
fields::image.plot(mba.int<http://mba.int>)



data <- foo
varInteger_Txt <- "value"
varX_Txt <- "x_coord"
varY_Txt <- "y_coord"

tranform <- function(data, varInteger_Txt, varX_Txt, varY_Txt){
  data <- data[, c(varInteger_Txt, varX_Txt, varY_Txt)]

  Original_values <- nrow(data)
  data <- data[ !duplicated(data[,varX_Txt], data[,varY_Txt]),]
  Final_values <- nrow(data)

  if(Original_values != Final_values){
    warning("You add repited values please check your data set")
  }


  data[,varInteger_Txt ] <- as.integer(data[,varInteger_Txt ])
  Number_of_Repetitions <- data[,varInteger_Txt ] %>% table %>% names %>% as.integer()

  data <-
    data[rep(row.names(data), data[ , varInteger_Txt]), c(varX_Txt, varY_Txt) ]
  return(data)

}

varInteger_Txt <- "value"
varX_Txt <- "x_coord"
varY_Txt <- "y_coord"
foo2 <- tranform(data =  foo %>% data.frame,
                 varX_Txt = "x_coord",
                 varY_Txt = "y_coord",
                 varInteger_Txt = "value")


# S solución uno ----------------------------------------------------------
p <-
  ggplot(foo2, aes(x = x_coord, y = y_coord)) +
  stat_density2d(data= foo2, aes(x= x_coord, y= y_coord, fill = ..level.., alpha = ..level..),
                 size= 10, bins= 50, geom='polygon') +
  geom_point(data= foo2, aes(x= x_coord, y= y_coord),  # coordinates
             color="black", # Color point
             position=position_jitter(w=0.1,h=0.1), # Point plot desviation
             alpha=0.1) + # Point transaparecen

  theme_bw() + # Kind of theme. I strongly recomend theme_bw

  scale_fill_gradient( low = "green",  # Lowest color value
                       high = "red" # High color value

  ) +
  scale_alpha_continuous(range=c(0.0, 001) , guide = FALSE) + # You can play with the range to show a better image. Range belongs to [0, 1] interval
  xlim(0, 4) + # Control lim for x-axe
  ylim(0, 4) # Control lim for y-axe
print(p)
# E solución uno ----------------------------------------------------------



# S solución dos ----------------------------------------------------------
colfunc <- colorRampPalette(c("darkblue", "lightblue", "green", "yellow", "red"))
ggplot(foo2, aes(x = x_coord, y = y_coord)) +
  stat_density2d(geom="tile", aes(fill = ..density.., alpha = ..level..), contour = FALSE) +
  scale_fill_gradientn(colours=colfunc(400)) +
  scale_alpha(guide =F) +
  xlim(c(0, 5)) + ylim(c(0, 5)) +
  # geom_density2d(colour="black", bins=10) +
  geom_point() +
  guides(fill = guide_colorbar(barwidth = 0.5, barheight = 10)) +
  theme(legend.title=element_blank())
# E solución dos ----------------------------------------------------------

# S solucion 3 ------------------------------------------------------------
colfunc <- colorRampPalette(c("darkblue", "lightblue", "green", "yellow", "red"))
ggplot(foo2, aes(x = x_coord, y = y_coord)) +
  annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  stat_binhex(bins = 100, colour = "gray", alpha = 0.5) +
  scale_fill_gradientn(colours=colfunc(400)) +
  scale_alpha(guide =F) +
  xlim(c(0, 5)) + ylim(c(0, 5)) +
  # geom_density2d(colour="black", bins=10) +
  geom_point(data= foo2, aes(x= x_coord, y= y_coord),  # coordinates
             color="black", # Color point
             position=position_jitter(w=0.1,h=0.1), # Point plot desviation
             alpha=0.1) +
  guides(fill = guide_colorbar(barwidth = 0.5, barheight = 10)) +
  theme(legend.title=element_blank())

colfunc <- colorRampPalette(c("darkblue", "lightblue", "green", "yellow", "red"))
ggplot(foo2, aes(x = x_coord, y = y_coord)) +
  annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  stat_bin2d(bins = 6, colour = "gray", alpha = 0.5) +
  scale_fill_gradientn(colours=colfunc(400)) +
  scale_alpha(guide =F) +
  xlim(c(0, 5)) + ylim(c(0, 5)) +
  # geom_density2d(colour="black", bins=10) +
  geom_point(data= foo2, aes(x= x_coord, y= y_coord),  # coordinates
             color="black", # Color point
             position=position_jitter(w=0.1,h=0.1), # Point plot desviation
             alpha=0.1) +
  guides(fill = guide_colorbar(barwidth = 0.5, barheight = 10)) +
  theme(legend.title=element_blank())
# E solucion 3 ------------------------------------------------------------




> --------- Mensaje reenviado ----------
> From: "Gilsanz, Jose Luis" <jluis.gilsanz en eu.jll.com<mailto:jluis.gilsanz en eu.jll.com>>
> To: "r-help-es en r-project.org<http://project.org>" <r-help-es en r-project.org<http://project.org>>
> Cc:
> Date: Wed, 21 Oct 2015 10:36:41 +0000
> Subject: Re: [R-es] Resumen de R-help-es, Vol 80, Envío 26
> Gracias por la respuesta Carlos pero sigo sin ver el camino.

> Con stat_density2d puedo representar la densidad de los puntos en una zona > > determinada, pero eso no es lo que yo quiero.
> Lo que quiero es mostrar el valor de z (independientemente de que haya mucho > o pocos puntos en la zona)

> El problema lo tengo a la hora de comprender como definir bien el aes para que > el mapa de calor muestre una escala (la escala tim.colors(n = 64)) de los > > > > valores de z y no la cantidad de puntos.
> -----Mensaje original-----
> De: R-help-es [mailto:r-help-es-bounces en r-project.org<mailto:r-help-es-bounces en r-project.org>] En nombre de r-
> help-es-request en r-project.org<mailto:help-es-request en r-project.org>
> Enviado el: martes, 20 de octubre de 2015 22:36
> Para: r-help-es en r-project.org<mailto:r-help-es en r-project.org>
> Asunto: Resumen de R-help-es, Vol 80, Envío 26
>
> Envíe los mensajes para la lista R-help-es a
>       r-help-es en r-project.org<mailto:r-help-es en r-project.org>
>
> Para subscribirse o anular su subscripción a través de la WEB
>       https://stat.ethz.ch/mailman/listinfo/r-help-es
>
> O por correo electrónico, enviando un mensaje con el texto "help" en el
> asunto (subject) o en el cuerpo a:
>       r-help-es-request en r-project.org<mailto:r-help-es-request en r-project.org>
>
> Puede contactar con el responsable de la lista escribiendo a:
>       r-help-es-owner en r-project.org<mailto:r-help-es-owner en r-project.org>
>
> Si responde a algún contenido de este mensaje, por favor, edite la linea del
> asunto (subject) para que el texto sea mas especifico que:
> "Re: Contents of R-help-es digest...". Además, por favor, incluya en la
> respuesta sólo aquellas partes del mensaje a las que está respondiendo.
>
>
> Asuntos del día:
>
>    1. Re: Mapa de Calor con Google Maps de fondo
>       (Carlos J. Gil Bellosta )
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Tue, 20 Oct 2015 22:35:37 +0200
> From: "Carlos J. Gil Bellosta " <cgb en datanalytics.com<mailto:cgb en datanalytics.com>>
> To: "Gilsanz, Jose Luis" <jluis.gilsanz en eu.jll.com<mailto:jluis.gilsanz en eu.jll.com>>
> Cc: "r-help-es en r-project.org<mailto:r-help-es en r-project.org>" <r-help-es en r-project.org<mailto:r-help-es en r-project.org>>
> Subject: Re: [R-es] Mapa de Calor con Google Maps de fondo
> Message-ID:
>       <CADg83eefbuPD7bkSX08toLi62mo--kFGxWEVfLP6U28V-
> fvxrw en mail.gmail.com<mailto:fvxrw en mail.gmail.com>>
> Content-Type: text/plain; charset="utf-8"
>
> Hola, ¿qué tal?
>
> Tienes que hacer algo así como
>
> ggmap(mapa) + stat_density2d([...])
>
> Tienes ejemplos completos en el artículo de Wickham
>
> https://journal.r-project.org/archive/2013-1/kahle-wickham.pdf
>
> Un saludo,
>
> Carlos J. Gil Bellosta
> http://www.datanalytics.com
>
> El 20 de octubre de 2015, 17:39, Gilsanz, Jose Luis < jluis.gilsanz en eu.jll.com<mailto:jluis.gilsanz en eu.jll.com>>
> escribió:
>
> > Hola:
> >
> >
> >
> > Estoy intentando generar un mapa de calor que muestre, dadas unas
> > coordenadas geográficas determinadas, el ?calor? (cuanto mas alto el
> > valor de esta variable mas rojo y cuanto mas bajo mas azul) de una
> > determinada variable.
> >
> >
> >
> > Es decir con unos datos como estos:
> >
> > x                             y                             z
> >
> > -3,716575            40,41743              3.169
> >
> > -3,710735            40,42179              4.134
> >
> > -3,704625            40,40333              2.606
> >
> > -3,703929            40,40363              2.563
> >
> > -3,686431            40,36133              1.452
> >
> > -3,682371            40,35542              1.523
> >
> > -3,675325            40,41986              4.122
> >
> > -3,673758            40,41978              4.098
> >
> > -3,645127            40,42780              2.306
> >
> >
> >
> > Donde el data frame datos contiene:
> >
> > x: Longitud
> >
> > y: Latitud
> >
> > z:  Variable a estudiar
> >
> >
> >
> > lo que quiero es mostrar sobre un fondo de GoogleMaps, otra
> > capa(semitransparente)  con el  Calor de la variable.
> >
> >
> >
> > Para ello primero calculo una aproximación de superficies de mis
> > puntos usando MBA
> >
> >
> >
> > ##Cargamos paquetes
> >
> > library(MBA)
> >
> >
> >
> > ##Calculamos aproximacion de superficies segun coordenadas y valores
> >
> > superf <- mba.surf(datos, 2000, 2000,extend=FALSE)$xyz.est
> >
> >
> >
> > ##Obtenemos la capa con los colores a partir de la aproximación de
> > superficies
> >
> > image.plot(superf,  bg= NULL, nlevel = param$NIVELES)
> >
> >
> >
> >
> >
> > Por otro lado obtengo el mapa de google maps sobre el cual deberia ir
> > esto
> > asi:
> >
> > #Cargamos paquete
> >
> > library(ggmap)
> >
> >
> >
> > ##Centro del mapa
> >
> > center <- c(mean(datos$x), mean(datos$y))
> >
> > ##Zoom
> >
> > zoom <- min(MaxZoom(range(datos$x), range(datos$x)))
> >
> >
> >
> > ##Obtenenmos mapa base
> >
> > mapa <- get_map(center, zoom = 12)
> >
> >
> >
> > Lo que ya no consigo hacer es poner la imagen con los colores sobre el
> > mapa de forma que este correctamente calibrada.
> >
> >
> >
> > Seguro que todo esto se pude hacer de un tiron con ggmap y/o
> > RgoogleMaps pero por mas que miro no veo la manera de meter el objeto
> superf ?dentro?
> > de un mapa.
> >
> >
> >
> > Muchas Gracias
> >
> >
> >
> >
> >
> > TASACIONES HIPOTECARIAS S.A.
> > Registration number: A-28/806222.
> > Registered Office: Pº de la Castellana, 79 - 1ª ; 28046 Madrid
> >
> > This e-mail is for the use of the intended recipient(s) only. If you
> > have received this e-mail in error, please notify the sender
> > immediately and then delete it. If you are not the intended recipient,
> > you must not use, disclose or distribute this e-mail without the author's
> prior permission.
> > We have taken precautions to minimise the risk of transmitting
> > software viruses, but we advise you to carry out your own virus checks
> > on any attachment to this message. We cannot accept liability for any
> > loss or damage caused by software viruses. If you are the intended
> > recipient and you do not wish to receive similar electronic messages
> > from us in future then please respond to the sender to this effect
> >
> > _______________________________________________
> > R-help-es mailing list
> > R-help-es en r-project.org<mailto:R-help-es en r-project.org>
> > https://stat.ethz.ch/mailman/listinfo/r-help-es
> >
> ------------ próxima parte ------------
> Se ha borrado un adjunto en formato HTML...
> URL: <https://stat.ethz.ch/pipermail/r-help-
> es/attachments/20151020/7d4339f9/attachment.html>
> ------------ próxima parte ------------
> A non-text attachment was scrubbed...
> Name: image002.png
> Type: image/png
> Size: 265395 bytes
> Desc: no disponible
> URL: <https://stat.ethz.ch/pipermail/r-help-
> es/attachments/20151020/7d4339f9/attachment.png>
> ------------ próxima parte ------------
> A non-text attachment was scrubbed...
> Name: image001.png
> Type: image/png
> Size: 13312 bytes
> Desc: no disponible
> URL: <https://stat.ethz.ch/pipermail/r-help-
> es/attachments/20151020/7d4339f9/attachment-0001.png>
>
> ------------------------------
>
> Subject: Pié de página del digest
>
> _______________________________________________
> R-help-es mailing list
> R-help-es en r-project.org<mailto:R-help-es en r-project.org>
> https://stat.ethz.ch/mailman/listinfo/r-help-es
>
> ------------------------------
>
> Fin de Resumen de R-help-es, Vol 80, Envío 26
> *********************************************





--
[https://lh6.googleusercontent.com/-OmJSTAIo4J4/UW01N1mJAeI/AAAAAAAAABk/NYyJQ0fT4B4/h120/526620_580124745341874_542437733_n.jpg]

	[[alternative HTML version deleted]]



Más información sobre la lista de distribución R-help-es