ggplot добавить geom_path с другим эстетическим цветом // Ошибка: Ошибка: недостаточно значений в ручном масштабировании

Я пытаюсь связать geom_points в моем ggplot с geom_path. Линии должны быть того же цвета, что и цвет заливки geom_point. Однако geom_path не знает заливки, и цвет используется для другой группировки.

Я также выделяю определенные geom_points черным контуром, используя

scale_color_manual(values = c("NA", "black"), labels = c("No Buy Box", "Buy Box"))

Что я могу сделать? Фактически, я хочу нарисовать точки разным цветом (заливкой) с помощью seller_id, выделить некоторые из этих точек с помощью color = black, если bbox = 1, и, кроме того, соединить точки в их цвете с помощью geom_path. Я предполагаю, что есть некоторые более общие проблемы в том, как я распределил графики по слоям с точки зрения субвыборки. geom_path не знает fill, это было бы самым простым решением. Фрагмент данных находится в конце этого сообщения.

Спасибо!!

ggplot(data = subset(algo_pricing,bbox_product == 9200000096286280), aes(x = bbox_time2)) +
  geom_point(mapping = aes(y = price_total, colour = as.factor(bbox), fill = seller_id), shape = 21) +
  geom_line(data = subset(algo_pricing, bbox ==1 & bbox_product == 9200000096286280), 
            mapping = aes(y = bbox_price, linetype = as.factor(bbox)),colour = "black") +
  geom_path(mapping = aes(y = price_total, colour = seller_id), linetype = "dotted") +
  scale_linetype_manual(values = "dotted", labels = "Buy Box Price") +
  scale_color_manual(values = c("NA", "black"), labels = c("No Buy Box", "Buy Box"))
example <- wrapr::build_frame(
   "bbox_time2"           , "bbox_price", "price_total", "seller_id"            , "bbox", "min_price", "bbox_product" |
     as.Date("2019-01-07"), 151         , 169.9        , "linkerlisse"          , 0L    , 129.5      , 4.641e-308     |
     as.Date("2019-01-18"), 125         , 169.9        , "linkerlisse"          , 0L    , 112        , 4.641e-308     |
     as.Date("2019-01-20"), 125         , 169.9        , "goedslapennl"         , 0L    , 118.5      , 4.641e-308     |
     as.Date("2019-01-14"), 120         , 169.9        , "decoware"             , 0L    , 114.3      , 4.641e-308     |
     as.Date("2019-01-18"), 125         , 169.9        , "goedslapennl"         , 0L    , 112        , 4.641e-308     |
     as.Date("2019-01-19"), 125         , 125          , "bol.com"              , 1L    , 125        , 4.641e-308     |
     as.Date("2019-01-20"), 125         , 169.9        , "decoware"             , 0L    , 121        , 4.641e-308     |
     as.Date("2019-01-19"), 125         , 169.9        , "decoware"             , 0L    , 124.2      , 4.641e-308     |
     as.Date("2019-01-10"), 135         , 120.3        , "hetbestebeddengoed.nl", 0L    , 120.3      , 4.641e-308     |
     as.Date("2019-01-11"), 135         , 135          , "bol.com"              , 1L    , 115.5      , 4.641e-308     |
     as.Date("2018-12-31"), 151         , 151          , "bol.com"              , 1L    , 143.8      , 4.641e-308     |
     as.Date("2019-01-17"), 125         , 169.9        , "goedslapennl"         , 0L    , 116.2      , 4.641e-308     |
     as.Date("2019-01-20"), 125         , 169.9        , "goedslapennl"         , 0L    , 119.8      , 4.641e-308     |
     as.Date("2019-01-17"), 125         , 169.9        , "goedslapennl"         , 0L    , 115.5      , 4.641e-308     |
     as.Date("2019-01-22"), 112.3       , 112.3        , "hetbestebeddengoed.nl", 1L    , 112.3      , 4.641e-308     |
     as.Date("2019-01-01"), 151         , 169.9        , "linkerlisse"          , 0L    , 142.1      , 4.641e-308     |
     as.Date("2019-01-21"), 125         , 127.5        , "sleepworld"           , 0L    , 117.8      , 4.641e-308     |
     as.Date("2018-12-31"), 151         , 151          , "bol.com"              , 1L    , 142.8      , 4.641e-308     |
     as.Date("2019-01-18"), 125         , 169.9        , "smulderstextiel.nl"   , 0L    , 125        , 4.641e-308     |
     as.Date("2019-01-01"), 151         , 169.9        , "linkerlisse"          , 0L    , 141.2      , 4.641e-308     )

