library(sf)
library(googleway)
library(dplyr)
library(tidyr)
library(stringr)
library(leaflet)
Google Places
O Google Places API permite acessar os dados do Google Maps. O pacote googleway
integra estes dados dentro de R
já em formato tidy. Neste post vou mostrar como importar dados desta API com foco no Places, que encontra informações sobre estabelecimentos ou pontos de interesse, em geral. Há diversos outros usos desta API, como de encontrar rotas, estimar a elevação, recuperar fotos do Street View, entre outros. Para uma lista completa veja a documentação do pacote.
API - chave
Para usar o pacote é preciso registrar uma API. Se você não tem uma key é preciso criar uma. Um tutorial do Google está disponível aqui.
::set_key("sua_chave") googleway
Starbucks
Para exemplificar o uso da API vamos começar com um exemplo simples. Via de regra, é preciso definir apenas dois parâmetros para começar a busca:
- Um termo de busca
- Um ponto
No exemplo abaixo buscamos o termo “starbucks” a partir da coordenada do Museu de Arte de São Paulo (MASP).
= c(-23.561462, -46.655937)
ponto
= google_places(
search_sbux search_string = "starbucks",
location = ponto
)
O objeto guarda vários resultados da query.
# Resultados da query em formato data.frame
$results
places# 'token' para continuar a busca
$next_page_token
places# Status da query
$status places
A query de busca encontra apenas 20 resultados (no máximo). Para encontrar mais resultados é preciso fazer uma nova busca, usando $next_page_token
para encontrar mais resultados.
# busca mais resultados para a mesma pesquisa
= google_places(
search_sbux_2 search_string = "starbucks",
location = ponto,
page_token = search_sbux$next_page_token
)# busca mais resultados para a mesma pesquisa
= google_places(
search_sbux_3 search_string = "starbucks",
location = ponto,
page_token = search_sbux_2$next_page_token
)# Agrega todos os resultados encontrados
<- bind_rows(
res $results,
search_sbux$results,
search_sbux_2$results
search_sbux_3 )
Ao todo, a query encontrou 50 resultados que estão agregados no objeto res
acima. A query retorna várias das informações que normalmente se encontram numa busca via Google Maps: a nota média do estabelecimento, algumas fotos, o endereço, a posição geográfica (lat/lng), o tipo do estabelecimento, etc.
Formalmentem, as informações estão estruturadas num “nested” data.frame
, que é um data.frame
comum que possui outros data.frame
ou list
como colunas. Isto pode causar algum estranhamento, mas não é nada demais. Para selecionar uma coluna acaba sendo necessário fazer df$col1$col2
ou usar os comandos tidyr::unnest
.
<- res %>%
subres unnest(cols = "geometry") %>%
unnest(cols = "location") %>%
select(
business_status, name, formatted_address, rating, user_ratings_total, types,
lat, lng
)
<- st_as_sf(subres, coords = c("lng", "lat"), crs = 4326)
subres
# Mapa iterativo simples
leaflet(subres) |>
addTiles() |>
addCircleMarkers(label = ~name) |>
addProviderTiles("CartoDB")
A coluna types
é uma lista que contém cinco strings que categorizam o estabelecimento.
$types[[1]] subres
Os dados do Google Maps não costumam ser 100% limpos. Não é incomum encontrar estabelecimentos fantasmas, ou mal-construídos. Um jeito fácil de encontrar estes casos é filtrar pelo número de reviews ou pelo nome. Na tabela abaixo há dois estabelecimentos suspeitos: o STARBUCKS CO
e o Starbucks Coffee
: ambos têm um baixo número de reviews e têm uma nota muito baixa (2 e 2.1, respectivamente).
|>
subres arrange(user_ratings_total) |>
head(10)
Busca estruturada
Vou montar uma busca simples para retornar todos os Starbucks do Brasil. Seria muito demorado fazer uma busca completa, no país inteiro, então vou usar como ponto de partida os pares de coordenadas que encontrei via webscrape.
A função abaixo procura pelo termo “starbucks” em todos os pontos que forneço. Para simplificar, a função devolve apenas algumas das colunas.
# Function to grap starbucks info
<- function(lat, lng) {
get_starbucks_info
= google_places(
places search_string = "starbucks",
location = c(lat, lng)
)
= c(
sel_cols "name", "formatted_address", "lat", "lng", "rating", "user_ratings_total",
"business_status")
$results %>%
places::unnest("geometry") %>%
tidyr::unnest("location") %>%
tidyr::select(dplyr::all_of(sel_cols))
dplyr
}
O código abaixo roda a função acima em todos os 142 estabelecimentos, encontrados na página oficial do Starbucks Brasil.
# Remove geometry and keep only coordinates
<- starbucks %>%
coords_starbucks st_drop_geometry() %>%
as_tibble() %>%
select(index, name, lat, lng)
= purrr::map2(
starbucks_info $lat,
coords_starbucks$lng,
coords_starbucks
get_starbucks_info
)
<- starbucks_info %>%
dat bind_rows(.id = "search_id") %>%
distinct()
Novamente, é preciso limpar os resultados. Olhando para a coluna de nome vemos que há vários estabelecimentos errados.
unique(dat$name)
[1] "Starbucks - Top Center"
[2] "Starbucks"
[3] "Starbucks Coffee"
[4] "Starbucks Shopping Higienópolis"
[5] "STARBUCKS CO"
[6] "Starbucks Shopping Plaza Sul"
[7] "Starbucks Einstein - Maternidade"
[8] "Starbucks Interlagos"
[9] "Starbucks Grand Plaza Shopping"
[10] "Starbucks Shopping Tamboré"
[11] "STARBUCKS COFFEE"
[12] "Starbucks T3 Desembarque"
[13] "Starbucks - Mogi Shopping"
[14] "Lago Azul Restaurant - North"
[15] "Starbucks Litoral Plaza Shopping"
[16] "Starbucks - Parque Dom Pedro"
[17] "Starbucks Livraria Leitura - Parque Dom Pedro"
[18] "Starbuks"
[19] "Starbucks Ribeirão Shopping"
[20] "Starbucks Coffee - Shopping Mueller"
[21] "Starbucks - Palladium"
[22] "Starbucks (Sala de Embarque) Aeroporto Curitiba Afonso Pena"
[23] "Starbucks Shopping Jockey"
[24] "Starbucks Shopping Curitiba"
[25] "Casa Bauducco"
[26] "Havanna Café Palladium Curitiba"
[27] "Season Coffee & Co."
[28] "Starbucks - Santos Dumont"
[29] "DarkCoffee Centro Rio"
[30] "Starbucks Garten Shopping"
[31] "Starbucks Norte Shopping"
[32] "Starbucks Itaú Power Shopping"
[33] "Starbucks | Beiramar Shopping"
[34] "Starbucks Boulevard Shopping"
[35] "Starbucks Airport Gate 115"
[36] "Starbucks - Barra Shopping Sul"
[37] "Starbucks Portão 8 Aeroporto Internacional de Brasília Lago Sul"
[38] "Caffetteria"
[39] "Black Coffee"
[40] "Duckbill Cookies & Coffee Taguatinga Shopping - Brasília/DF"
[41] "Caffetteria WPS Santa Lúcia"
Para fazer a limpeza, vou manter apenas as unidades ativas com contêm “Starbucks” no seu nome. Além disso, vou parear os dados com a minha base de webscape usando st_nearest_feature(x, y)
. Esta função encontra o ponto mais próximo em y
para cada ponto de x
.
<- dat |>
dat filter(str_detect(name, "Starbucks"), business_status == "OPERATIONAL") |>
arrange(formatted_address)
<- dat %>%
google_data st_as_sf(coords = c("lng", "lat"), crs = 4326)
<- st_nearest_feature(google_data, starbucks)
inds
<- starbucks %>%
metadata slice(inds) %>%
st_drop_geometry() %>%
as_tibble()
<- google_data |>
google_data rename(google_name = name, google_address = formatted_address) |>
bind_cols(metadata)
Mapa
O mapa interativo abaixo mostra todos os Starbucks de São Paulo. A cor de cada círculo representa a sua nota e o tamanho do círculo, o número de avaliações. As unidades no corredor da Av. Paulista, por exemplo, têm notas médias elevadas e grande número de avaliações. Uma das piores unidades parece ser a da Uv. Mackenzie, que tem nota 2,1 e 15 avaliações. Na Zona Leste, a unidade no Shopping Aricanduva também tem nota um pouco inferior, 3,9 com 158 avaliações.
<- filter(google_data, name_muni == "São Paulo")
sp
<- sp |>
sp mutate(
rad = findInterval(user_ratings_total, c(25, 100, 1000, 2500, 5000))*2 + 5
)
<- colorNumeric("RdBu", domain = sp$rating)
pal
<- stringr::str_glue(
labels "<b> {sp$name} </b> <br>
<b> Rating </b>: {sp$rating} <br>
<b> No Ratings </b> {sp$user_ratings_total}"
)
<- lapply(labels, htmltools::HTML)
labels
leaflet(sp) |>
addTiles() |>
addCircleMarkers(
radius = ~rad,
color = ~pal(rating),
label = labels,
stroke = FALSE,
fillOpacity = 0.5
|>
) addLegend(pal = pal, values = ~rating) |>
addProviderTiles("CartoDB")
Melhores Starbucks de São Paulo
Tecnicamente, o Starbucks mais bem avaliado de São Paulo é o Starbucks da Ala Consultório do Hospital Albert Einstein, com nota 4,8. Contudo, considerando as unidades com maior número de avaliações, podemos montar um mapa dos “melhores” Starbucks de São Paulo: as unidades com nota igual ou superior a 4,4 e com mais de 500 avaliações.
De maneira geral, o mapa mostra as unidades dentro do Centro Expandido, no eixo da Paulista e do Itaim Bibi. Nas bordas do Centro Expandido temos quase exclusivamente, unidades dentro de shoppings.
<- sp |>
melhores_starbucks filter(rating >= 4.4 & user_ratings_total > 500)
<- colorNumeric("Blues", domain = melhores_starbucks$rating)
pal
<- stringr::str_glue(
labels "<b> {melhores_starbucks$name} </b> <br>
<b> Rating </b>: {melhores_starbucks$rating} <br>
<b> No Ratings </b> {melhores_starbucks$user_ratings_total}"
)
<- lapply(labels, htmltools::HTML)
labels
leaflet(melhores_starbucks) |>
addTiles() |>
addCircleMarkers(
radius = ~sqrt(user_ratings_total / 10),
color = "#045a8d",
label = labels,
stroke = FALSE,
fillOpacity = 0.5
|>
) addProviderTiles("CartoDB")