NabAra
NabAra

Reputation: 61

Using radar/polar graphs to depict individual datapoints

This is following my previous post: How to measure the area of a polygon in ggplot2?

What I would like now to do is to use the resulting radar charts as data points in a totally separate scatterplot or maybe save the object and use it later on graphs to depict the shape of the actual data.

I have many files and they typically look like this. They range from 1 to many in col number and the fractions are always in descending format. ie #1 always contributes most in any given file.

myfile
01 0.31707317
02 0.12195122
03 0.09756098
04 0.07317073
05 0.07317073
06 0.07317073
07 0.07317073
08 0.07317073
09 0.04878049
10 0.04878049

Here, I would like to plot a radar chart for each of these files individually and just get the shape with no grid around it. ggradar is the closest and the nicest I have found.

ggradar(as.matrix(t(radar)), group.point.size = 2, grid.line.width = 0, grid.max = 1.0, grid.mid = 0, 
    grid.min = 0, axis.line.colour = "white", axis.label.size = 0, grid.label.size = 0, 
    centre.y = 0, background.circle.colour = "white", group.colours = "black", group.line.width = 1) 

radargraph

Now the problem starts when I want to use these shapes as data points.

@brian kindly commented and hinted as to how to approach this.

R::ggplot2::geom_points: how to swap points with pie charts?

Small ggplot2 plots placed on coordinates on a ggmap

Inspired by these comments, I can now save plots as one column along with the filename and keep adding the new files using the same pipeline.

  for (file in file_list){
#eliminate the empty files (they contain only the header)
if (file.size(file) > 420){
  # if the merged dataset does exist, append to it
  if (exists("dfradar")){
    radarfile <-read.table(file, header=TRUE, sep="\t")
    radarfile1 <- as.data.frame(as.numeric(radarfile[,3]))
    rownames(radarfile1) <- c(1:nrow(radarfile))
    dfradar1 <- ggradar(t(radarfile1), group.point.size = 1, grid.line.width = 0, grid.max = 1, grid.mid = 0, 
                        grid.min = 0, axis.line.colour = "white", axis.label.size = 0, grid.label.size = 0, 
                        centre.y = 0, background.circle.colour = "white", group.colours = "black", group.line.width = 0.5) + 
                    theme(legend.position = "none")      
    dfradar1 <- cbind(substring(file,11), dfradar1)
    dfradar <- rbind(dfradar, dfradar1)
  }  
  # if the merged dataset doesn't exist, create it
  if (!exists("dfradar")){
    radarfile <- read.table(file, header=TRUE, sep="\t")
    radarfile1 <- as.data.frame(as.numeric(radarfile[,3]))
    rownames(radarfile1) <- c(1:nrow(radarfile))
    dfradar <- ggradar(t(radarfile1), group.point.size = 1, grid.line.width = 0, grid.max = 1, grid.mid = 0, 
                        grid.min = 0, axis.line.colour = "white", axis.label.size = 0, grid.label.size = 0, 
                        centre.y = 0, background.circle.colour = "white", group.colours = "black", group.line.width = 0.5) + 
                theme(legend.position = "none")
    dfradar <- cbind(substring(file,11), dfradar)
    rm(radarfile)
    rm(radarfile1)
  }
} }

Now when I want to save the grobs, I can't; I get:

"Error in mutate_impl(.data, dots) : Evaluation error: attempt to apply non-function."

or:

"Error in plot_clone(plot) : attempt to apply non-function"

# merge the df with another df containing all other 
# variables that I wanna use in my scatterplot
dfradar_merge <- merge(dfradar, Cases, all=FALSE)
dfradar_merge <-  dfradar_merge %>% mutate(radargrobs = list(annotation_custom(ggplotGrob(radarplots)), 
xmin = as.numeric(Gender), xmax = as.numeric(Gender)*1.2, 
ymin = as.numeric(Age) , ymax = as.numeric(Age)*1.2)))

I think if I can get this part straight and pass the variables as xmin and ymin, I should be able to do what I need...

Any ideas are really appreciated. It has been a headache for me.

Upvotes: 4

Views: 591

Answers (1)

jazzurro
jazzurro

Reputation: 23574

