Контролирующий порядок точек в ggplot2 в R?

Предположим, что я рисую плотный график рассеяния в ggplot2 в R, где каждая точка может быть помечена другим цветом:

df <- data.frame(x=rnorm(500))
df$y = rnorm(500)*0.1 + df$x
df$label <- c("a")
df$label[50] <- "point"
df$size <- 2
ggplot(df) + geom_point(aes(x=x, y=y, color=label, size=size))

Когда я это делаю, точка разброса, обозначенная как "точка" (зеленая), наносится поверх красных точек с меткой "a". Что контролирует этот порядок z в ggplot, т.е. Какой элемент управления находится над ним? Например, что, если бы я хотел, чтобы все точки "а" находились поверх всех точек, помеченных как "точка" (что означает, что они иногда частично или полностью скрывают эту точку)? Это зависит от буквенно-цифрового упорядочения меток? Я хотел бы найти решение, которое можно легко перевести на rpy2. спасибо

Ответ 1

ggplot2 будет создавать графики поэтапно и внутри каждого слоя, порядок построения определяется типом geom. По умолчанию используется график в том порядке, в котором они отображаются в data.

Если это не так, отметим. Например

geom_line

Подключить наблюдения, упорядоченные по значению x.

и

geom_path

Подключить наблюдения в порядке данных


Существуют также известные проблемы, касающиеся порядка factors, и интересно отметить ответ автора пакета Hadley

Отображение графика должно быть инвариантным к порядку кадра данных - все остальное является ошибкой.


Эта цитата в виду, слой нарисован в указанном порядке, поэтому переполнение может быть проблемой, особенно при создании плотных участков рассеяния. Поэтому, если вам нужен согласованный график (а не тот, который зависит от порядка в кадре данных), вам нужно подумать немного больше.


Создайте второй слой

Если вы хотите, чтобы определенные значения отображались над другими значениями, вы можете использовать аргумент subset для создания второго слоя, который определенно будет нарисован впоследствии. Вам нужно будет явно загрузить пакет plyr, чтобы .() работал.

set.seed(1234)
df <- data.frame(x=rnorm(500))
df$y = rnorm(500)*0.1 + df$x
df$label <- c("a")
df$label[50] <- "point"
df$size <- 2
library(plyr)
ggplot(df) + geom_point(aes(x = x, y = y, color = label, size = size)) +
  geom_point(aes(x = x, y = y, color = label, size = size), 
             subset = .(label == 'point'))

enter image description here

Обновление

В ggplot2_2.0.0 аргумент subset устарел. Использовать, например. base::subset, чтобы выбрать соответствующие данные, указанные в аргументе data. И не нужно загружать plyr:

ggplot(df) +
  geom_point(aes(x = x, y = y, color = label,  size = size)) +
  geom_point(data = subset(df, label == 'point'),
             aes(x = x, y = y, color = label, size = size))

Или используйте alpha

Другим подходом, чтобы избежать проблемы переназначения, было бы установить alpha (прозрачность) точек. Это будет не так эффективно, как явный подход второго уровня выше, однако, при разумном использовании scale_alpha_manual вы сможете заставить что-то работать.

eg

# set alpha = 1 (no transparency) for your point(s) of interest
# and a low value otherwise
ggplot(df) + geom_point(aes(x=x, y=y, color=label, size=size,alpha = label)) + 
  scale_alpha_manual(guide='none', values = list(a = 0.2, point = 1))

enter image description here

Ответ 2

Обновление 2016:

Эстетический порядок устарел, поэтому в этот момент самым простым способом является сортировка data.frame, так что зеленая точка находится в снизу, и последний график. Если вы не хотите изменять исходный файл data.frame, вы можете отсортировать его во время вызова ggplot - вот пример, который использует %>% и arrange из пакета dplyr для сортировки на лету:

library(dplyr)
ggplot(df %>%
         arrange(label),
       aes(x = x, y = y, color = label, size = size)) +
  geom_point()

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

Оригинальный ответ 2015 года для версий ggplot2 < 2.0.0

В ggplot2 вы можете использовать order aesthetic, чтобы указать порядок, в котором отображаются точки. Самые последние из них будут отображаться сверху. Чтобы применить это, вы можете создать переменную, содержащую порядок, в котором вы хотите нарисовать точки.

Чтобы поставить зеленую точку сверху, построив ее после других:

