La inteligencia locacional es usar datos de ubicación para tomar mejores decisiones. En simples palabras, es entender dónde pasan las cosas y cómo ese lugar afecta lo que sucede. Se usa en negocios, ciudades, seguridad, ventas, entre otras cosas Un ejemplo sería un negocio que analiza dónde viven sus clientes para elegir el mejor lugar para abrir otra sucursal.
Según el video la inteligencia locacional está transformando industrias al aprovechar datos de ubicación con contexto. Con el crecimiento del IoT, sectores como seguros, banca, retail y logística mejoran su eficiencia y retorno de inversión. Además, mercados financieros y plataformas digitales usan estos datos para seguridad, comercio y marketing, que impulsa a grandes empresas como startups en la economía, a nivel local, nacional e internacional.
Por último, el análisis de sentimientos es una herramienta muy importante en el desarrollo de los negocios y las industrias porque permite a las organizaciones comprender la percepción real de los consumidores o usuarios sobre productos, servicios o marcas. A partir de eso se hace una toma de decisiones estratégicas buscando mejorar la percepción de los mismos usuarios y comprender mejor las tendencias o los aspectos culturales y sociales.
### LOADING REQUIRED LIBRARIES
# data analysis
library(dplyr) # grammar of data manipulation helping to resolve data manipulation difficulties
library(Hmisc) # useful functions for data analysis and high - level graphics
library(foreign) # read data stored by Minitab, SPSS, Stata
library(openxlsx) # open, read, write,and edit xlsx files
library(tidyverse) # collection of R packages designed for data science
# spatial data analysis
library(leaflet.extras) # to provide extra functionality to the leaflet R package
library(sp) # functions for plotting data as maps, spatial selection, methods for retrieving coordinates
library(sf) # encode spatial vector data
library(maps) # geographic maps
library(tmap) # generate thematic maps
library(spdep) # a collection of functions to create spatial weights matrices from polygon contiguities
library(terra) # methods for spatial data analysis
library(leaflet) # interactive maps
library(mapproj) # map projections
library(mapsapi) #
library(spatialreg) # spatial regression models
library(sfdep) # an interface to 'spdep' to integrate with 'sf' objects and the 'tidyverse
library(tidygeocoder) # makes getting data from geocoding services easy
library(mapboxapi) # 'Mapbox' Navigation APIs, including directions, isochrones, and route optimization.
# visualization
library(ggmap) # spatial data visualization
library(rgeoda) # spatial data analysis based on software GeoDa
library(ggplot2) # Grammar of graphics. System for declarative creating graphics
library(corrplot) # provides a visual exploratory tool on correlation matrix
library(RColorBrewer) # offers several color palettes
library(leafsync) # create small multiples of several leaflet web maps
library(htmltools) # tools for HTML generation and output
# others
library(rlang) # collection of frameworks and APIs for programming with R
library(classInt) # methods for choosing univariate class intervals for mapping or other graphic purposes
library(gridExtra) # to arrange and combine plots for easy comparison
library(knitr) # integrates computing and reporting
### Getting access to distance, reviews, and ratings by using Google Maps
library(tm) # a framework for text mining applications
library(wordcloud) # functionality to create pretty word clouds
library(wordcloud2) #
library(googleway) # provides a mechanism to access various Google Maps APIs, including plotting a Google Map from R and overlaying it with shapes and markers, and retrieving data from the places, directions, roads, distances, geocoding, elevation and timezone APIs
library(gmapsdistance) # allows to calculate distances for a database through Google maps
# library(hereR) # geocode and autocomplete addresses or reverse geocode POIs using the Geocoder API
library(osrm) # enables the computation of routes, trips, isochrones and travel distances matrices (travel time and kilometric distance).
### Text Mining
library(tm) # text mining functions
library(syuzhet) # includes four sentiment dictionaries and provides a method for accessing the robust, but computationally expensive, sentiment extraction tool developed in the NLP group at Stanford.
library(SnowballC)
library(wordcloud)
library(wordcloud2)
# library(remotes)
# library(openrouteservice)
# remotes::install_github("GIScience/openrouteservice-r")
Mty <- leaflet() %>%
addTiles() %>%
setView(-100.3349053863702, 25.651831711454633, zoom = 14) %>% ### Mty downtown area
addMarkers(-100.3349053863702, 25.651831711454633, popup = "Monterrey Downtown Area")
Mty
### Map coordinates of Parque Fundidora (Starting Point)
latitude <- 25.651831711454633
longitude <- -100.3349053863702
r <- 8000
### Use the google_places function to make a call to the API and save the results
search_str <- google_places(search_string = 'Tacos', location=c(latitude,longitude), radius=r, key=gmaps_key)
### we can visualize the results (hospitals) got from google_places()
# search_str$results
### The page_token is the way to tell Google to return the next 20 results in the search instead of only the first 20
search_str_add_one <- google_places(search_string = 'Tacos', location=c(latitude,longitude), radius=r, key=gmaps_key, page_token = search_str$next_page_token)
### The page_token is the way to tell Google to return the next 20 results in the search instead of only the first 40
search_str_add_two <- google_places(search_string = 'Tacos', location=c(latitude,longitude), radius=r, key=gmaps_key, page_token = search_str_add_one$next_page_token)
### The data frame will give you a wealth of information about each place, including its address, latitude & longitude coordinates, price level, star rating, number of ratings, categories, and more.
business_name <- c(search_str$results$name, search_str_add_one$results$name, search_str_add_two$results$name)
business_rating <- c(search_str$results$rating, search_str_add_one$results$rating, search_str_add_two$results$rating)
user_ratings_total <- c(search_str$results$user_ratings_total, search_str_add_one$results$user_ratings_total,search_str_add_two$results$user_ratings_total)
place_id <- c(search_str$results$place_id, search_str_add_one$results$place_id, search_str_add_two$results$place_id)
lat <- c(search_str$results$geometry$location$lat, search_str_add_one$results$geometry$location$lat, search_str_add_two$results$geometry$location$lat)
lon <- c(search_str$results$geometry$location$lng, search_str_add_one$results$geometry$location$lng, search_str_add_two$results$geometry$location$lng)
# write.csv(data, "D:\\CD2001C_AD2024\\Power_BI_Data_AD2024\\data_location_intl.csv", row.names=TRUE)
data <- data.frame(business_name,business_rating,user_ratings_total,place_id,lat,lon)
# write.csv(data, "D:\\CD2001C_AD2024\\Power_BI_Data_AD2024\\data_location_intl.csv", row.names=TRUE)
data <- data %>% distinct(business_name, .keep_all = TRUE)
data_top_ratings <- data %>% slice_max(business_rating, n = 10)
data_low_ratings <- data %>% slice_min(business_rating, n = 10)
### Lets visualize the reviews information by coffee shop
top_ratings_plot <- ggplot(data_top_ratings, aes(x=reorder(business_name,business_rating), y=business_rating)) +
geom_bar(stat="identity", fill="lightblue") +
labs(title="Tacos - Top 10 User Ratings", subtitle = "ZMM") +
coord_flip()
top_ratings_plot
low_ratings_plot <- ggplot(data_top_ratings, aes(x=reorder(business_name,user_ratings_total), y=user_ratings_total)) +
geom_bar(stat="identity", fill="lightblue") +
labs(title="Tacos - Top 10 User Reviews", subtitle = "ZMM") +
coord_flip()
low_ratings_plot
top_users_plot <- ggplot(data_low_ratings, aes(x=reorder(business_name,business_rating), y=business_rating)) +
geom_bar(stat="identity", fill="lightpink") +
labs(title="Tacos - Low 10 User Ratings", subtitle = "ZMM") +
coord_flip()
top_users_plot
low_users_plot <- ggplot(data_low_ratings, aes(x=reorder(business_name,user_ratings_total), y=user_ratings_total)) +
geom_bar(stat="identity", fill="lightpink")+
labs(title="Tacos - Low 10 Business Reviews", subtitle = "ZMM") +
coord_flip()
low_users_plot
### Mapa de calor de Top / Lowest Ratings
### Where in ZMM are located the hospitals characterized by the highest ratings?
register_google(key = gmaps_key)
ggmap(get_googlemap(center = c(lon = longitude, lat = latitude), zoom = 13)) +
stat_density2d(data = data_top_ratings, aes(lon, lat, fill = after_stat(level)),
geom = "polygon", alpha = 0.40) +
scale_fill_gradient(low = "green", high = "red", guide = "none") +
labs(x = '', y = '', title = "ZMM - Tacos with the Highest Ratings")
### Where in ZMM are located the Hospitals characterized by the lowest ratings?
ggmap(get_googlemap(center = c(lon = longitude, lat = latitude), zoom = 13)) +
stat_density2d(data = data_low_ratings, aes(lon, lat, fill = after_stat(level)),
geom = "polygon", alpha = 0.42) +
scale_fill_gradient(low = "green", high = "red", guide = "none") +
labs(x = '', y = '', title = "ZMM - Tacos with the Lowest Ratings")
## ℹ <https://maps.googleapis.com/maps/api/staticmap?center=25.651832,-100.334905&zoom=13&size=640x640&scale=2&maptype=terrain&key=xxx-TzTcERfzJ3o>
## Warning: Removed 5 rows containing non-finite outside the scale range
## (`stat_density2d()`).
## request more details about the hospitals using google_place_details()
reviews_top_ratings <- google_place_details(place_id = data_top_ratings$place_id[10], key = gmaps_key)
reviews_low_ratings <- google_place_details(place_id = data_low_ratings$place_id[10], key = gmaps_key)
# reviews_top_ratings$result$reviews$text
# reviews_low_ratings$result$reviews$text
### Generate a vector containing only the text
top_ratings_text <- reviews_top_ratings$result$reviews$text
top_ratings_doc <- Corpus(VectorSource(top_ratings_text))
low_ratings_text <- reviews_low_ratings$result$reviews$text
low_ratings_doc <- Corpus(VectorSource(low_ratings_text))
### Clean the text data
options(warn=-1)
top_ratings_doc <- top_ratings_doc %>% tm_map(removeNumbers) %>% tm_map(removePunctuation) %>% tm_map(stripWhitespace)
top_ratings_doc <- tm_map(top_ratings_doc, content_transformer(tolower))
top_ratings_doc <- tm_map(top_ratings_doc, removeWords, stopwords("english"))
options(warn=-1)
low_ratings_doc <- low_ratings_doc %>% tm_map(removeNumbers) %>% tm_map(removePunctuation) %>% tm_map(stripWhitespace)
low_ratings_doc <- tm_map(low_ratings_doc, content_transformer(tolower))
low_ratings_doc <- tm_map(low_ratings_doc, removeWords, stopwords("english"))
### Lets create a dataframe containing each word in the first column and their frequency in the second column.
options(warn=-1)
dtm_top <- TermDocumentMatrix(top_ratings_doc)
matrix_top <- as.matrix(dtm_top)
words_top <- sort(rowSums(matrix_top),decreasing=TRUE)
words_top_df <- data.frame(word = names(words_top),freq=words_top)
# write.csv(words_top_df, "D:\\CD2001C_AD2024\\Power_BI_Data_AD2024\\wordcloud_a.csv", row.names=TRUE)
options(warn=-1)
dtm_low <- TermDocumentMatrix(low_ratings_doc)
matrix_low <- as.matrix(dtm_low)
words_low <- sort(rowSums(matrix_low),decreasing=TRUE)
words_low_df <- data.frame(word = names(words_low),freq=words_low)
### We can now generate the word cloud according to the top and low ratings reviews.
set.seed(1234) # for reproducibility
### top ratings
# top_raiting_wc<-wordcloud(words = words_top_df$word, freq = words_top_df$freq, min.freq = 1, max.words=200, random.order=FALSE, rot.per=0.35, colors=brewer.pal(8, "Dark2"))
top_rating_wc <- wordcloud2(data = words_top_df, color = "random-dark", size = 0.6, shape = "circle")
top_rating_wc
### low ratings
#low_raiting_wc<-wordcloud(words = words_low_df$word, freq = words_low_df$freq, min.freq = 1, max.words=200, random.order=FALSE, rot.per=0.35, colors=brewer.pal(8, "Dark2"))
low_rating_wc <- wordcloud2(data = words_low_df, color = "random-dark", size = 0.6, shape = "circle")
low_rating_wc
## request more details about the restaurant using google_place_details()
Tacos_reviews <- google_place_details(place_id = data$place_id[20], language = "es", key = "AIzaSyDMtkIEvUpFccyUCGxLgXO-TzTcERfzJ3o")
Tacos_reviews
## $html_attributions
## list()
##
## $result
## $result$address_components
## long_name short_name
## 1 3604 3604
## 2 Avenida Junco de la Vega Av. Junco de la Vega
## 3 Contry Contry
## 4 Monterrey Monterrey
## 5 Nuevo León N.L.
## 6 México MX
## 7 64860 64860
## types
## 1 street_number
## 2 route
## 3 sublocality_level_1, sublocality, political
## 4 locality, political
## 5 administrative_area_level_1, political
## 6 country, political
## 7 postal_code
##
## $result$adr_address
## [1] "<span class=\"street-address\">Av. Junco de la Vega 3604</span>, <span class=\"extended-address\">Contry</span>, <span class=\"postal-code\">64860</span> <span class=\"locality\">Monterrey</span>, <span class=\"region\">N.L.</span>, <span class=\"country-name\">México</span>"
##
## $result$business_status
## [1] "OPERATIONAL"
##
## $result$current_opening_hours
## $result$current_opening_hours$open_now
## [1] TRUE
##
## $result$current_opening_hours$periods
## close.date close.day close.time close.truncated open.date open.day open.time
## 1 2025-03-17 1 0100 NA 2025-03-16 0 1830
## 2 2025-03-18 2 0100 NA 2025-03-17 1 1830
## 3 2025-03-18 2 2359 TRUE 2025-03-18 2 1830
## 4 2025-03-12 3 0100 NA 2025-03-12 3 0000
## 5 2025-03-13 4 0200 NA 2025-03-12 3 1830
## 6 2025-03-14 5 0400 NA 2025-03-13 4 1830
## 7 2025-03-15 6 0400 NA 2025-03-14 5 1830
## 8 2025-03-16 0 0400 NA 2025-03-15 6 1830
## open.truncated
## 1 NA
## 2 NA
## 3 NA
## 4 TRUE
## 5 NA
## 6 NA
## 7 NA
## 8 NA
##
## $result$current_opening_hours$weekday_text
## [1] "lunes: 18:30–1:00" "martes: 18:30–1:00" "miércoles: 18:30–2:00"
## [4] "jueves: 18:30–4:00" "viernes: 18:30–4:00" "sábado: 18:30–4:00"
## [7] "domingo: 18:30–1:00"
##
##
## $result$delivery
## [1] TRUE
##
## $result$dine_in
## [1] TRUE
##
## $result$formatted_address
## [1] "Av. Junco de la Vega 3604, Contry, 64860 Monterrey, N.L., México"
##
## $result$formatted_phone_number
## [1] "81 8365 0385"
##
## $result$geometry
## $result$geometry$location
## $result$geometry$location$lat
## [1] 25.64213
##
## $result$geometry$location$lng
## [1] -100.2777
##
##
## $result$geometry$viewport
## $result$geometry$viewport$northeast
## $result$geometry$viewport$northeast$lat
## [1] 25.64355
##
## $result$geometry$viewport$northeast$lng
## [1] -100.2763
##
##
## $result$geometry$viewport$southwest
## $result$geometry$viewport$southwest$lat
## [1] 25.64085
##
## $result$geometry$viewport$southwest$lng
## [1] -100.279
##
##
##
##
## $result$icon
## [1] "https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png"
##
## $result$icon_background_color
## [1] "#FF9E67"
##
## $result$icon_mask_base_uri
## [1] "https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet"
##
## $result$international_phone_number
## [1] "+52 81 8365 0385"
##
## $result$name
## [1] "Tacos El Güero Contry"
##
## $result$opening_hours
## $result$opening_hours$open_now
## [1] TRUE
##
## $result$opening_hours$periods
## close.day close.time open.day open.time
## 1 1 0100 0 1830
## 2 2 0100 1 1830
## 3 3 0100 2 1830
## 4 4 0200 3 1830
## 5 5 0400 4 1830
## 6 6 0400 5 1830
## 7 0 0400 6 1830
##
## $result$opening_hours$weekday_text
## [1] "lunes: 18:30–1:00" "martes: 18:30–1:00" "miércoles: 18:30–2:00"
## [4] "jueves: 18:30–4:00" "viernes: 18:30–4:00" "sábado: 18:30–4:00"
## [7] "domingo: 18:30–1:00"
##
##
## $result$photos
## height
## 1 2988
## 2 4080
## 3 3000
## 4 3456
## 5 3000
## 6 5712
## 7 4032
## 8 4000
## 9 4032
## 10 3648
## html_attributions
## 1 <a href="https://maps.google.com/maps/contrib/118135001251766519033">Laura Leal</a>
## 2 <a href="https://maps.google.com/maps/contrib/108373607551634913631">Valeria García Rivera</a>
## 3 <a href="https://maps.google.com/maps/contrib/105573470060229901008">Margret Aros</a>
## 4 <a href="https://maps.google.com/maps/contrib/103969771769384328211">Oralia Mayorga</a>
## 5 <a href="https://maps.google.com/maps/contrib/117146532883390183328">Hector Farias</a>
## 6 <a href="https://maps.google.com/maps/contrib/107065803341759280174">Nayeli Cisneros</a>
## 7 <a href="https://maps.google.com/maps/contrib/102827563687459341485">Kassandra Martinez</a>
## 8 <a href="https://maps.google.com/maps/contrib/102598466599280341990">Jorge Herrera</a>
## 9 <a href="https://maps.google.com/maps/contrib/113907715529155913832">Ricardo Velazquez</a>
## 10 <a href="https://maps.google.com/maps/contrib/111662982705021176447">Daniel Arango</a>
## photo_reference
## 1 AUy1YQ3ustXXIW7Dm6pe5LoHz36z2ITbSBAn2K3vb9WQHoMahB5qJ6StKYknN-8LTvZVLCwPmI1kla6qvHQBmnAgKCsOzCDeuQTwLEVdZxn6VOZybeJinlYW9J8rwuOApHzIQ82n0bv11efJdKK7juUdB52TEQZ9sEpx2Tgl0sf_ZWQPs7kfJb0KRkxbmPDAoDjun1ryt9jtVfMEf-g9Hcf1ONirnRLpSNRMqkqzeqsoBSAUySmi2gDKM1oHIc3rDnUJAziEngh20HTlnFdAi8Qh_NMtCvoZsoa1Z53MjKfcht8lflaqz4xrdq3hqb1hgMiqG9eLWWHT1CE
## 2 AUy1YQ1VVWokdvFBLlsGxYTOBbQPFjUtFy2WTOMACPcviKhtMIKpYXphwSHZE67lMyW8Sm_ETSnJ9jIxBeW0Y5FndVWaPSigeCKDk1LkZulYNZPrquMJrWYu1Eha06hTnQbPjub-GUl5rwbIzaVTQtV6EdypiAMTK1avM5xx2jZ9kZoHS29mx1rBR-dphfVJ0aNNcnr7VsExSqMrKPqJqal97or-yEeQ8lp5YNoxbxY8ACnZcsjp8ZOZdYFvyV1vGaVvUE7wmkgvIaXsrxVC8-e9tXduqiG6h0ArwwVYyeThMPcrxgSLdGbkrJiVC3MWAEcheExFd5y2rX0
## 3 AUy1YQ0jNuluRGZSE5rzetUkCD5ybVEZ3TpVSvcePcT8zKR7Qq2n6lCRsvPKIY4daQM9hVhyAAzitZSRLY813AcTwTfeU3ZFhkXdgFB2hvrqQ6YMjEKhNESXPnGP6Y3DVq3zvuY0rQZBoDvP_jJTy7ZBR--3eH_0ZMrnF9Y00UNjaLUUX8m55yNZMcQHtVxDx3oyGNrqArhrj4iF7JBWI3P6ttMJ2nHTbIsI1fpPdDyRLSuNNO8XpNBwTmI37rVTEx6PGh3w-ARNWXdGpzwFWL9P54k1xSNwiBE6iqFqVEPwioX7jA4TcgOb1onqQ41nXQ1onAjTYdWVEws
## 4 AUy1YQ2I3wqcfVmBkyahYnuh6tHoGGu9YPJ7YOH4-BidEpM3pdcYn7ItV0M14-SxwnZy8cQANSJIG98ZqU-q3VLdfwCmasMZZliNqqHPSmW-FTh2NpS-1Bb7y_mYrSRtIqshiWPyKbL3idxYd68cuaktvigquDUuOVHOZp9ouauz6EIINyrupco8CLjoGLHxG6WiB0C76oSirRsLgikZ4VjZbGkJnvwjnZgqBPJplXe8px_c6MPqyKovjcUXjmc_pVx5lN4iH57iElY60CTuiPUaPkIatOs9ohOmSN6Mn3BvBes5NJ-z4-4ICiQyxs-LWVXVc2FTufEFGG8
## 5 AUy1YQ1TvfCgK5PVVnFA1lhfogG_a0_JQqFooqGgIK3kr1b1r5zqaAAq2Acy_5mqZxbI_LHXq5yGYnCXqKe0iaTVTveg3D6s2V7Xy95samMm3MCCTujNf6W7_aLLpG2MMIIS4cElgZCFtQeuDSzXwZCADlEaKG3zs78eSs8cXzkEeKddsJIstS7_PvkaLeph4T0z5hWHH-8j7i42RCHX03eyK3temDD-atWRBBXyECBPcBnMnyBQX7bcSDXiEpxTo5eVuXa3J3I_6phnrfQncA-rGMtOImTROd2gbM-jdS0dpVlYoyMPPeEafMCr65LmHlZaddSlEyGtGWg
## 6 AUy1YQ0Lm_SEKVFIE5bf848Yv47-TcV_fpyvIivN4aIXO5ON-GEQM7b9U7s5YDzEom7Yu3m_SCbaGBJKLJPpX0d70YHbYvuL4IU35lL8R7TOliogsJm3P5YHzDlIycGpmT9nWhV3aITSdPfUaH2L1dko5vVk8dConrR6r01n0R80oW6iwbBINfWWG8mtc2o2dlE5lJrzre78ebuxeYDmWGg0nzu6yIRZyXtJ_4rXjf4TJ-v8S85X8MPlFr-MGaJaLMPErHOuKXU90L4KyiR1SJ6B4-LhAPKnoZ3s5M_-c-jCoqC7jA7qcPSPeIwcoyc2oW2gp11mIF1PWrQ
## 7 AUy1YQ3a82LmA7sCOVzKncimYkOO7rCeRyisxqC-sttgUmlZjZGV3LZ7o9qLft_oTiVEWSsIU78AuucLtxLmw1LHoJmqNsErO9V8zBGB11kQ63wAtprVRRCWPJ0tGVYSif-wfeEVr4y0I5oWKz50vMe4UaavbZvgBjF8tETW-io1X-oDo6HaFqM8VZnBW86A4yosshvi1sGob-L0SDM7NvVc6nw1r1By594CdgSdt5GrQ3Fsk1oWZ_Z2Ag-rx-u8GZAKtWeMCKz_yMztGzbDdaf-cSeEHGXrg9acvbuIJwur60mv0XSvTI0HuKmePFgeB6KO13ZcudAX
## 8 AUy1YQ0ZHUOyYpOKVZHSwFB-0oaYcvFlBKsgYSspohs5rVCXk-LGxg8EUxmlFlBnH7z68zG_rT9Cbyg3f3pUNJbFFyHopeK5VBtqq4KeQkM0CTqdQBzV4pDNyRK9ehMjW2kswbFaxLsOWvYiyE2CuhA3nWHFxBNjiTUIBiENsMMWln0w-lvxn7MGaN7XSXtnCxI9XA4pQz7tF-VN1Y2FAM1qt_nBnrJuUPrHGhcCG3kI3xNH5BBZ5IquvgZeOrJXpwNlc-K_KsZdVP7SYgZ5NNZr_83_ChqNRyC_EMt2cuHQGn4RzyN2rxeLp0FrheWDMZS6l2FXWhKfTtc
## 9 AUy1YQ3r8QUbI2ctkSK26j3FCokvkWVGqbxTU5MgjK_oHowK7m-uo_93eYF5JZad42PAviodxqT3bLPcrmF4Fd5qF9Tqd9iu_Q5coVtPnpB2Quaao06XPFjeUA1UhI7QY58g06zEjCf7FuTkWG-72rjVnYx5tiAWhQjUYxn5pNX09qXzRQChj8P7sXz5RcDGekcpUFO0H2j65zLMj9tphfWOR_YEzotE3FhUorIdEwMkGV345kRNutP2JC2pdgRXu14zCs2M_uinqGv1KLtXTH9nkFSjT9-KRFmRm6FxB6jlzi7Nbfq_zwp9RBtJGCzK9vnrh_q_bkiXaXY
## 10 AUy1YQ0iHWzkkfoQbvnDQxCcpln-fC9sFnZaJiCycHduajFVxQK4wI0sJW6v3XJVhxkkADuj2c_4g83FkNzHn6Hwq6YvbpNwwrHpahp1fkUG_k_I9ca0rSGN3IfuIyDe2p3Cbc6gt_QXQO7sPuxhPwib4sFt6fnryLtQ15v3Sx_0S9kJes0V2WojNn1QoB9vcGqkEWbA_mgNKRi_PRmQFcgFDxjZjj96V5BQ6jEHLStcgS9EXDzQ8Tq5XXhr9AMyD2eYdtYa2HgU-PZ-GnvFbDuhVMajmF6_v_ay7LVV4DOjIDrKDhNwPzXAG5JedXTVSF-BKMdYlw0b6Z8
## width
## 1 5312
## 2 3060
## 3 4000
## 4 3456
## 5 4000
## 6 4284
## 7 3024
## 8 3000
## 9 3024
## 10 2052
##
## $result$place_id
## [1] "ChIJixyP45m_YoYR9OWpv7Nx0lQ"
##
## $result$plus_code
## $result$plus_code$compound_code
## [1] "JPRC+VW Monterrey, N.L., México"
##
## $result$plus_code$global_code
## [1] "75QXJPRC+VW"
##
##
## $result$price_level
## [1] 1
##
## $result$rating
## [1] 4.4
##
## $result$reference
## [1] "ChIJixyP45m_YoYR9OWpv7Nx0lQ"
##
## $result$reservable
## [1] FALSE
##
## $result$reviews
## author_name
## 1 Daniel Arango
## 2 Amor de mis Amores - Mkela -
## 3 Rocío Saldaña
## 4 Ricardo Velazquez
## 5 Ppt Luna
## author_url language
## 1 https://www.google.com/maps/contrib/111662982705021176447/reviews es
## 2 https://www.google.com/maps/contrib/114774638619719355637/reviews es
## 3 https://www.google.com/maps/contrib/111893336206184253082/reviews es
## 4 https://www.google.com/maps/contrib/113907715529155913832/reviews es
## 5 https://www.google.com/maps/contrib/103554757981270800139/reviews es
## original_language
## 1 es
## 2 es
## 3 es
## 4 es
## 5 es
## profile_photo_url
## 1 https://lh3.googleusercontent.com/a-/ALV-UjU1fzEtJeExmWkZd70giGD5FycPL7VbetnwjdxAe5fPBNyhZ8f4wQ=s128-c0x00000000-cc-rp-mo-ba6
## 2 https://lh3.googleusercontent.com/a-/ALV-UjV42BINSTSoY2NCoECZuXX6AkgYHbQ-8zhLl0I9Jg_hysD9pePQeA=s128-c0x00000000-cc-rp-mo-ba5
## 3 https://lh3.googleusercontent.com/a-/ALV-UjV_6A-zWAX6hm6hptXiZwKLoZqCwVIbrFs9nUrPfTRu3ysEQT74=s128-c0x00000000-cc-rp-mo-ba2
## 4 https://lh3.googleusercontent.com/a-/ALV-UjVooiVpTZEuaAioovrs3FYkyi0tRJxhEzk_HeOTZU3bj1bCCddPBA=s128-c0x00000000-cc-rp-mo-ba5
## 5 https://lh3.googleusercontent.com/a-/ALV-UjWZAYQYS8k26i1JMFDRXPtymxLurdETcvEcM_yztMRNr72tDU-L=s128-c0x00000000-cc-rp-mo-ba4
## rating relative_time_description
## 1 5 Hace 1 mes
## 2 5 Hace un año
## 3 1 Hace 9 meses
## 4 4 Hace 7 meses
## 5 5 Hace 2 semanas
## text
## 1 Nada sobresaliente el sabor. Y lo peor del caso es que no aceptan pago con tarjeta o transferencia. ¿Que negocio en esta época no acepta el pago con terminal? Ah pues Tacos el Güero Contry...pongan atención a eso, muchos clientes no manejamos efectivo por la cantidad de robos qué se han sufrido. Hasta las tienditas de abarrotes de las esquinas aceptan pago con tarjeta. Tache con eso. Para no volver.
## 2 Cada platillo de muy buen sabor. Según el que eligió cada uno de nuestra mesa. Hamburguesa, tacos, enchiladas y los cueritos deliciosos. No hubo demora en que se nos sirviera. Muy cordiales las personas que atienden
## 3 ¡PÉSIMO LUGAR! Mi primera vez viniendo aquí y no vuelvo a venir. Desde que ingresamos, no se nos dio la bienvenida, la cual, ustedes dirán no es importante, sin embargo si quedó a desear en todo aspecto. Mi pareja y yo pedimos una hamburguesa especial doble y una campechana. Al cuestionar si la hamburguesa incluía papás a la francesa tal cual muestra la imagen, nos respondieron de mala gana que no ofrecían eso, que a diferencia, podía solicitar de "cuadritos." Nos traen a los minutos las papas, y sabían demasiado a aceite. Después, pasamos más de media hora esperando nuestros platillos, mientras veíamos como los meseros estaban jugando, corriendo y riendo. Para que, al momento de entregar, se me entregara una campechana con la tortilla fría y sin casi nada de carne, así como la hamburguesa envuelta como si hubiese sido para llevar. Al momento de comentarle al mesero que la campechana estaba fría, se retiró y al acercarse con los cocineros, estos de mala gana la calentaron y hasta tocaron el timbre de manera muy agresiva. Nosotros vinimos por las buenas reseñas, sin embargo, para el costo y el ambiente tan desastroso, no recomendamos este lugar.
## 4 Muy ricos los recomiendo, buen servicio, costos justos, en general buena experiencia.
## 5 Excelente lugar por algo siempre tienen lucha gente 👏👏👏\n\nEsos sopes que metieron uff 👌
## time translated
## 1 1738658400 FALSE
## 2 1696440221 FALSE
## 3 1717737753 FALSE
## 4 1722483845 FALSE
## 5 1740587674 FALSE
##
## $result$serves_beer
## [1] FALSE
##
## $result$serves_breakfast
## [1] FALSE
##
## $result$serves_brunch
## [1] FALSE
##
## $result$serves_dinner
## [1] TRUE
##
## $result$serves_lunch
## [1] TRUE
##
## $result$serves_wine
## [1] FALSE
##
## $result$takeout
## [1] TRUE
##
## $result$types
## [1] "restaurant" "food" "point_of_interest"
## [4] "establishment"
##
## $result$url
## [1] "https://maps.google.com/?cid=6112072661123851764"
##
## $result$user_ratings_total
## [1] 2466
##
## $result$utc_offset
## [1] -360
##
## $result$vicinity
## [1] "Avenida Junco de la Vega 3604, Contry, Monterrey"
##
## $result$website
## [1] "https://tacoselguero.mx/"
##
## $result$wheelchair_accessible_entrance
## [1] TRUE
##
##
## $status
## [1] "OK"
### Based on google reviews lets generate a vector containing only the text.
### Corpus is a collection of written texts or a body of writing on a particular subject.
### Cleaning text data.
Tacos_reviews_text <- Tacos_reviews$result$reviews$text
Tacos_reviews_doc <- Corpus(VectorSource(Tacos_reviews_text)) ### Tokenization: Break down the text into individual words or tokens.
Tacos_reviews_doc <- Tacos_reviews_doc %>% tm_map(removeNumbers) %>% tm_map(removePunctuation) %>% tm_map(stripWhitespace)
Tacos_reviews_doc <- tm_map(Tacos_reviews_doc, content_transformer(tolower))
Tacos_reviews_doc <- tm_map(Tacos_reviews_doc, removeWords, stopwords("spanish"))
dtm_Tacos_reviews <- TermDocumentMatrix(Tacos_reviews_doc)
matrix <- as.matrix(dtm_Tacos_reviews)
words <- sort(rowSums(matrix),decreasing=TRUE)
words_df <- data.frame(word = names(words),freq=words)
### Word cloud of 50 hospitals around the starting point (Parque Fundidora)
### words with frequency below min.freq will not be plotted
# wordcloud(words = words_df$word, freq = words_df$freq, min.freq = 5, max.words=200, random.order=FALSE, rot.per=0.35, colors=brewer.pal(8, "Dark2"))
### Word clouds are a visual representation of text data where words are arranged in a cluster. The size of each word reflects its frequency or importance in the data set.
wordcloud2(data = words_df, color = "random-dark", size = 0.5, shape = "circle")
### term matrix is a table containing the frequency of the words.
tdm_sparse <- TermDocumentMatrix(Tacos_reviews_doc, control = list(weighting = weightTfIdf))
tdm_m_sparse <- as.matrix(tdm_sparse)
# lets display frequency of words
term_freq <- rowSums(tdm_m_sparse)
term_freq_sorted <- sort(term_freq, decreasing = TRUE)
tdm_d_sparse <- data.frame(word = names(term_freq_sorted), freq = term_freq_sorted)
# lets display the top 10 most frequent words
head(tdm_d_sparse, 10)
## word freq
## cada cada 0.2579920
## buena buena 0.2579920
## costos costos 0.2579920
## experiencia experiencia 0.2579920
## general general 0.2579920
## justos justos 0.2579920
## recomiendo recomiendo 0.2579920
## ricos ricos 0.2579920
## servicio servicio 0.2579920
## excelente excelente 0.2321928
# we create a word cloud to visualize the most frequent words in the google reviews
# wordcloud(words = tdm_d_sparse$word, freq = tdm_d_sparse$freq, min.freq = 4, max.words = 100, colors = brewer.pal(8, "Dark2"))
wordcloud2(data = tdm_d_sparse, color = "random-dark", size = 0.6, shape = "circle")
# lets convert review column of dataframe to character vector so we can generate sentiment scores
text <- iconv(Tacos_reviews_text)
# Syuzhet method: It is an algorithm used to extract emotions from a sentence. It is a sentiment lexicon that can be used with non-English texts.
syuzhet_vector <- get_sentiment(text, method = "syuzhet") ### get_sentiment() function is used to analyze sentiment.
# See first row of vector
head(syuzhet_vector)
## [1] -0.5 0.0 -1.8 0.4 0.0
# See summary statistics of vector
summary(syuzhet_vector)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -1.80 -0.50 0.00 -0.38 0.00 0.40
# Using the full dataset for sentiment analysis might still
text_sampled <- iconv(Tacos_reviews_text)
syuzhet_vector_sampled <- get_sentiment(text_sampled, method = "syuzhet")
ggplot(data.frame(syuzhet_vector_sampled), aes(x = syuzhet_vector_sampled)) +
geom_histogram(binwidth = 0.1, fill = "blue", color = "black") +
labs(title = "Sentiment Distribution using Syuzhet Method (Sampled Data)", x = "Sentiment Score", y = "Frequency") +
theme_minimal()
nrc_sampled <- get_nrc_sentiment(text_sampled) ### sentiment dictionary to calculate the presence of eight different emotions and their corresponding valence in a text file
nrct_sampled <- data.frame(t(nrc_sampled))
nrcs_sampled <- data.frame(rowSums(nrct_sampled))
nrcs_sampled <- cbind("sentiment" = rownames(nrcs_sampled), nrcs_sampled)
rownames(nrcs_sampled) <- NULL
names(nrcs_sampled)[1] <- "sentiment"
names(nrcs_sampled)[2] <- "frequency"
nrcs_sampled <- nrcs_sampled %>% mutate(percent = frequency/sum(frequency))
nrcs2_sampled <- nrcs_sampled[1:8, ]
colnames(nrcs2_sampled)[1] <- "emotion"
### 1) The bar plot illustrating the distribution of emotions based on sentiment analysis using the NRC lexicon on the google reviews
### 2) Each bar represents a different emotion, and the height of the bar indicates the frequency of that emotion within the text data.
ggplot(nrcs2_sampled, aes(x = reorder(emotion, -frequency), y = frequency, fill = emotion)) +
geom_bar(stat = "identity") +
labs(title = "Emotion Distribution (Sampled Data)", x = "Emotion", y = "Frequency") +
theme_minimal() +
scale_fill_brewer(palette = "Set3")
### 1) The output is a horizontal bar plot illustrating the frequency of the top 10 most popular words in the text data.
### 2) Each bar represents a word, and the length of the bar indicates the frequency of that word in the dataset.
tdm_d_sparse <- tdm_d_sparse[1:10, ]
tdm_d_sparse$word <- reorder(tdm_d_sparse$word, tdm_d_sparse$freq)
ggplot(tdm_d_sparse, aes(x = word, y = freq, fill = word)) +
geom_bar(stat = "identity") +
coord_flip() +
labs(title = "Most Popular Words", x = "Word", y = "Frequency") +
theme_minimal()
# lets create a data frame with sentiment and count
sentiment_df <- data.frame(sentiment = c("Positive", "Negative", "Neutral"), count = c(sum(syuzhet_vector_sampled > 0), sum(syuzhet_vector_sampled < 0), sum(syuzhet_vector_sampled == 0)))
# Create a pie chart
### 1) The output is a pie chart illustrating the distribution of sentiment categories within the dataset.
### 2) Each segment of the pie chart represents a sentiment category (“Positive”, “Negative”, “Neutral”), and the size of each segment corresponds to the count of that sentiment category in the dataset.
ggplot(sentiment_df, aes(x = "", y = count, fill = sentiment)) +
geom_bar(stat = "identity", width = 1) +
coord_polar("y", start = 0) +
labs(title = "Distribución de sentimientos", x = "", y = "") +
theme_minimal() +
scale_fill_brewer(palette = "Set3")
Las taquerías con mejor rating localizadas en un radio de 8 km de Fashion Drive son Tacos Rex, Tacos la pasadita, y Tacos Gaby. Con el peor rating son Tacos los naranjos, Tacos Felix, y Tacos El Güero.
Las taquerias con mejores reviews son Tacos el primo, Taquería Felix y Tacos El Güero. Con los peores reviews son Tacos Felix, Tacos El sabor de la noche y Tacos El Güero.
Según el mapa de calor los tacos con rating más alto están ubicados en el Centro de Monterrey y Zona Tec los de más bajo rating están ubicados en el Mitras Centro y en Independencia.
Entre las palabras más populares son servicio, ricos, recomiendo, y justos. El análisis de sentimientos dio como resultado un sentimiento negativo y neutral iguales en en su mayoría, mientras que positivo fue minoría.
Esri. (2019, agosto 9). Why is location intelligence vital for successful business? [Video]. YouTube. https://www.youtube.com/watch?v=7YAlv93nQiY