I came up with the following idea. I used the ggradar package to create a graphic. Then, I looked into the data frames staying behind the graphic with ggplot_build(). It seems that there are 13 lists behind the graphic. I needed to investigate which list is the right one containing polygon data. I found that the 6th list is the one you want to extract and save for your future use. Let me show you what I have done.

library(dplyr)
library(ggradar)
library(scales)

# I modified the code from https://github.com/ricardo-bion/ggradar to get a graphic.

mtcars %>%
mutate_all(rescale) %>%
mutate(group = rownames(mtcars)) %>%
slice(5:9) %>%
select(1:4) -> mtcars_radar

g <- ggradar(mtcars_radar)

The code above generates the following graphic. There is something wrong with my computer or something else, and I do not see a complete graphic. But this is not an issue for this question.

enter image description here

Now, we want to get the data staying behind the graphic and look for the right data.

foo <- ggplot_build(g)$data

# This is the 6th list in foo.

 $ :'data.frame':   20 obs. of  8 variables:
  ..$ colour  : chr [1:20] "#FF5A5F" "#FF5A5F" "#FF5A5F" "#FF5A5F" ...
  ..$ x       : num [1:20] 0 0.72 -0.687 0 0 ...
  ..$ y       : num [1:20] 1.111 -0.416 -0.397 1.111 0.611 ...
  ..$ group   : atomic [1:20] 1 1 1 1 2 2 2 2 3 3 ...
  .. ..- attr(*, "n")= int 5
  ..$ PANEL   : Factor w/ 1 level "1": 1 1 1 1 1 1 1 1 1 1 ...
  ..$ size    : num [1:20] 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 ...
  ..$ linetype: num [1:20] 1 1 1 1 1 1 1 1 1 1 ...
  ..$ alpha   : logi [1:20] NA NA NA NA NA NA ...

You want to extract this list as a data frame. The reason why I could spot this list is that I was paying attention to color information (e.g., FF5A5F).

mydf <- foo[[6]]

    colour          x          y group PANEL size linetype alpha
1  #FF5A5F  0.0000000  1.1111111     1     1  1.5        1    NA
2  #FF5A5F  0.7203077 -0.4158698     1     1  1.5        1    NA
3  #FF5A5F -0.6868360 -0.3965450     1     1  1.5        1    NA
4  #FF5A5F  0.0000000  1.1111111     1     1  1.5        1    NA
5  #FFB400  0.0000000  0.6111111     2     1  1.5        1    NA
6  #FFB400  0.4286803 -0.2474987     2     1  1.5        1    NA
7  #FFB400 -0.2584135 -0.1491951     2     1  1.5        1    NA
8  #FFB400  0.0000000  0.6111111     2     1  1.5        1    NA
9  #007A87  0.0000000  1.1111111     3     1  1.5        1    NA
10 #007A87  0.7203077 -0.4158698     3     1  1.5        1    NA
11 #007A87 -0.4726248 -0.2728700     3     1  1.5        1    NA
12 #007A87  0.0000000  1.1111111     3     1  1.5        1    NA
13 #8CE071  0.0000000  0.1111111     4     1  1.5        1    NA
14 #8CE071  0.2467912 -0.1424850     4     1  1.5        1    NA
15 #8CE071 -0.2278119 -0.1315273     4     1  1.5        1    NA
16 #8CE071  0.0000000  0.1111111     4     1  1.5        1    NA
17 #7B0051  0.0000000  0.1111111     5     1  1.5        1    NA
18 #7B0051  0.2595364 -0.1498434     5     1  1.5        1    NA
19 #7B0051 -0.1268266 -0.0732234     5     1  1.5        1    NA
20 #7B0051  0.0000000  0.1111111     5     1  1.5        1    NA

Let's confirm if this data reproduces the five triangles in the ggradar graphic.

gg <- ggplot(data = mydf, aes(x = x, y = y, group = group, color = factor(group))) +
      geom_path(show.legend = FALSE) +
      theme_bw()

enter image description here

In summary, you want to hack ggplot data to extract the data you want. This method allows you to save data for the "shape" that you want. I hope this is what you are after.

Upvotes: 1

Related Questions