df$order <- ifelse(df$label=="a", 1, 2)
ggplot(df) + geom_point(aes(x=x, y=y, color=label, size=size, order=order))

Или сначала нарисовать зеленую точку и похоронить ее, нарисуйте точки в обратном порядке:

ggplot(df) + geom_point(aes(x=x, y=y, color=label, size=size, order=-order))

Для этого простого примера вы можете пропустить создание новой переменной сортировки и просто принудить переменную label к коэффициенту, а затем цифру:

ggplot(df) +
  geom_point(aes(x=x, y=y, color=label, size=size, order=as.numeric(factor(df$label))))

Ответ 3

Основной вопрос здесь можно перефразировать следующим образом:

Как мне управлять слоями моего сюжета?

В пакете "ggplot2" вы можете сделать это быстро, разделив каждый другой слой на другую команду. Мышление с точки зрения слоев требует немного практики, но, по сути, оно сводится к тому, что вы хотите построить поверх других вещей. Вы строите с фона вверх.

Prep. Подготовьте образцы данных. Этот шаг необходим только для этого примера, потому что у нас нет реальных данных для работы.

# Establish random seed to make data reproducible.
set.seed(1)

# Generate sample data.
df <- data.frame(x=rnorm(500))
df$y = rnorm(500)*0.1 + df$x

# Initialize 'label' and 'size' default values.
df$label <- "a"
df$size <- 2

# Label and size our "special" point.
df$label[50] <- "point"
df$size[50] <- 4

Вы можете заметить, что я добавил в пример другой размер, чтобы сделать разницу уровней более четкой.

Шаг 1. Разделите свои данные на слои. Всегда делайте это, прежде чем использовать функцию "ggplot". Слишком много людей застревают, пытаясь манипулировать данными с помощью функций ggplot. Здесь мы хотим создать два слоя: один с метками "a" и один с метками "point".

df_layer_1 <- df[df$label=="a",]
df_layer_2 <- df[df$label=="point",]

Вы можете сделать это с помощью других функций, но я просто быстро использую логику соответствия кадра данных, чтобы вытащить данные.

Шаг 2. Выделите данные как слои. Сначала мы хотим сначала отобразить все "а", а затем отобразить все "точечные" данные.

ggplot() + 
    geom_point(
        data=df_layer_1,
        aes(x=x, y=y), 
        colour="orange", 
        size=df_layer_1$size) +
    geom_point(
        data=df_layer_2, 
        aes(x=x, y=y), 
        colour="blue", 
        size=df_layer_2$size)

demo chart

Обратите внимание, что базовый графический слой ggplot() не имеет назначенных данных. Это важно, потому что мы будем переопределять данные для каждого слоя. Затем мы имеем два отдельных слоя геометрии точки geom_point(...), которые используют свои собственные спецификации. Ось x и y будет разделяться, но мы будем использовать разные данные, цвета и размеры.

Важно перемещать спецификации цвета и размера вне функции aes(...), поэтому мы можем точно указать эти значения. В противном случае функция "ggplot" обычно назначает цвета и размеры в соответствии с уровнями, найденными в данных. Например, если у вас есть значения размера 2 и 5 в данных, он назначит размер по умолчанию для любых вхождений значения 2 и назначит некоторый больший размер для любых вхождений значения 5. An 'aes' функциональная спецификация не будет использовать значения 2 и 5 для размеров. То же самое касается цветов. У меня есть точные размеры и цвета, которые я хочу использовать, поэтому я переношу эти аргументы в функцию "geom_plot". Кроме того, любые характеристики функции "aes" будут помещены в легенду, которая может быть действительно бесполезной.

Заключительная записка. В этом примере вы можете достичь желаемого результата разными способами, но важно понять, как работают слои "ggplot2", чтобы максимально использовать ваш "ggplot" диаграммы. Пока вы разделяете свои данные на разные слои, прежде чем вы вызываете функции "ggplot", у вас есть большой контроль над тем, как все будет отображаться на экране.

Ответ 4

Он отображается по строкам в файле data.frame. Попробуйте следующее:

df2 <- rbind(df[-50,],df[50,])
ggplot(df2) + geom_point(aes(x=x, y=y, color=label, size=size))

Как вы видите, зеленая точка рисуется последним, так как она представляет последнюю строку data.frame.

Вот способ упорядочивания кадра data.frame с первой зеленой точкой:

df2 <- df[order(-as.numeric(factor(df$label))),]