简体   繁体   中英

Plot a line over geom_bar

I am trying to plot a line over my barplot, who shows Import + Export. Can someone please help? Everything works fine until geom_line. I was inspirated to do this by this site https://aledemogr.com/2017/05/29/plots-based-on-un-data-in-r/ , but can't seem to get it right...

library(tidyverse)
library(readxl)

eximp <- read_excel("C:/Users/xxx/Downloads/eximp.xlsx")


mydata <- eximp %>% mutate(Balance=Export+Import) %>% 
  gather(Type,value,-1,-4)
base <- mydata %>%
  filter(Type != "Balance")

balance <- mydata %>%
  filter(Type == "Balance")

ggplot(balance, aes(x = Date, y = value)) +
  geom_bar(data = base, aes(fill = Type), stat = "identity") +
  geom_point(aes(colour = Type)) +
  geom_line(aes(colour = Type, group=1)) +
  labs(x = "", y = "Trade")+
  theme_classic()

.

Error: Aesthetics must be either length 1 or the same as the data (1): colour, x and y

Data:

eximp
# A tibble: 10 x 3
   Date                Export Import
   <dttm>               <dbl>  <dbl>
 1 2020-03-01 00:00:00 1000.   -804.
 2 2020-04-01 00:00:00 1212.  -2011.
 3 2020-05-01 00:00:00  806.  -1504.
 4 2020-06-01 00:00:00  700.   -320.
 5 2020-07-01 00:00:00  689.   -650.
 6 2020-08-01 00:00:00  260.  -1423.
 7 2020-09-01 00:00:00  371.   -512.
 8 2020-10-01 00:00:00  390.   -800.
 9 2020-11-01 00:00:00  235.  -1402.
10 2020-12-01 00:00:00   98.2  -662.



> dput(eximp)
structure(list(Date = structure(c(1583020800, 1585699200, 1588291200, 
1590969600, 1593561600, 1596240000, 1598918400, 1601510400, 1604188800, 
1606780800), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
    Export = c(1000.49219126285, 1211.52108001295, 805.787086089857, 
    699.544263919341, 689.023877568315, 260.324542543, 370.641681212495, 
    390.499682375661, 234.51939579408, 98.1534745), Import = 
c(-803.910230262846, 
    -2011.04895501295, -1504.48058508986, -320.103174919341, 
    -650.005315568315, -1423.04591701548, -511.837273212495, 
    -800.04198337566, -1401.98263179408, -661.847163189375)), row.names = 
c(NA, 
-10L), class = c("tbl_df", "tbl", "data.frame"))

When you are creating your "balance" dataframe, it's looking like it's empty. I don't think you need to split your data frame, but use different aesthetics.

library(tidyverse)

eximp <- structure(list(Date = structure(c(1583020800, 1585699200, 1588291200, 
                                           1590969600, 1593561600, 1596240000, 1598918400, 1601510400, 1604188800, 
                                           1606780800), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
                        Export = c(1000.49219126285, 1211.52108001295, 805.787086089857, 
                                   699.544263919341, 689.023877568315, 260.324542543, 370.641681212495, 
                                   390.499682375661, 234.51939579408, 98.1534745), Import = 
                              c(-803.910230262846, 
                                -2011.04895501295, -1504.48058508986, -320.103174919341, 
                                -650.005315568315, -1423.04591701548, -511.837273212495, 
                                -800.04198337566, -1401.98263179408, -661.847163189375)), row.names = 
                         c(NA, 
                           -10L), class = c("tbl_df", "tbl", "data.frame"))



mydata <- eximp %>% mutate(Balance=Export+Import) %>% 
      gather(Type,value,-1,-4)
# You can plot from here directly

head(arrange(mydata, Date))
# A tibble: 6 x 4
Date                Balance Type    value
<dttm>                <dbl> <chr>   <dbl>
1 2020-03-01 00:00:00    197. Export  1000.
2 2020-03-01 00:00:00    197. Import  -804.
3 2020-04-01 00:00:00   -800. Export  1212.
4 2020-04-01 00:00:00   -800. Import -2011.
5 2020-05-01 00:00:00   -699. Export   806.
6 2020-05-01 00:00:00   -699. Import -1504.

Using the mydata as the source data for everything, we'll plot the value as the y aesthetic for the bars, and the Balance as the aesthetic for the line.

ggplot(mydata, aes(x = Date, y = value)) +
      geom_bar(aes(fill = Type), stat = "identity") +  # could use geom_col and drop the stat
      geom_point(aes(colour = Type)) +
      geom_line(aes(x= Date, y = Balance)) +
      labs(x = "", y = "Trade")+
      theme_classic()

在此处输入图像描述

Looking at the example you are trying to emulate, you probably also want to use Balance as the y aesthetic for the point geometry too. This is how I would approach the figure

mydata %>%
      ggplot(aes( x = Date))+  # Only specifying the common aesthetics
      geom_col(aes(y = value, fill = Type))+   # Using geom_col which defaults to plotting the value rather than count
      geom_line(aes(y = Balance))+  
      geom_point(aes(y= Balance)) +  # so points are on top of line and showing balance
      labs(x = "", y = "Trade")+
      theme_classic()

在此处输入图像描述

This is pretty much as @Brian Fisher's answer but uses the more up-to-date pivot_longer() function and works with one modified dataset.

library(dplyr)
library(tidyr)
library(ggplot2)


mydata <- 
  eximp %>% 
  mutate(Balance = Export+Import) %>% 
  pivot_longer(-Date)


ggplot() +
  geom_col(data = filter(mydata, name != "Balance"), aes(Date, value, fill = name))+
  geom_line(data = filter(mydata, name == "Balance"), aes(Date, value), size = 1) +
  labs(x = NULL,
       y = "Trade",
       fill = "Type")+
  theme_classic()

Created on 2021-03-29 by the reprex package (v1.0.0)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM