plotly not getting geom_text in R / ggplot

2019-06-21 06:36发布

问题:

I have a ggplot that works fine by its own. But when I try to import it in to the plotly api system, the geom_text seems to not work - everything else works. Can anyone help me?

Here's my R version - R version 3.1.2 (2014-10-31) and plotly version - 0.5.23

The data that I am using is in file.csv and looks like:

Province,Community,General Shelters,General Beds,Mens Shelters,Mens Beds,Womens Shelters,Womens Beds,Youth Shelters,Youth Beds,Family Shelters,Family Beds,Total Shelters,Total Beds
New Brunswick,Saint John,0,0,1,35,1,10,0,0,0,0,2,45
Quebec,Montréal,7,114,9,916,12,259,17,197,1,7,45,"1,493"
Quebec,Québec City,3,49,2,102,1,12,2,15,0,0,8,178
Ontario,Toronto,4,250,13,"1,483",10,572,10,416,4,496,41,"3,217"
British Columbia,Vancouver,13,545,7,291,9,238,7,90,2,30,38,"1,194"
British Columbia,Victoria,1,84,1,21,1,25,1,10,1,5,5,145

And here's my full code:

library(ggplot2)
library(zoo)
library(DAAG)
library(mapdata) #for canada map from worldhires database
library(ggmap)
library("plotly") # for plotly

homeless <- function()
{
    allcit <- NULL

    #read csv
    allcittmp <- read.csv("file.csv", sep=",", header=TRUE, colClasses="character")

    #cast data to proper format from character for both data frames
    allcittmp[,1] <- as.character(allcittmp[,1])
    allcittmp[,2] <- as.character(allcittmp[,2])
    allcittmp[,13] <- as.integer(allcittmp[,13])
    allcittmp[,14] <- as.integer(gsub(",","",allcittmp[,14]))

    #get only relevant columns to a new data frame
    allcit <- allcittmp[,c(1,2,13,14)]

    #delete temp data frames for hygiene
    allcittmp <- NULL

    #give better colnames
    colnames(allcit) <- c("prov","community","totshelters","totbeds")

    #concatenate col2,1 to get city, province
    allcit$hcity <- paste(allcit$community,allcit$prov, sep=", ")

    #clean up NA's
    allcit <- na.omit(allcit)

    plmap <- mapcit3(allcit$hcity, allcit$totshelters, allcit$community)

    #the following two lines commented out makes plotly graph
    #everything is fine except that the city names don't show up 
    #py <- plotly()
    #py$ggplotly(plmap)

}

mapcit3 <- function(citiesM, indM, cityname)
{
    #concatenate Canada to city names, to be safe and not pick up similar US cities:
    citiesM <- paste(citiesM,", Canada", sep="")

    freqM <- data.frame(citiesM, indM, cityname) #make dataframe
    lonlat <- geocode(citiesM) #courtesy of google, logitude, lattitude      (gives two var's lon, lat among others)
    citiesC <- cbind(freqM,lonlat) #make new df with long/lat

    mappts2 <- ggplot(citiesC, aes(lon, lat)) +
            borders(regions="canada", name="borders") +
            coord_equal() +
            geom_point(aes(text=cityname, size=indM), colour="red", alpha=1/2, name="cities", label=citiesC$cityname) +
            geom_text(size=2, aes(label=cityname),hjust=0, vjust=0)

    return(mappts2)
}

Attached as map1_without_plotly.png is the version without plotly: And the map with plotly that appears on the plotly site as an API: (yes, the plotly version has more cities, but that is because I stripped down the csv file for stack overflow, so it is easily reproducible)

But basically the plotly version is missing the geom_text (city names) that are in the non-plotly version.

回答1:

Okay, I spotted several shortcomings in the ggplotly conversion. For now, I can suggest the following workaround:

mappts2 <- ggplot(citiesC, aes(x=lon, y=lat)) +
  geom_text(size=10, aes(label=cityname), hjust=0, vjust=0) +
  borders(regions="canada", name="borders") +
  coord_equal() +
  geom_point(aes(text=cityname, size=indM), colour="red", alpha=0.5,
             name="cities", label=citiesC$cityname)
# Take a look
mappts2
# Yes, text is too big in ggplot2

first_version <- py$ggplotly(mappts2, kwargs=list(filename="map_text",
                                                  fileopt="overwrite"))
# Has the labels, misses the markers

my_account <- "marianne2"  # Replace with yours
account_url <- paste0("https://plot.ly/~", my_account, "/")
plot_number <- as.integer(gsub(account_url, "", first_version$response$url))

text_marker <- py$get_figure(my_account, plot_number)

text_marker$data[[1]]$mode
# Says "text"
text_marker$data[[1]]$mode <- "text+markers"
final_version <- py$plotly(text_marker$data,
                           kwargs=list(layout=text_marker$layout,
                                       fileopt="overwrite",
                                       filename="text_markers_mode"))

# Visit final_version$url
  • Size conversion is not perfect, hence my replacement of size=2 with size=10.

  • Unfortunately arguments hjust and vjust are not supported (ignored here).

  • When geom_text and geom_point are used on the same data, ggplotly should set mode="text+markers", which is not currently the case in the R "plotly" package (version 0.5.25).



回答2:

read.csv() has defaults header=TRUE, sep="," so you don't need to specify these.

If you have run allcittmp <- read.csv("file.csv", colClasses="character") you don't need to do the

for (i in c(1, 2)) {
    allcittmp[, i] <- as.character(allcittmp[, i])
}

because that's precisely what colClasses="character" takes care of.

I'm not too fond of the mapcit3() function, which seems to be doing some processing and then some plotting(?!).