2

I have a dataframe composed of IP addresses and corresponding values. I want to visualize these IP addresses (converted to geospatial coordinates) and corresponding values as a bubble map.

The problem is that some of these IP addresses are in the same city. This means that I have multiple bubbles in almost the exact same area, which I'd rather see combined into a single bubble.

So far what I've tried is converting IP addresses -> Lat and Long (ip2coordinates from RDSTK) -> Addresses (using coordinates2politics from RDSTK), and then using CartoDB to convert those city names to coordinates and plotting them there.

I've run coordinates <- lapply(ips$field_1, ip2coordinates), but instead of returning a dataframe it returns a long (and useless) list.

What's an alternative way of doing what I'm trying to do?

Danny David Leybzon
  • 670
  • 1
  • 9
  • 21

1 Answers1

3

No need for the clunky DSTK:

library(iptools)
library(rgeolocate)
library(dplyr)
library(ggplot2)
library(ggalt)

URL <- "http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz"
fil <- basename(URL)
if (!file.exists(fil)) download.file(URL, fil)
R.utils::gunzip(fil, overwrite=TRUE)

ips <- ip_random(10000)
ip_geo <- maxmind(ips, "GeoLite2-City.mmdb", c("country_name", "city_name", "longitude", "latitude"))

count(ip_geo, longitude, latitude, sort=TRUE) %>% 
  filter(!is.na(longitude)) -> for_circles

world_map <- map_data("world")
world_map <- filter(world_map, region != "Antarctica")

gg <- ggplot()
gg <- gg + geom_map(data=world_map, map=world_map,
                    aes(long, lat, map_id=region),
                    colour="#2b2b2b", size=0.15, fill=NA)
gg <- gg + geom_point(data=for_circles, 
                      aes(x=longitude, y=latitude, size=n),
                      shape=21, stroke=0.15, alpha=1.8/2, color="#b2182b")
gg <- gg + scale_size_continuous(trans="log10")
gg <- gg + coord_proj("+proj=wintri")
gg <- gg + ggthemes::theme_map()
gg

enter image description here

Or, bin them:

pts <- hexbin(ip_geo$longitude, ip_geo$latitude, xbins=5)
from_hex <- data_frame(x=pts@xcm, y=pts@ycm, n=pts@count)

gg <- ggplot()
gg <- gg + geom_map(data=world_map, map=world_map,
                    aes(long, lat, map_id=region),
                    colour="#2b2b2b", size=0.15, fill=NA)
gg <- gg + geom_point(data=from_hex, aes(x, y, size=n),
                      shape=21, stroke=0.5, color="#b2182b", fill="#b2182b22")
gg <- gg + scale_size_continuous(trans="sqrt")
gg <- gg + coord_proj("+proj=wintri")
gg <- gg + ggthemes::theme_map()
gg

enter image description here

You could also county by region (country, state, etc) and then plot the circles at the centers of each region.

hrbrmstr
  • 77,368
  • 11
  • 139
  • 205
  • I'll try it out in a couple hours, but it looks perfect! Thanks! – Danny David Leybzon Aug 05 '16 at 16:50
  • @hrbmstr `> ip_geo <- maxmind(ips, "GeoLite2-City.mmdb", c("country_name", "city_name", "longitude", "latitude"))` leads to `Error: not compatible with STRSXP` – Danny David Leybzon Aug 05 '16 at 20:19
  • It is my own IP addresses. They are in fact factors, but I'm having trouble converting them. I tried `i <- sapply(grouped_ips$., is.factor)` `grouped_ips$.[i] <- lapply(grouped_ips$.[i], as.character)` as recommended by http://stackoverflow.com/a/2853231/5472184 but it isn't working – Danny David Leybzon Aug 05 '16 at 20:51
  • And even using a column of chars it returns the same error – Danny David Leybzon Aug 05 '16 at 20:52
  • The output is too long to show up in the RStudio output console and I can't export it with `cat()` – Danny David Leybzon Aug 05 '16 at 21:38
  • There is no possible way that `dput(head(your_vector_of_ip_addresses))` generates large output unless `your_vector_of_ip_addresses` is not a simple character vector. – hrbrmstr Aug 05 '16 at 22:05
  • The vector of IPs is composed of factors. That is exactly the problem. I am attempting to convert them, but the code I tried (`i <- sapply(grouped_ips$., is.factor)` and `grouped_ips$.[i] <- lapply(grouped_ips$.[i], as.character)` failed – Danny David Leybzon Aug 05 '16 at 22:47