1

I am trying to make an income to expenses sankey diagram, preferably with ggsankey or another ggplot extension, because I need the final plot as an image (png). Here is my data:

data <- tibble::tribble(
                 ~Name, ~Annual.Amount,  ~Category,
    "Moira's Earnings",         50000L,   "Income",
   "Johnny's Earnings",        300000L,   "Income",
     "Living Expenses",        140000L, "Expenses",
       "Spent Savings",         25238L, "Expenses",
         "Liabilities",         44280L, "Expenses",
     "Planned Savings",         23000L, "Expenses",
               "Taxes",         98482L, "Expenses",
           "Insurance",         13000L, "Expenses"
  )

I am trying to create something like this diagram, but with only the first 2 flows, all income into one column from where the expenses flow: enter image description here

Ljupcho Naumov
  • 196
  • 2
  • 12

1 Answers1

3
library(tidyverse)
library(networkD3)

data <- tibble::tribble(
  ~Name, ~Annual.Amount,  ~Category,
  "Moira's Earnings",         50000L,   "Income",
  "Johnny's Earnings",        300000L,   "Income",
  "Living Expenses",        140000L, "Expenses",
  "Spent Savings",         25238L, "Expenses",
  "Liabilities",         44280L, "Expenses",
  "Planned Savings",         23000L, "Expenses",
  "Taxes",         98482L, "Expenses",
  "Insurance",         13000L, "Expenses"
)

Nodes = tibble(
  Name = c(data$Name, "Budget") %>% unique()
) %>% as.data.frame()


df = data %>% filter(Category=="Income") %>%
  select(-Category) %>%
  rename(Source = Name) %>%
  mutate(Target = "Budget") %>%
  bind_rows(
    data %>%
      filter(Category=="Expenses") %>%
      select(-Category) %>%
      rename(Target = Name) %>%
      mutate(Source = "Budget")
  ) %>% mutate(
  IDSource = match(Source, Nodes$Name)-1,
  IDTarget = match(Target, Nodes$Name)-1
) %>% as.data.frame()

sankeyNetwork(Links = df, Nodes = Nodes,
              Source = "IDSource", Target = "IDTarget",
              Value = "Annual.Amount", NodeID = "Name",
              sinksRight=FALSE, fontSize = 16)

enter image description here

Small update

library(webshot)
webshot::install_phantomjs()
sankeyNetwork(Links = df, Nodes = Nodes,
              Source = "IDSource", Target = "IDTarget",
              Value = "Annual.Amount", NodeID = "Name",
              sinksRight=FALSE, fontSize = 16) %>%
  saveNetwork("sn.html")

webshot("sn.html", "sankeyNetwork.png")

enter image description here

Marek Fiołka
  • 4,825
  • 1
  • 5
  • 20
  • Thank you Marek. I started with network3d and dropped it for ggplot alternarives, because I read it was difficult to generate png. I need the final chart as an image. I'm trying now to use the webshot library to convert the html to png. – Ljupcho Naumov Oct 30 '21 at 21:43
  • 1
    Unfortunately I had trouble loading the `ggsankey` package. That's why I did it using the `networkD3` package. – Marek Fiołka Oct 30 '21 at 21:43
  • Yes it is not on CRAN yet. ```devtools::install_github("davidsjoberg/ggsankey")``` – Ljupcho Naumov Oct 30 '21 at 21:45
  • 2
    I'm afraid it will be difficult for now to create exactly the graph you want with the `ggsankey` library. So far, I don't understand how to set the `knot` height in `ggsankey`. It's simple with `networkD3`. There is a `Value` argument that expects an appropriate variable with values proportional to the height of the links (nodes). – Marek Fiołka Oct 30 '21 at 22:33
  • 1
    Hi, thank you for the effort. Yes the library is not optimized for flows defined by the user. Somebody else also had this issue with the same problem - income and expenses: https://github.com/davidsjoberg/ggsankey/issues/14 – Ljupcho Naumov Oct 31 '21 at 12:31