-1

The data I have contain four columns: x, y_cnt, y1_rate, y2_rate.

set.seed(123)
x <- seq(1,10)
y_cnt <- rnorm(10, 200, 50)
y1_rate <- runif(10,0,1)
y2_rate <- runif(10,0,1)
df <- data.frame(x, y_cnt, y1_rate, y2_rate)

I need to produce a plot such that x is on the x-axis, both y1_rate and y2_rate are on the main y-axis, and y_cnt on the secondary y-axis.

Here how it looks in Excel:

enter image description here

Update:

This is what I've so far. It seems that the figure below shows y1_rate only.

transf_fact <- max(df$y_cnt)/max(df$y1_rate)

# Plot
ggplot(data = df,
       mapping = aes(x = as.factor(x),
                     y = y_cnt)) +
  geom_col(fill = 'red') +
  geom_line(aes(y = transf_fact * y1_rate), group = 1) + 
  geom_line(aes(y = transf_fact * y2_rate)) +
  scale_y_continuous(sec.axis = sec_axis(trans = ~ . / transf_fact, 
                                         name = "Rate"))+
  labs(x = "X")

enter image description here

user9292
  • 1,125
  • 2
  • 12
  • 25

1 Answers1

1

Here's an approach that adjusts the scaling of the rate variables, then gathers all the series into long form, and then shows the variables with their respective geoms.

transf_fact <- max(df$y_cnt)/max(df$y1_rate)

library(tidyverse) # Using v1.2.1

df %>%
  # Scale any variables with "rate" in their name
  mutate_at(vars(matches("rate")), ~.*transf_fact) %>%
  # Gather into long form; 
  #  one column specifying variable, one column specifying value
  gather(y_var, val, -x) %>%

  # Pipe into ggplot; all layers share x, y, and fill/color columns
  ggplot(aes(x = as.factor(x), y = val, fill = y_var)) +
  # bar chart only uses "y_cnt" data
  geom_col(data = . %>% filter(y_var == "y_cnt")) +
  # lines only use non-"y_cnt" data
  geom_line(data = . %>% filter(y_var != "y_cnt"),
            aes(color = y_var, group = y_var),
            size = 1.2) +
  # Use the "fill" aesthetic to control both colour and fill;
  # geom_col typically uses fill, geom_line uses colour
  scale_fill_discrete(aesthetics = c("colour", "fill")) +
  scale_y_continuous(sec.axis = sec_axis(trans = ~ . / transf_fact, 
                                         name = "Rate")) +
  labs(x = "X")

enter image description here

Jon Spring
  • 55,165
  • 4
  • 35
  • 53
  • I just tried to run your code and got the following error: ``` Error in UseMethod("as.fun_list") : no applicable method for 'as.fun_list' applied to an object of class "formula"```. Do you know what went wrong? – user9292 Aug 29 '19 at 00:48
  • Are you running with the example data or something new? I reloaded R, loaded your example data, and ran my code no problems. I would suggest removing pipes (the `%>%`) and seeing which step is making that error, as it's not obvious to me. – Jon Spring Aug 29 '19 at 03:04