person marcellobello    schedule 14.04.2020    source источник
comment
Привет! Можете ли вы опубликовать свои данные через dput(your.data.frame) или хотя бы их часть, чтобы у нас был воспроизводимый пример?   -  person chemdork123    schedule 14.04.2020
comment
Конечно, я забыл об этом. Добавлен фрагмент в OP.   -  person marcellobello    schedule 14.04.2020
comment
Спасибо за публикацию, но, к сожалению, я не могу создать разумный график, используя эти данные (я думаю, что он представляет только одну дату). Возможно, было бы неплохо использовать sample() для захвата нескольких строк из исходного фрейма данных: (например, algo_pricing[sample(1:nrow(algo_pricing), 20),] будет работать для случайного захвата 20 строк), но вы должны убедиться, что ваш пример работает с вашим набором данных, который вы публикуете. Кроме того, что вы получаете в результате своего кода, и где он, кажется, идет не так? Вы создаете график, который выглядит неправильно, или вы получаете сообщение об ошибке?   -  person chemdork123    schedule 14.04.2020
comment
Ах, очевидно, извините. Сделал правку выше. Я получаю сообщение об ошибке «Недостаточно значений при ручном масштабировании». Это потому, что цвет уже определен с двумя значениями.   -  person marcellobello    schedule 14.04.2020
comment
Хорошо - это то, что я тоже получал. Я посмотрю.   -  person chemdork123    schedule 14.04.2020
comment
Удалите звонки scale_color_manual и scale_linetype_manual. Это создаст сюжет, но, вероятно, это не то, что вы хотите видеть. ggplot объединит масштабы, если вы укажете один и тот же эстетический вид: например, вы укажете, что тип линий geom_line и внешний цвет geom_point будут применяться к одному и тому же фактору (as.factor(bbox)). Создается легенда, которая указывает, что bbox либо точечно с одним цветом, либо сплошной с другим цветом (объединяя два). Удалите эти scale_... призывы, опубликуйте свой сюжет, затем проясните свой вопрос - возможно, относительно легенды и маркировки.   -  person chemdork123    schedule 14.04.2020


Ответы (2)


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

Однако это очень хорошее упражнение для отображения и контроля эстетики.

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

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

Другие комментарии в коде.

library(tidyverse)
example <- example %>% 
  distinct(seller_id, bbox_time2,.keep_all = TRUE) %>%
  mutate(bbox_sell  = paste(seller_id, bbox, sep = '_'),
         price_total = jitter(price_total, amount = 1)) %>%
  arrange(bbox_time2, seller_id)   # arranging is important for geom_path


ggplot( # setting the general aesthetics. You could do this in each geom call, but I am a bit lazy, so I define the main aesthetics here. 
  data = example,
  aes(
    x = bbox_time2,
    y = price_total,
    group = seller_id
  )
) +
  geom_point(
    aes(colour = seller_id) # color aesthetic matches the following geom_path.
# also, the shape defaults to 16. This avoids messing with both fill and color aesthetic. 
  ) +
  geom_path(
    aes(colour = seller_id),
    linetype = "dotted"
  ) +
  geom_path(
    data = filter(example, bbox == 1),
    aes(linetype = "box1", group = bbox_sell),
    colour = "black".   # color defined outside of aesthetic! 
  ) +
  scale_linetype_manual(name = NULL, values = "dotted", labels = "Buy Box Price") +
  ggnewscale::new_scale_colour() + # now here's an option how to easily create two color scales. 
  geom_point(
    data = filter(example, bbox == 1),
    aes(color = as.character(bbox)), # you can now use a new color scale. 
    shape = 21, # using a different shape for the highlighted points
  ) +
  scale_color_manual(name = NULL, values = "black", labels = "Buy Box") 

Порядок легенд, конечно, своеобразен. Управление порядком легенды - вещь довольно простая, и «обычный» способ управления им с помощью + guides(xxx = guide_legend(order =...)), похоже, не работает с ggnewscale.

Создано 15 апреля 2020 г. пакетом REPEX (v0.3.0)

person tjebo    schedule 15.04.2020
comment
ggnewscale::new_scale_colour() это то, что я искал все время !! Это очень полезно, большое спасибо за вашу помощь и ценные комментарии. Я понимаю, что сюжет немного преувеличен, но, тем не менее, я подумал, что полезно научиться определять несколько цветовых шкал вручную. Ваше здоровье! - person marcellobello; 15.04.2020

Попробуйте, сложно воспроизвести ваш фрейм данных, но у меня были похожие проблемы, и следующее сработало.

Сначала определите свой цвет и значения (также я не совсем понимаю, что вы пытаетесь сделать с «NA» здесь, вам нужны цвета, а не NA). У вас также есть один цвет, определенный для двух разных графиков (линия и путь, убедитесь, что вы добавили его для двух отдельно).

Также обратите внимание на это решение: [график ниже, показывающий 2 легенды при ручном управлении цветом шкалы


cl <- c("black" = "Buy Box", "blue" = "No Buy Box")
ggplot(data = subset(algo_pricing,bbox_product == 9200000096286280), aes(x = bbox_time2)) +
  geom_point(mapping = aes(y = price_total, colour = as.factor(bbox), fill = seller_id), shape = 21) +
  geom_line(data = subset(algo_pricing, bbox ==1 & bbox_product == 9200000096286280), 
            mapping = aes(y = bbox_price, linetype = as.factor(bbox)),colour = "Buy Box") +
  geom_path(mapping = aes(y = price_total, colour = seller_id), linetype = "dotted", colour = "No Buy Box") +
  scale_color_manual(values = c("blue", "black"))

person Sally_ar    schedule 14.04.2020