Hot questions for Using Ggplot2 in ggthemes


I have the following nibble:

#> + ggplot2        Date: 2017-06-23
#> + tibble  1.3.3                R: 3.3.2
#> + tidyr   0.6.3              GUI: X11
#> + readr   1.1.1           Locale: en_US.UTF-8
#> + purrr             TZ: Asia/Tokyo
#> + dplyr   0.7.0           
#> + stringr 1.2.0
#> Conflicts -----------------------------------------------------------------
#> * filter(),  from dplyr, masks stats::filter()
#> * lag(),     from dplyr, masks stats::lag()
tbl <- structure(list(sample = c("Fx", "Vx"), nof_degs = c(6038L, 
3606L)), .Names = c("sample", "nof_degs"), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -2L))

#> # A tibble: 2 x 2
#>   sample nof_degs
#>    <chr>    <int>
#> 1     Fx     6038
#> 2     Vx     3606

With the following code:

ggplot(tbl, aes(x=sample,y=nof_degs)) +
geom_histogram(position=position_dodge(0.01), colour="black", stat="identity", width=0.2) +
  geom_rangeframe() + 
  theme_tufte() +
  theme(axis.ticks.length = unit(7, "pt"))

As shown in the image below:


Let me know if this is close enough:

ggplot(df, aes(x=sample,y=nof_degs)) +
  geom_histogram(position=position_dodge(0.01), colour="black",
                 stat="identity", width=0.8) +
  geom_rangeframe(y=c(0, max(df$nof_degs))) + 
  theme_tufte() +
  theme(axis.ticks.length = unit(5, "pt"))

Another option is with aspect.ratio:

ggplot(df, aes(x=sample,y=nof_degs)) +
  geom_histogram(position=position_dodge(2), colour="black",
                 stat="identity", width = 0.6) +
  geom_rangeframe(y=c(0, max(df$nof_degs))) + 
  theme_tufte() +
  theme(aspect.ratio = 2) +
  theme(axis.ticks.length = unit(5, "pt"))

You can play around with width and aspect.ratio parameters to get a desired plot. For example width = 0.8 and aspect.ratio = 1.5:


I got the following graphs using the code given below:


p <- ggplot(data = mtcars, mapping = aes(x = wt, y = mpg)) + 
     geom_point() +
p + geom_text(mapping = aes(label = rownames(mtcars)))

p + geom_text(mapping = aes(label = rownames(mtcars)), family = "Times New Roman")

The font for the geom_text is different from the font of rest of graph. I wonder how can I get same font for geom_text as the font of rest of graph.


R version 3.6.0 (2019-04-26)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 18.04.2 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/atlas/
LAPACK: /usr/lib/x86_64-linux-gnu/atlas/

 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] ggthemes_4.2.0 ggplot2_3.1.1 

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.1       rstudioapi_0.10  magrittr_1.5     tidyselect_0.2.5
 [5] munsell_0.5.0    colorspace_1.4-1 R6_2.4.0         rlang_0.3.4.9003
 [9] stringr_1.4.0    plyr_1.8.4       dplyr_0.8.1      tools_3.6.0     
[13] grid_3.6.0       gtable_0.3.0     withr_2.1.2      lazyeval_0.2.2  
[17] assertthat_0.2.1 tibble_2.1.1     crayon_1.3.4     purrr_0.3.2     
[21] vctrs_0.1.0.9003 zeallot_0.1.0    glue_1.3.1       labeling_0.3    
[25] stringi_1.4.3    compiler_3.6.0   pillar_1.4.0     scales_1.0.0    
[29] backports_1.1.4  pkgconfig_2.0.2 


I am not sure why the font for axis titles is different from the font resulting from geom_text call in your graphs. If I run your code, the fonts are identical.

According to Hadley Wickham's "ggplot2: Elegant Graphics for Data Analysis" (2nd Ed.),

there are only 3 fonts that are guaranteed to work everywhere: "sans", "serif", and "mono" (p. 37)

If you use the following code, I think you will have the same font for axes and geom_text.

# solution for text family
### explicitely setting "family" twice
p <- ggplot(data = mtcars, mapping = aes(x = wt, y = mpg)) + 
  geom_point() +
  theme_igray(base_family = "sans")                                     ## <----

p + geom_text(mapping = aes(label = rownames(mtcars)), family = "sans") ## <----

On my side, this yielded the following graph:

On my side, I can switch on any combination of "sans", "serif", and "mono" for the 2 types of text in the graph.

Please, let me know whether this worked for you.


I created my own theme and now I also want to standardize the color set that is used. I tried to do this with the list solution, provided in the answer of Viktor in this feed:

Associate a color palette with ggplot2 theme

df <- mtcars
uwvPalet <- c("#0078D2","#003282","#C4D600")
theme_uwv <- function(base_size = 22, base_family = "Verdana"){theme_hc(base_size = base_size, base_family = base_family)%+replace%theme(plot.title = element_text(color = rgb(0, 120, 210)), complete = TRUE)}
theme_uwv2 <- list(theme_uwv, scale_color_manual(values = uwvPalet))
ggplot(df, aes(fill = cyl, x = am, y = mpg)) + geom_bar(position = "dodge", stat="identity") + theme_uwv2()

Unfortunately, I get the error:

Error in theme_uwv2() : could not find function "theme_uwv2"

Anyone know how I can fix this?


The following worked for me. theme_uwv2 needed the value returned from theme_uwv() as a list element, not the function itself. Also, you were making a plot where the fill was the dominant colour variable, so I've substituted scale_color_manual() with scale_fill_manual() for demonstration purposes.


