Закрытие линий в диаграмме радара / паука ggplot2

Мне нужен гибкий способ создавать диаграммы радара / паука в ggplot2. Из решений, которые я нашел на github и в группе ggplot2, я зашел так далеко:

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

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)))

который работает, за исключением того, что линии не закрыты. Я думаю, что я смог бы сделать это:

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)))

для того, чтобы присоединиться к линии, но это не работает. Ни один не делает это:

closes <- subset(mtcarsm,variable == names(scaled)[c(1,11)])
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))) + geom_path(data=closes)

которая не решает проблему, а также производит много

"geom_path: каждая группа состоит только из одного наблюдения. Вам нужно настроить эстетику группы?"

Сообщения. Сом, как мне закрыть линии?

/ Fredrik

6 ответов

Решение

Извините, я был глупым. Это похоже на работу:

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))) 

Используя новый ggproto механизм доступен в ggplot2 2.0.0, coord_radar можно определить как:

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)
}

Не уверен, что синтаксис идеален, но он работает...

  • ключевой фактор решения
    1. добавить дубликат mpg ряд после melt от rbind
    2. унаследовать CoordPolar на ggproto
    3. задавать is_linear = function() TRUE на ggproto

особенно is_linear = function() TRUE это важно,
так как если не получишь сюжет вот так...

с is_linear = function() TRUE настройки, которые вы можете получить,

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")
  • конечный результат

Коды здесь кажутся устаревшими для ggplot2: 2.0.0

Попробуйте мой пакет zmisc: devtools:install_github("jerryzhujian9/ezmisc")

После его установки вы сможете запустить:

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)

если вам интересно, что внутри, посмотрите мои коды на github:

Основные коды были адаптированы с http://www.cmap.polytechnique.fr/~lepennec/R/Radar/RadarAndParallelPlots.html

введите описание изображения здесь введите описание изображения здесь

Спасибо вам, ребята, за помощь, но она не покрыла все мои потребности. Я использовал две серии данных для сравнения, поэтому я взял подмножество mtcars для Mazda:

  1. никто не упоминал о порядке переменной x, и ggplot2 сортирует эту переменную для графика, но не сортирует данные, и это сделало мою диаграмму неправильной с первой попытки. Примените функцию сортировки для меня это было dplyr::range(plot.data, x.variable.name)

  2. Мне нужно было аннотировать диаграмму значениями, и ggplot2::annotate() работает нормально, но она не была включена в последние ответы

  3. приведенный выше код не работал нормально для моих данных до добавления ggplot2::geom_line

Наконец этот фрагмент кода сделал мою диаграмму:

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()

Надеюсь, кому-нибудь пригодится

Оказывается, что geom_polygom по-прежнему выдает многоугольник в полярных координатах, так что

# 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("")

работает отлично...

Другие вопросы по тегам