Closing the lines in a ggplot2 radar / spider chart

后端 未结 6 1977
时光取名叫无心
时光取名叫无心 2020-12-16 07:11

I need a flexible way to make radar / spider charts in ggplot2. From solutions I\'ve found on github and the ggplot2 group, I\'ve come this far:

library(ggpl         


        
相关标签:
6条回答
  • 2020-12-16 07:37

    Thank you guys for the help but it did not cover all of my needs. I used two series of data to be compared so I took the subset of mtcars for Mazda:

    1. nobody mentioned about order of the x variable and ggplot2 sorts this variable for the plot but does not sort the data and it made my chart wrong at the first attempt. Apply sorting function for me it was dplyr::arrange(plot.data, x.variable.name)

    2. I needed to annotate the chart with values and ggplot2::annotate() works fine but it was not included in the recent answers

    3. the above code did not work fine for my data until adding ggplot2::geom_line

    Finally this code chunk did my chart:

    scaled <- as.data.frame(lapply(mtcars, ggplot2:::rescale01))
    scaled$model <- rownames(mtcars)
    mtcarsm <- scaled %>%
      filter(grepl('Mazda', model)) %>% 
      gather(variable, value, mpg:carb) %>% 
      arrange(variable)
    
    
    ggplot(mtcarsm, aes(x = variable, y = value)) + 
      geom_polygon(aes(group = model, color = model), fill = NA, size = 1) +
      geom_line(aes(group = model, color = model), size = 1) + 
      annotate("text", x = mtcarsm$variable, y = (mtcarsm$value + 0.05), label = round(mtcarsm$value, 2), size = 3) +
      theme(strip.text.x = element_text(size = rel(0.8)),
            axis.text.x = element_text(size = rel(1.2)),
            axis.ticks.y = element_blank(),
            axis.text.y = element_blank()) +
      xlab("") + ylab("") +
      guides(color = guide_legend()) +
      coord_radar()
    

    Hopefully usefull for somebody

    0 讨论(0)
  • 2020-12-16 07:43

    The codes here seem outdated for ggplot2: 2.0.0

    Try my package zmisc: devtools:install_github("jerryzhujian9/ezmisc")

    After you install it, you will be able to run:

    df = mtcars
    df$model = rownames(mtcars)
    
    ez.radarmap(df, "model", stats="mean", lwd=1, angle=0, fontsize=0.6, facet=T, facetfontsize=1, color=id, linetype=NULL)
    ez.radarmap(df, "model", stats="none", lwd=1, angle=0, fontsize=1.5, facet=F, facetfontsize=1, color=id, linetype=NULL)
    

    if you are curious about what's inside, see my codes at github:

    The main codes were adapted from http://www.cmap.polytechnique.fr/~lepennec/R/Radar/RadarAndParallelPlots.html

    0 讨论(0)
  • 2020-12-16 07:51

    Sorry, I was beeing stupid. This seems to work:

    library(ggplot2) 
    
    # Define a new coordinate system 
    coord_radar <- function(...) { 
      structure(coord_polar(...), class = c("radar", "polar", "coord")) 
    } 
    is.linear.radar <- function(coord) TRUE 
    
    # rescale all variables to lie between 0 and 1 
    scaled <- as.data.frame(lapply(mtcars, ggplot2:::rescale01))
    
    scaled$model <- rownames(mtcars)    # add model names as a variable 
    
    as.data.frame(melt(scaled,id.vars="model")) -> mtcarsm
    
    
    mtcarsm <- rbind(mtcarsm,subset(mtcarsm,variable == names(scaled)[1]))
    ggplot(mtcarsm, aes(x = variable, y = value)) + 
        geom_path(aes(group = model)) +
        coord_radar() + facet_wrap(~ model,ncol=4) + 
        theme(strip.text.x = element_text(size = rel(0.8)), 
              axis.text.x = element_text(size = rel(0.8))) 
    
    0 讨论(0)
  • 2020-12-16 07:52
    • solution key factor
      1. add duplicated mpg row after melt by rbind
      2. inherit CoordPolar on ggproto
      3. set is_linear = function() TRUE on ggproto

    especially is_linear = function() TRUE is important,
    since if not you will get plot like this...

    with is_linear = function() TRUE settings you can get,

    library(dplyr)
    library(data.table)
    library(ggplot2)
    
    rm(list=ls())
    
    scale_zero_to_one <- 
      function(x) {
        r <- range(x, na.rm = TRUE)
        min <- r[1]
        max <- r[2]
        (x - min) / (max - min)
      }
    
    scaled.data <-
      mtcars %>%
      lapply(scale_zero_to_one) %>%
      as.data.frame %>%
      mutate(car.name=rownames(mtcars)) 
    
    plot.data <-
      scaled.data %>%
      melt(id.vars='car.name') %>%
      rbind(subset(., variable == names(scaled.data)[1]))
    
    # create new coord : inherit coord_polar
    coord_radar <- 
      function(theta='x', start=0, direction=1){
        # input parameter sanity check
        match.arg(theta, c('x','y'))
    
        ggproto(
          NULL, CoordPolar, 
          theta=theta, r=ifelse(theta=='x','y','x'),
          start=start, direction=sign(direction),
          is_linear=function() TRUE)
      }
    
    plot.data %>%
      ggplot(aes(x=variable, y=value, group=car.name, colour=car.name)) + 
      geom_path() +
      geom_point(size=rel(0.9)) +
      coord_radar() + 
      facet_wrap(~ car.name, nrow=4) + 
      theme_bw() +
      theme(
        axis.title.y = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank(),
        axis.title.x = element_blank(),
        legend.position = 'none') +
      labs(title = "Cars' Status")
    
    • final result
    0 讨论(0)
  • 2020-12-16 07:58

    Using the new ggproto mechanism available in ggplot2 2.0.0, coord_radar can be defined as:

    coord_radar <- function (theta = "x", start = 0, direction = 1) 
    {
     theta <- match.arg(theta, c("x", "y"))
     r <- if (theta == "x") 
            "y"
          else "x"
     ggproto("CoordRadar", CoordPolar, theta = theta, r = r, start = start, 
          direction = sign(direction),
          is_linear = function(coord) TRUE)
    }
    

    Not sure if the syntax is perfect but it is working...

    0 讨论(0)
  • 2020-12-16 08:02

    It turns out than geom_polygom still produces a polygon in the polar coordinates so that

    # rescale all variables to lie between 0 and 1
    scaled <- as.data.frame(lapply(mtcars, ggplot2:::rescale01))
    scaled$model <- rownames(mtcars)    # add model names as a variable
    # melt the dataframe
    mtcarsm <- reshape2::melt(scaled)
    # plot it as using the polygon geometry in the polar coordinates
    ggplot(mtcarsm, aes(x = variable, y = value)) +
    geom_polygon(aes(group = model), color = "black", fill = NA, size = 1) +
    coord_polar() + facet_wrap( ~ model) +
    theme(strip.text.x = element_text(size = rel(0.8)),
        axis.text.x = element_text(size = rel(0.8)),
        axis.ticks.y = element_blank(),
        axis.text.y = element_blank()) +
    xlab("") + ylab("")
    

    works perfectly...

    0 讨论(0)
提交回复
热议问题