df <- mtcars
uwvPalet <- c("#0078D2","#003282","#C4D600")
theme_uwv <- function(base_size = 22, base_family = "Verdana"){
  theme_hc(base_size = base_size, base_family = base_family) %+replace% 
    theme(plot.title = element_text(color = rgb(0, 120, 210, maxColorValue = 255)), 
          complete = TRUE)}
theme_uwv2 <- list(theme_uwv(), scale_fill_manual(values = uwvPalet))

ggplot(df, aes(fill = as.factor(cyl), x = am, y = mpg)) + 
  geom_col(position = "dodge") + 
  ggtitle("test") +


I have a folder of xx .csv timeseries that I want to graph and knit into a clean HTML document. I have a ggplot code that produces the plot that I want using a single timeseries.csv. However, when I try to put the bones of that ggplot code in a function inside of a for loop to run each of the timeseries.csv files through the function I get a some plots with pretty different formatting.

Plot generated with my test ggplot code:

Plot generated with function and for loop:

Changes I'm trying to make to the ugly Rmd plot:

  • Nicely space the x-axis tick marks to whole mins (i.e. "11:14:00", "11:15:00")
  • Connect the data points (solved with subbing geom_line() with geom_path())

Example Rmd Code Below. Please Note that the graphs produced still have nice formatting, I'm not sure how to reproduce this problem sort of posting a 500 row dataframe. I also don't know how to post my rmd code without SO using the formatting commands in this post, so I threw in at 3 of " around my header formatting and at the end of the code to disable it.

Edits and Updates

  • I am getting a persistent error geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?.
  • As suggested by the commenters I tried removing plot() and using the the createChlDiffPlot() directly and replacing plot() with print(). Both produce the same ugly plots as before.
  • Replaced geom_line() with geom_path(). The points are now connected! x-axis cluttering is still there.
  • Time variable is reading as hms num

Many thanks for any help on this!

title: "Chl Filtration"
    theme: yeti
    orientation: rows
  chunk_output_type: console

```{r setup}

#### Example Data
df1 <- data.frame(Time = as_hms(c("11:22:33","11:22:34","11:22:35","11:22:38","11:23:00","11:23:01","11:23:02")),
                  Chl_ug_L_Up = c(0.2,0.1,0.25,-0.2,-0.3,-0.15,0.1),
                  Chl_ug_L_Down = c(0.5,0.4,0.3,0.2,0.1,0,-0.1))
df2 <- data.frame(Time = as_hms(c("08:02:33","08:02:34","08:02:35","08:02:40","08:02:42","08:02:43","08:02:49")),
                  Chl_ug_L_Up = c(-0.2,-0.1,-0.25,0.2,0.3,0.15,-0.1),
                  Chl_ug_L_Down = c(-0.1,0,0.1,0.2,0.3,0.4,0.1))

data_directory = "./" # data folder in R project folder in the real deal
output_directory = "./" # output graph directory in R project folder
write_csv(df1, file.path(data_directory, "SO_example_df1.csv"))
write_csv(df2, file.path(data_directory, "SO_example_df2.csv"))

#### Function to create graphs
createChlDiffPlot = function(aTimeSeriesFile, aFileName, aGraphOutputDirectory, aType)
  aFile_Mod = aTimeSeriesFile %<>%
    select(Time, Chl_ug_L_Up, Chl_ug_L_Down) %>% 
    mutate(Chl_diff = Chl_ug_L_Up - Chl_ug_L_Down)

  one_plot = ggplot(data = aFile_Mod, aes(x = Time, y = Chl_diff)) + # tried adding 'group = 1' in aes to connect points 
    geom_path(size = 1, color = "green") + 
    geom_point(color = "green") +
    theme_gdocs() +
    theme(axis.text.x = element_text(angle = 45, hjust = 1),
          legend.title = element_blank()) +
    labs(x = "", y = "Chl Difference", title = paste0(aFileName, " - ", "Filtration"))

  one_graph_name = paste0(gsub(".csv", "", aFileName), "_", aType, ".pdf")
  ggsave(one_graph_name, one_plot, dpi = 600, width = 7, height = 5, units = "in", device = "pdf", aGraphOutputDirectory)

"``` ### remove the quotes when running example
Plots - After Velocity Adjustment
=====================================" ### remove quotes when running example

```{r, fig.width=13.5, fig.height=5}

all_files_Filtration = list.files(data_directory, pattern = ".csv")

# Loop to plot function
for(file in 1 : length(all_files_Filtration))

  file_name = all_files_Filtration[file]

  one_file = fread(file.path(data_directory, file_name))

  # plot the time series agains
  plot(createChlDiffPlot(one_file, file_name, output_directory, "Velocity_Paired"))

"``` #remove quotes when running example


I finally figured it out.

1) Replacing geom_line() with geom_path() connected the data points when rendered in Rmd.

2) df1$Time was formatted as a difftime object. When I looked at the dataframe in the global environment, Time :hmsnum 11:11:09 .... This made me think my format was ok, but when I ran class(df1$Time) I got [1] "hms" "difftime". With a quick google I found out difftime objects are not quite the same as hms, and my original time was generated by subtracting times. I added a conversion into my mutate function:

    select(Time, Chl_ug_L_Up, Chl_ug_L_Down) %>% 
    mutate(Chl_diff = Chl_ug_L_Up - Chl_ug_L_Down,
           Time = as_hms(Time)) # convert difftime objecct to hms 

ggplot I think has some auto-formatting for hms variables, which is why difftime variable was producing ugly crowded x- axes.