The Global Database of Events, Language, and Tone, or GDELT, is “a realtime network diagram and database of global human society for open research”.
The potential for a firehose stream of global data has tantalizing possibilities for research in many fields, one of which being security studies.
The following is a cursory walkthrough of GDELT’s event data. It focuses on a country racked by conflict in recent years: Syria. The immense complexity of the Syrian conflict makes monitoring the dozens of international actors and hundreds (if not thousands) of domestic groups extremely challenging. The lion’s share of attention paid to Syria has been in regards to IS with blips of shifted focus following chemical weapons attacks, while systematic open-source tracking of the other involved parties has been disappointingly minimal.
How does GDELT fare in capturing events and trends of a country in the midst of its sixth year of civil war? With minimal massaging, it does pleasingly well.
Rlibrary(dplyr, quietly = TRUE)
library(bigrquery, quietly = TRUE)
source("~/SyriaR/not_for_git_data/db_vars.R") # project "billing" variable
# requires creating GoogleBQ project and
# creating API OAuth keys
db_connection <- DBI::dbConnect(dbi_driver(),
project = "gdelt-bq",
dataset = "full",
billing = big_query_billing)
DBI::dbListTables(db_connection)
## Auto-refreshing stale OAuth token.
## [1] "crosswalk_geocountrycodetohuman" "events"
## [3] "events_partitioned"
A simple geographic filter can be applied by using a coordinate bounding box.
sy_bounds <- list(min_lat = 32,
min_long = 36,
max_lat = 37,
max_long = 42.5)
The database looks to be accessible through both high-level dplyr verbs and SQL.
syria_db <- db_connection %>%
tbl("events") %>% # extract and convert "events" to an object we can reference
filter(FractionDate > 2017.75, # filter legitimately big data to reasonable size
ActionGeo_Lat >= sy_bounds$min_lat & # filter data by Syria bounding box
ActionGeo_Lat <= sy_bounds$max_lat &
ActionGeo_Long >= sy_bounds$min_long &
ActionGeo_Long <= sy_bounds$max_long)
When inspecting query results, the object looks like a regular tibble, but indicates the data Source and Database.
syria_db
## # Source: lazy query [?? x 58]
## # Database: BigQueryConnection
## GLOBALEVENTID SQLDATE MonthYear Year FractionDate Actor1Code
## <int> <int> <int> <int> <dbl> <chr>
## 1 703942123 20171104 201711 2017 2017.833 SYR
## 2 703840455 20171104 201711 2017 2017.833 CVL
## 3 703816024 20171104 201711 2017 2017.833 USA
## 4 703888646 20171104 201711 2017 2017.833 JUDMED
## 5 703894322 20171104 201711 2017 2017.833 LBNGOV
## 6 703905528 20171104 201711 2017 2017.833 SYR
## 7 703926089 20171104 201711 2017 2017.833 SYRCVL
## 8 703813873 20171104 201711 2017 2017.833 USA
## 9 703822985 20171028 201710 2017 2017.816 IRQGOV
## 10 703876706 20171104 201711 2017 2017.833 SYR
## # ... with more rows, and 52 more variables: Actor1Name <chr>,
## # Actor1CountryCode <chr>, Actor1KnownGroupCode <chr>,
## # Actor1EthnicCode <chr>, Actor1Religion1Code <chr>,
## # Actor1Religion2Code <chr>, Actor1Type1Code <chr>,
## # Actor1Type2Code <chr>, Actor1Type3Code <chr>, Actor2Code <chr>,
## # Actor2Name <chr>, Actor2CountryCode <chr>, Actor2KnownGroupCode <chr>,
## # Actor2EthnicCode <chr>, Actor2Religion1Code <chr>,
## # Actor2Religion2Code <chr>, Actor2Type1Code <chr>,
## # Actor2Type2Code <chr>, Actor2Type3Code <chr>, IsRootEvent <int>,
## # EventCode <chr>, EventBaseCode <chr>, EventRootCode <chr>,
## # QuadClass <int>, GoldsteinScale <dbl>, NumMentions <int>,
## # NumSources <int>, NumArticles <int>, AvgTone <dbl>,
## # Actor1Geo_Type <int>, Actor1Geo_FullName <chr>,
## # Actor1Geo_CountryCode <chr>, Actor1Geo_ADM1Code <chr>,
## # Actor1Geo_Lat <dbl>, Actor1Geo_Long <dbl>, Actor1Geo_FeatureID <chr>,
## # Actor2Geo_Type <int>, Actor2Geo_FullName <chr>,
## # Actor2Geo_CountryCode <chr>, Actor2Geo_ADM1Code <chr>,
## # Actor2Geo_Lat <dbl>, Actor2Geo_Long <dbl>, Actor2Geo_FeatureID <chr>,
## # ActionGeo_Type <int>, ActionGeo_FullName <chr>,
## # ActionGeo_CountryCode <chr>, ActionGeo_ADM1Code <chr>,
## # ActionGeo_Lat <dbl>, ActionGeo_Long <dbl>, ActionGeo_FeatureID <chr>,
## # DATEADDED <int>, SOURCEURL <chr>
The data can then be cleaned and structured in a very straightforward fashion.
The following steps are taken here:
tibbleSQLDATE to Date classActionGeo_FullName into three separate variableslibrary(tidyr, quietly = TRUE)
syria_df <- syria_db %>%
as_data_frame() %>%
mutate(date = as.Date(as.character(SQLDATE),
format = "%Y%m%d", origin = "1970-01-01")) %>%
gather(actor_code_types, code_type, contains("Type")) %>%
separate(ActionGeo_FullName, c("micro_loc", "meso_loc", "macro_loc"),
sep = ",", fill = "left") %>%
inner_join(gdeltr2::get_codes_cameo_events(),
by = c("EventCode" = "idCAMEOEvent",
"EventRootCode" = "idParentCode")) %>%
select(date, # when?
descriptionCAMEOEvent, # what?
ActionGeo_Lat, ActionGeo_Long, # where?
micro_loc, meso_loc, macro_loc, # where's that?
Actor1Name, Actor2Name, # who?
actor_code_types, code_type, # who's that? filterable code
EventCode, EventRootCode, # filterable codes
ActionGeo_FeatureID, # geocoded ID to match exact locations
SOURCEURL) %>% # reference
distinct() %>%
arrange(desc(date))
What do the structured data look like?
library(knitr)
library(kableExtra)
options(knitr.table.format = "html")
syria_df %>%
select(-SOURCEURL) %>%
head() %>%
kable() %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
font_size = 8)
| date | descriptionCAMEOEvent | ActionGeo_Lat | ActionGeo_Long | micro_loc | meso_loc | macro_loc | Actor1Name | Actor2Name | actor_code_types | code_type | EventCode | EventRootCode | ActionGeo_FeatureID |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2017-11-05 | Host a visit | 35 | 38 | NA | NA | Syria | MILITANT | NA | Actor1Type1Code | UAF | 043 | 04 | SY |
| 2017-11-05 | Make a visit | 35 | 38 | NA | NA | Syria | MOSCOW | NA | Actor1Type1Code | NA | 042 | 04 | SY |
| 2017-11-05 | Make pessimistic comment | 35 | 38 | NA | NA | Syria | VANCOUVER | NA | Actor1Type1Code | ELI | 012 | 01 | SY |
| 2017-11-05 | Investigate, not specified below | 35 | 38 | NA | NA | Syria | CRIMINAL | NA | Actor1Type1Code | CRM | 090 | 09 | SY |
| 2017-11-05 | Make statement, not specified below | 35 | 38 | NA | NA | Syria | SAUDI | NA | Actor1Type1Code | NA | 010 | 01 | SY |
| 2017-11-05 | Occupy territory | 35 | 38 | NA | NA | Syria | SAUDI ARABIA | NA | Actor1Type1Code | NA | 192 | 19 | SY |
Taking a glimpse at the data raises questions about how sparse the ActionGeo_FullName variable is. Additionally, the clearly questionable identification of actors in the Actor1Name and Actor2Name variables is concerning. With that in mind, let’s see if events and actor codes can be filtered in a more robust fashion.
Referencing GDELT’s CAMEO Codebook, the following can be selected as best representing non-state armed actors, which should assist in focusing more directly on intrastate conflict.
These filters can be further refined by selecting Verbs 18, 19, and 20, which reference “Assault”, “Fight”, and “Engage in Unconventional Mass Violence” respectively.
opposition_role_codes <- c("INS", # insurgent
"OPP", # opposition
"REB", # rebel
"SEP", # separatist
"UAF", # armed forces
"RAD") # radical
syria_df %>%
filter(EventRootCode >= 18,
code_type %in% opposition_role_codes) %>%
select(-meso_loc, -macro_loc, -SOURCEURL) %>%
distinct() %>%
head() %>%
kable() %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
font_size = 8)
| date | descriptionCAMEOEvent | ActionGeo_Lat | ActionGeo_Long | micro_loc | Actor1Name | Actor2Name | actor_code_types | code_type | EventCode | EventRootCode | ActionGeo_FeatureID |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 2017-11-05 | Use unconventional violence, not specified below | 35.9500 | 39.0167 | Raqqa | TERRORIST | NA | Actor1Type1Code | UAF | 180 | 18 | -2538949 |
| 2017-11-05 | Use conventional military force, not specified below | 35.0000 | 38.0000 | NA | EXTREMIST | MILITARY | Actor1Type1Code | RAD | 190 | 19 | SY |
| 2017-11-05 | Use conventional military force, not specified below | 36.2028 | 37.1586 | Aleppo | OPPOSITION FACTION | RUSSIA | Actor1Type1Code | OPP | 190 | 19 | -2541857 |
| 2017-11-05 | Carry out suicide bombing | 35.0000 | 38.0000 | NA | SUICIDE BOMBER | CIVILIAN | Actor1Type1Code | REB | 1831 | 18 | SY |
| 2017-11-05 | Carry out car bombing | 35.0000 | 38.0000 | NA | TERRORIST | CIVILIAN | Actor1Type1Code | UAF | 1832 | 18 | SY |
| 2017-11-05 | Carry out suicide bombing | 35.0000 | 38.0000 | NA | SUICIDE BOMBER | KIRKUK | Actor1Type1Code | REB | 1831 | 18 | SY |
With the data filtered, what does roughly one month of a civil war look like spatially?
library(ggmap)
sy_map <- ggmap::get_map(location = "Syria",
maptype = "toner-hybrid",
zoom = 7)
plot_data <- syria_df %>%
filter(EventRootCode >= 18,
code_type %in% opposition_role_codes) %>%
mutate(`Event Type` = ifelse(EventRootCode == "18", "Assault",
ifelse(EventRootCode == "19", "Fight",
"Engage in Unconventional Mass Violence")))
sy_map %>%
ggmap(legend = "bottom", extent = "device", darken = c(.4, "white")) +
geom_point(data = plot_data,
size = 3,
aes(ActionGeo_Long, ActionGeo_Lat, color = code_type)) +
coord_equal() +
theme(legend.title = element_blank()) +
labs(caption = "@synaptogenesis_") +
ggtitle(label = "GDELT Event Points: 4 October - 4 November",
subtitle = "Brendan Knapp")
As the capital, Damascus will inevitably enjoy a disproportionate amount of attention, but the cluster does not appear to be directly in Damascus and will need to be investigated.
al-Mayadin, which you may recognize as being the site of the June 2017 Iranian ballistic missile strike, sits on on the Euphrates River. The Euphrates has recently acted as the de facto boundary between the Assad regime’s Syrian Arab Army (SAA) forces to the southwest and U.S.-backed Syrian Democratic Forces (SDF) to the northeast.
By adding another dimension to the data, namely the top-level type of event that GDELT identified, we get a more nuanced picture.
plot_data %<>% filter(EventRootCode >= 18,
code_type %in% opposition_role_codes,
code_type != "SEP", # Not enough points to justify space loss
code_type != "INS") %>% # Not enough points to justify space loss
mutate(`Event Type` = ifelse(EventRootCode == "18", "Assault",
ifelse(EventRootCode == "19", "Fight",
"Engage in Unconventional Mass Violence")))
sy_map %>%
ggmap(extent = "panel",
darken = c(.4, "white")) +
stat_density2d(data = plot_data, aes(ActionGeo_Long, ActionGeo_Lat,
alpha = ..level..,
fill = code_type),
size = 0.5, bins = 5, geom = "polygon") +
coord_equal() +
facet_wrap(~`Event Type`, ncol = 2) +
scale_fill_manual(labels = c("Opposition", "Radical", "Rebel", "Armed Forces"),
values = c(c("#FF7256", "#00BFFF", "#ADFF2F", "#836FFF"))) +
theme(legend.title = element_blank(),
panel.spacing.x = unit(4, "lines"),
legend.position = c(0.75, 0.25),
legend.key.size = unit(1.5, "cm"),
legend.direction = "horizontal",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.title.x = element_blank(),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank()) +
guides(alpha = FALSE) +
labs(caption = "@synaptogenesis_") +
ggtitle(label = "GDELT Event Density: 4 October - 4 November",
subtitle = "Brendan Knapp")
The Radical blue of the “Assault” panel is likely displaying SDF’s capture of Raqqa and their ongoing race with SAA to al-Mayadin, It also appears to capture what is hopefully the homestretch through the remaining IS heartland to the Iraqi border.
We can better review GDELT’s results by referencing more robustly curated data.
load("~/SyriaR/data/occ_polys_df.rda")
source("~/SyriaR/R/hotspots.R")
ggplot() +
geom_polygon(data = occ_polys_df,
aes(x = long, y = lat, fill = Occupier, group = group),
alpha = 0.25, color = "transparent") +
stat_density2d(data = plot_data, aes(ActionGeo_Long, ActionGeo_Lat,
color = code_type),
size = 0.75, bins = 4, inherit.aes = FALSE) +
geom_text(data = hotspots_df, aes(long, lat, label = name, fontface = "bold"),
show.legend = FALSE) +
coord_equal() +
scale_fill_manual(values = c("HTS" = "darkgreen", "IDF" = "blue",
"IS" = "black", "SAA" = "red",
"Other Opp." = "green", "SDF" = "yellow")) +
guides(alpha = FALSE,
color = guide_legend(title = "GDELT Event Code", ncol = 2)) +
theme(legend.position = c(0.75, 0.25),
legend.direction = "horizontal",
legend.background = element_rect(fill = "transparent"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.title.x = element_blank(),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank()) +
labs(caption = "@synaptogenesis_") +
ggtitle(label = "GDELT Event Coding and Real World Data",
subtitle = "Brendan Knapp")
Idlib, Raqqa, and Deir ez-Zour (DeZ) are all conflict hotspots, and GDELT very clearly captures this. As YPG-led SDF and SAA forces continue their press into IS territory, it will be interesting to see if the density around DeZ shifts toward the Iraqi border while the density around Raqqa diminishes.
The region labeled “Generic Syria Coords?” is exactly 35°N 38°E. It is likely referencing Syria as a whole as articles do not seem to reference this remote patch in the desert. While it is not the country’s centroid, I have not developed a more reasonable explanation.
We can clean up the plot by ignoring the 35°N 38°E events.
filtered_plot_data <- plot_data %>%
filter(ActionGeo_Lat != 35 & ActionGeo_Long != 38)
filtered_hotspots <- hotspots_df %>%
mutate(name = stringr::str_replace(name, "Generic Syria Coords\\?", ""))
ggplot() +
geom_polygon(data = occ_polys_df,
aes(x = long, y = lat, fill = Occupier, group = group),
alpha = 0.25, color = "transparent") +
stat_density_2d(data = filtered_plot_data,
aes(ActionGeo_Long, ActionGeo_Lat,
color = code_type),
size = 0.75, bins = 4.1, inherit.aes = FALSE) +
geom_text(data = filtered_hotspots,
aes(long, lat, label = name, fontface = "bold"),
show.legend = FALSE) +
geom_text(data = tiyas_airbase, aes(long, lat, label = name, fontface = "bold"),
show.legend = FALSE) +
coord_equal() +
scale_fill_manual(values = c("HTS" = "darkgreen", "IDF" = "blue",
"IS" = "black", "SAA" = "red",
"Other Opp." = "green", "SDF" = "yellow")) +
guides(alpha = FALSE,
color = guide_legend(title = "GDELT Event Code", ncol = 2)) +
theme(legend.position = c(0.75, 0.25),
legend.direction = "horizontal",
legend.background = element_rect(fill = "transparent"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.title.x = element_blank(),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank()) +
labs(caption = "@synaptogenesis_") +
ggtitle(label = "GDELT Event Coding and Real World Data",
subtitle = "Brendan Knapp")
Hidden in the noise of what were likely general coordinates for Syria is a major military installation that is uncovered with slight tweaking of density binning.
Filtering by coordinates reveals that the density seen was not simply an artifact of references to the whole of Syria, as a desert area roughly 50 miles from downtown Homs is identified. Further investigation reveals that what is being detected is actually Tiyas Military Airbase, or T4 Airbase (the name of the nearby pumping station).
Even if one were not familiar with the bases of the Syrian Arab Armed Forces, GDELT clearly identifies the base and surrounding area. With minor investigation, the installation reveals itself to be quite extensive.
library(leaflet)
library(leaflet.extras)
radar_icon <- awesomeIcons(icon = "fa-feed", iconColor = "red",
markerColor = "gray", library = 'fa')
housing_icon <- awesomeIcons(icon = "fa-home", iconColor = "green",
markerColor = "lightblue", library = 'fa')
fixed_wing_icon <- awesomeIcons(icon = "fa-fighter-jet", iconColor = "black",
markerColor = "darkred", library = 'fa')
pump_station_icon <- awesomeIcons(icon = "fa-industry", iconColor = "black",
markerColor = "white", library = 'fa')
rotary_icon <- awesomeIcons(icon = "fa-spinner", iconColor = "black",
markerColor = "darkred", library = 'fa')
hangar_icon <- awesomeIcons(icon = "fa-low-vision", iconColor = "beige",
markerColor = "green", library = 'fa')
leaflet() %>%
setView(lng = 37.642554, lat = 34.532257, zoom = 14) %>%
addProviderTiles(providers$Esri.WorldImagery,
options = providerTileOptions(maxZoom = 17),
group = "Esri Imagery") %>%
addAwesomeMarkers(data = T4_pump_station, lng = ~long, lat = ~lat,
popup = paste(T4_pump_station$name),
icon = pump_station_icon,
group = "Pump Station") %>%
addAwesomeMarkers(data = T4_housing, lng = ~long, lat = ~lat,
popup = paste(T4_housing$name),
icon = housing_icon,
group = "Housing") %>%
addAwesomeMarkers(data = T4_radars, lng = ~long, lat = ~lat,
popup = paste(T4_radars$name),
icon = radar_icon,
group = "Radars") %>%
addAwesomeMarkers(data = T4_fixed_wing, lng = ~long, lat = ~lat,
popup = paste(T4_fixed_wing$name),
icon = fixed_wing_icon,
group = "Fixed-Wing") %>%
addAwesomeMarkers(data = T4_rotary, lng = ~long, lat = ~lat,
popup = paste(T4_rotary$name),
icon = rotary_icon,
group = "Rotary-Wing") %>%
addAwesomeMarkers(data = T4_hangars, lng = ~long, lat = ~lat,
popup = paste(T4_hangars$name),
icon = hangar_icon,
group = "Hangars") %>%
addLayersControl(overlayGroups = c("Pump Station",
"Housing",
"Radars",
"Fixed-Wing",
"Rotary-Wing",
"Hangars"),
options = layersControlOptions(collapsed = FALSE),
position = "topright") %>%
addMiniMap(zoomLevelFixed = 5,
tiles = providers$Esri.WorldGrayCanvas) %>%
mapview::addMouseCoordinates(style = "basic")
This is not a remotely exhaustive annotation of the imagery, but provides enough evidence to convince anyone unfamiliar with the topic that the location is not insignificant. If one looks north of the highway, there are more sub installations and zooming out will display a perimeter, some of which appears to be mined.
Why exactly did GDELT identify the T4 Airbase? There were numerous articles referencing Russian casualties in the area. They explain the process of the numbering of Russian death certificates and evidence that 131 Russians died in Syria between January and September 2017. Acquaintances of some of the dead have described them as private military contractors, despite Moscow denial of Russian PMCs operating in Syria.
Considering that the data were referencing personnel connected to the base, rather than the base itself, and that the base is of relatively limited size, it is very encouraging to see that GDELT was able to capture its location with little manual investigation.
Interestingly, while first appearing to be Damascus itself, the density around the capital may actually be capturing turmoil in the suburb of Ghouta. Ghouta has been a battleground throughout the conflict and is reported to be occupied by branches of Jaysh al-Islam, Hayyat Tahrir al-Sham (HTS), Faylaq al-Rahman, and others. However, it is probably most recognizable as the target of a sarin attack in August 2013.
The kernel density seen may also be in reference to Jobar. Demonstrating the divide between regime-held Damascus proper and opposition-held and extensively bombed Jobar only takes looking at imagery of the boundary.
damascus_jobar_boundary <- ggmap::get_map(c(36.326248, 33.519928),
maptype = "hybrid",
zoom = 15)
inset_imagery <- ggmap::get_map(c(36.305231, 33.514929),
maptype = "roadmap",
zoom = 13)
inset <- ggplotGrob(ggmap(inset_imagery, extent = "device", padding = 5) +
geom_point(aes(36.326248, 33.519928),
color = "red", size = 3))
ggmap(damascus_jobar_boundary, extent = "device") +
geom_point(aes(36.326248, 33.519928),
color = "red", size = 5) +
coord_cartesian() +
annotation_custom(grob = inset,
xmin = 36.326, xmax = 36.345,
ymin = 33.509, ymax = 33.516)
This hasty assessment of GDELT is rather promising. After sufficiently filtering the data, it did not cause alarm or serious skepticism regarding its accuracy in identifying significant locations. In spite of the media exhaustion regarding the Syrian conflict, and its overwhelming focus on IS, GDELT was still able to paint a tantalizingly accurate picture of the current state of affairs, one which can surely be further refined with future trials in filtering and processing data.
My take away? As with any sort of analysis, meaningful interpretation is almost guaranteed to require familiarity with the topic. With some background knowledge, GDELT may prove itself to be a powerful resource and I look forward to deeper dives in the future.
sessionInfo()sessionInfo()
## R version 3.4.2 (2017-09-28)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 15063)
##
## Matrix products: default
##
## locale:
## [1] LC_COLLATE=English_United States.1252
## [2] LC_CTYPE=English_United States.1252
## [3] LC_MONETARY=English_United States.1252
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United States.1252
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] leaflet.extras_0.2 leaflet_1.1.0 ggmap_2.6.1
## [4] ggplot2_2.2.1 kableExtra_0.5.2 knitr_1.17
## [7] bindrcpp_0.2 tidyr_0.7.1 bigrquery_0.4.1
## [10] dplyr_0.7.4
##
## loaded via a namespace (and not attached):
## [1] colorspace_1.3-2 rjson_0.2.15
## [3] gdalUtils_2.0.1.7 rgdal_1.2-13
## [5] rprojroot_1.2 satellite_1.0.1
## [7] base64enc_0.1-3 urltools_1.6.0
## [9] RApiDatetime_0.0.3 lubridate_1.6.0
## [11] xml2_1.1.1 R.methodsS3_1.7.1
## [13] codetools_0.2-15 extrafont_0.17
## [15] mnormt_1.5-5 trelliscopejs_0.1.9
## [17] rlist_0.4.6.1 jsonlite_1.5
## [19] broom_0.4.2 Rttf2pt1_1.3.4
## [21] anytime_0.3.0 dbplyr_1.1.0
## [23] R.oo_1.21.0 png_0.1-7
## [25] shiny_1.0.5 wordcloud2_0.2.0
## [27] mapproj_1.2-5 readr_1.1.1.9000
## [29] compiler_3.4.2 httr_1.3.1
## [31] backports_1.1.1 mapview_2.1.4
## [33] assertthat_0.2.0 lazyeval_0.2.0
## [35] hrbrthemes_0.1.0 htmltools_0.3.6
## [37] prettyunits_1.0.2 tools_3.4.2
## [39] igraph_1.1.2 gtable_0.2.0
## [41] glue_1.1.1 reshape2_1.4.2
## [43] ggthemes_3.4.0 maps_3.2.0
## [45] Rcpp_0.12.13 raster_2.5-8
## [47] cellranger_1.1.0 nlme_3.1-131
## [49] udunits2_0.13 extrafontdb_1.0
## [51] iterators_1.0.8 crosstalk_1.0.0
## [53] psych_1.7.8 stringr_1.2.0
## [55] proto_1.0.0 rvest_0.3.2.9000
## [57] mime_0.5 devtools_1.13.3
## [59] MASS_7.3-47 zoo_1.8-0
## [61] scales_0.5.0 highcharter_0.5.0.9999
## [63] DistributionUtils_0.5-1 hms_0.3
## [65] parallel_3.4.2 tidyverse_1.1.1
## [67] yaml_2.1.14 quantmod_0.4-11
## [69] curl_3.0 memoise_1.1.0
## [71] geosphere_1.5-5 purrrlyr_0.0.2
## [73] triebeard_0.3.0 hunspell_2.6
## [75] stringi_1.1.5 highr_0.6
## [77] foreach_1.4.3 TTR_0.23-2
## [79] RgoogleMaps_1.4.1 rlang_0.1.2.9000
## [81] pkgconfig_2.0.1 evaluate_0.10.1
## [83] lattice_0.20-35 sf_0.5-4
## [85] purrr_0.2.3 bindr_0.1
## [87] htmlwidgets_0.9 labeling_0.3
## [89] tidyselect_0.2.2 plyr_1.8.4
## [91] magrittr_1.5 R6_2.2.2
## [93] DBI_0.7 haven_1.1.0
## [95] whisker_0.3-2 foreign_0.8-69
## [97] withr_2.0.0 units_0.4-6
## [99] xts_0.10-0 sp_1.2-5
## [101] tibble_1.3.4 modelr_0.1.1
## [103] plotly_4.7.1 rmarkdown_1.6
## [105] jpeg_0.1-8 progress_1.1.2
## [107] grid_3.4.2 readxl_1.0.0
## [109] data.table_1.10.4-2 forcats_0.2.0
## [111] digest_0.6.12 webshot_0.4.2
## [113] xtable_1.8-2 httpuv_1.3.5
## [115] gdeltr2_0.3.11023026 R.utils_2.5.0
## [117] stats4_3.4.2 openssl_0.9.7
## [119] munsell_0.4.3 viridisLite_0.2.0