Как одновременно применять цвет/форму/размер в диаграмме рассеяния с использованием графика?

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

[Добавлено 2016-06-20]. Чтобы расширить требуемое интерактивное поведение: идея, как только будет показана фигура, будет иметь возможность переключать группы точек, нажав любую из легенды. Например (в приведенных ниже примерах), если бы я нажимал на y в легенде, он скрывал/показывал точки № 4, 5 и 10 из всех серий. Если есть щелчок на A, то переключение точек # 1, 2 и 8. Как реальный случай использования - считайте цены облигаций, со сроком погашения по горизонтальной оси и ценой по вертикали. Облигации характеризуются страной происхождения, кредитным рейтингом и размером выпуска. Поэтому, если я нажму, скажем, кредитный рейтинг "А", я бы хотел, чтобы все проблемы с рейтингом A, независимо от размера и страны происхождения, были скрыты. В настоящее время они скрыты от следствия, связанного с оценкой. Показаны точки в следах, которые отражают другие атрибуты (размер и страна). Учитывая подробный ответ ниже, я склонен опубликовать это как запрос функции на сайте plotly.

Я задал вопрос для plotly, но если это поведение может быть достигнуто в другом пакете/библиотеке из R с относительно низкими уровнями боли (что означает отсутствие пользовательского JavaScript или тому подобного), я соглашусь с этим как на ответ, [end edit]

Статическая часть легко выполняется в ggplot2, но я не могу ее воссоздать в plotly (для интерактивности), даже используя ggplotly(). Не уверен, возможно ли вообще, но думал, что я спрошу. Пример данных и кода ниже.

(Возможно, связано с Использование 2+ легенд от R до plotly/plot.ly)

Сгенерируйте некоторые фиктивные данные:

library(data.table)
library(plotly)
library(ggplot2)


DT <- data.table(
    x = c(1:10), y = 1:10/2,
    gr1 = c("A", "A", "B", "C", "D", "D", "B", "A", "E", "E"),
    gr2 = c("x", "x", "x", "y", "y", "z", "z", "x", "x", "y"),
    gr3 = c(1,2,2,1,3,4,1,2,2,1)
)

Версия ggplot() выглядит так, и это то, что я хотел бы получить в замысле:

p <- ggplot(data = DT) + geom_point(aes(x = x, y = y, color = gr1, shape = gr2, size = gr3))
p

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

Вызов ggplotly(p) генерирует кучу предупреждений:

Warning messages:
1: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
2: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
3: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
4: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
5: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
6: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
7: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
8: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used

и создает эту цифру:

ggplotly version

Попытка использовать plot_ly(), я получаю следующее:

plot_ly(data = DT, x = x, y = y, color = gr1, symbol = gr2, type = "scatter", mode = "markers", marker = list(size = 10 * gr3)) # size is multiplied by 10, in plotly it is in pixels

plot_ly version

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

Я до сих пор совершенно не знаком с plotly, поэтому мне может не хватать чего-то очевидного.

Вышеописанное выполняется с помощью R 3.2.2 под Windows, с plotly_2.0.16 и ggplot2_2.0.0.

Ответ 1

К сожалению, замысел не дает этого поведения автоматически. Но это можно сделать достаточно просто, указав цвет, форму и размер каждой точки отдельно - используя аргументы colors =, size = и symbols =. Это позволяет контролировать, как накладываются точки, но не получает желаемую легенду. Поэтому мы используем showlegend = FALSE в основном графике и строим легенду, добавляя еще три (невидимые) трассы, которые есть только там, чтобы генерировать элементы легенды.

Обратите внимание, что здесь есть еще один трюк. Чтобы получить легенду, показывающую цвета или размеры, вы можете использовать аргумент visible = "legendonly", который создает запись легенды без чрезмерной графики дополнительных точек на графике. НО это не работает с фигурами. Объединение visible = "legendonly" с symbols = похоже на ошибку, которая помещает неправильные элементы в легенду. Таким образом, чтобы создать записи легенды для фигур, вы можете их выстроить в удаленном месте в стратосфере, где они никогда не будут видны (здесь я использовал x = y = 1e6) и задал пределы оси x и y, чтобы сохранить их зрения.

DT <- data.table(
  x = c(1:10), y = 1:10/2,
  gr1 = as.factor(c("A", "A", "B", "C", "D", "D", "B", "A", "E", "E")),
  gr2 = as.factor(c("x", "x", "x", "y", "y", "z", "z", "x", "x", "y")),
  gr3 = c(1,2,2,1,3,4,1,2,2,1)
)
shapes <- c("circle", "square", "diamond","cross", "x","square-open","circle-open","diamond-open")
DT$shapes <- shapes[DT$gr1]
DT$col <- rainbow(3)[DT$gr2]
DT$size <- DT$gr3*10

plot_ly() %>%
  add_trace(data = DT, x = x, y = y, type = "scatter", mode = "markers", 
            color=gr2, colors=col,
            marker = list(size = size, symbol=shapes), showlegend=F) %>%
  add_trace(data = DT, x = x, y = y, type = "scatter",mode = "markers", 
            color= factor(gr2), colors=col, 
            visible="legendonly", showlegend=T, legendgroup="color",
            marker = list(size = 14)) %>%
  add_trace(data = DT, x = x, y = y, type = "scatter",mode = "markers", 
            color=factor(gr3), colors="#000000", 
            marker = list(size = size),
            visible="legendonly", showlegend=T, legendgroup="size") %>%
  add_trace(data = DT, x = 1e6, y = 1e6, type = "scatter", mode = "markers", 
            color=factor(gr1), colors="#000000", 
            marker = list(size=14, symbol=shapes),
            showlegend=T, legendgroup="shape") %>%
  layout(legend=list(traceorder="grouped+reversed", tracegroupgap =30),
         xaxis=list(range=c(0,12)),
         yaxis=list(range=c(0,6)))

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