Интеллектуальная точка размещения меток в R - PullRequest
99 голосов
/ 30 сентября 2011

1) Существует ли какая-либо библиотека / функция R, которая бы осуществляла размещение меток ИНТЕЛЛЕКТУАЛЬНО в графике R?Я пробовал некоторые, но все они проблематичны - многие метки перекрывают друг друга или другие точки (или другие объекты на графике, но я вижу, что это намного сложнее обрабатывать).

2) Если нет,Есть ли способ, как удобно помочь алгоритму с размещением метки для конкретных проблемных точек?Требуется самое удобное и эффективное решение.

Вы можете поиграть и протестировать другие возможности на моем воспроизводимом примере и посмотреть, сможете ли вы добиться лучших результатов, чем я:

# data
x = c(0.8846, 1.1554, 0.9317, 0.9703, 0.9053, 0.9454, 1.0146, 0.9012, 
0.9055, 1.3307)
y = c(0.9828, 1.0329, 0.931, 1.3794, 0.9273, 0.9605, 1.0259, 0.9542, 
0.9717, 0.9357)
ShortSci = c("MotAlb", "PruMod", "EriRub", "LusMeg", "PhoOch", "PhoPho", 
"SaxRub", "TurMer", "TurPil", "TurPhi")

# basic plot
plot(x, y, asp=1)
abline(h = 1, col = "green")
abline(v = 1, col = "green")

Для маркировки я тогда попробовал эти возможности, никто не очень хорош:

1) этот ужасен:

text(x, y, labels = ShortSci, cex= 0.7, offset = 10)

2) этотхорошо, если вы не хотите размещать метки для всех точек, но только для выбросов, но метки часто размещаются неправильно:

identify(x, y, labels = ShortSci, cex = 0.7)

3) эта выглядела многообещающе, но естьпроблема меток, находящихся слишком близко к точкам;Я должен был заполнить их пробелами, но это не очень помогает:

require(maptools)
pointLabel(x, y, labels = paste("  ", ShortSci, "  ", sep=""), cex=0.7)

4)

require(plotrix)
thigmophobe.labels(x, y, labels = ShortSci, cex=0.7, offset=0.5)

5)

require(calibrate)
textxy(x, y, labs=ShortSci, cx=0.7)

Заранее спасибо!

РЕДАКТИРОВАТЬ: todo: попробуйте labcurve {Hmisc} .

Ответы [ 7 ]

47 голосов
/ 30 сентября 2011

Во-первых, вот результаты моего решения этой проблемы:

enter image description here

Я сделал это вручную в Preview (очень простой просмотрщик PDF / изображений в OS X) всего за несколько минут. ( Редактировать: Рабочий процесс оказался именно таким, как вы ожидали: я сохранил график в виде PDF-файла из R, открыл его в окне предварительного просмотра и создал текстовые поля с нужными метками (9pt Helvetica), а затем просто перетянул их с моей мышью, пока они не выглядели хорошо. Затем я экспортировал в PNG для загрузки в SO.)

Теперь, прежде чем вы уступите сильному желанию понизить это голосование до забвения и оставить язвительные комментарии о том, как смысл автоматизировать этот процесс, выслушайте меня!

Искать алгоритмические решения вполне нормально и (ИМХО) действительно интересно. Но, для меня, ситуации с маркировкой точек делятся примерно на три категории:

  1. У вас есть небольшое количество точек, ни одно из которых не очень близко друг к другу . В этом случае одно из решений, перечисленных в этом вопросе, вероятно, будет работать с минимальной настройкой.
  2. У вас есть небольшое количество точек, некоторые из которых слишком тесно упакованы, чтобы типичные алгоритмические решения давали хорошие результаты . В этом случае, поскольку у вас есть только небольшое количество точек, пометка их вручную (с помощью редактора изображений или точная настройка вашего вызова на text) - это не , это много усилий.
  3. У вас достаточно большое количество очков . В этом случае вам все равно не следует их маркировать, поскольку визуально трудно обрабатывать большое количество этикеток.

: забраться на мыльницу:

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

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

: спуск с мыльницы:

Я также хотел бы отметить, что я думаю, что все мы могли бы придумать графики рассеяния с <10-15 точками, которые почти невозможно будет чисто пометить, даже вручную, и они, вероятно, сломают любое автоматическое решение, которое кто-то придумает. </p>

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

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

39 голосов
/ 12 января 2016

ggrepel выглядит многообещающе применительно к ggplot2 точкам рассеяния.

# data
x = c(0.8846, 1.1554, 0.9317, 0.9703, 0.9053, 0.9454, 1.0146, 0.9012, 
0.9055, 1.3307)
y = c(0.9828, 1.0329, 0.931, 1.3794, 0.9273, 0.9605, 1.0259, 0.9542, 
0.9717, 0.9357)
ShortSci = c("MotAlb", "PruMod", "EriRub", "LusMeg", "PhoOch", "PhoPho", 
"SaxRub", "TurMer", "TurPil", "TurPhi")


df <- data.frame(x = x, y = y, z = ShortSci)
library(ggplot2)
library(ggrepel)

ggplot(data = df, aes(x = x, y = y)) + theme_bw() + 

    geom_text_repel(aes(label = z), 
       box.padding = unit(0.45, "lines")) +

    geom_point(colour = "green", size = 3)

enter image description here

10 голосов
/ 30 сентября 2011

Вы пробовали пакет directlabels ?

И, кстати, аргументы pos и offset могут принимать векторы, чтобы вы могли получить их в правильных позициях, когда есть разумное числоточек всего за несколько прогонов сюжета.

5 голосов
/ 28 октября 2011

Я нашел какое-то решение!К сожалению, он не идеален и не идеален, но сейчас он работает лучше всего для меня.Он наполовину алгоритмический, наполовину ручной, поэтому экономит время по сравнению с чисто ручным решением, набросанным Джораном.

Я упустил очень важную часть ?identify справки!

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

Так что, если вы используете решение identify(), как я написал в моем вопросе, то выможет повлиять на положение метки, не щелкая непосредственно по этой точке, а щелкая рядом с этой точкой относительно желаемого направления !!! Работает просто великолепно!

Недостатком является то, что есть только 4 позиции (сверху, слева, снизу, справа), но я бы больше оценил остальные 4 (вверху слева, вверху справа, внизу слева, внизу справа)) ... Так что я использую это для обозначения точек, где это меня не беспокоит, и остальных точек, которые я помечаю непосредственно в своей презентации Powerpoint, как предложил Джоран: -)

PS: у меня нетпопробовал решение для решетки / ggplot directlabels, я все еще предпочитаю использовать базовую библиотеку графиков.

4 голосов
/ 05 сентября 2013

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

http://blog.fellstat.com/?cat=11

3 голосов
/ 26 сентября 2018

Я написал функцию R с именем addTextLabels() в пакете plotteR. Пакет может быть установлен непосредственно в вашу библиотеку R с помощью следующего кода:

install.packages("devtools")
library("devtools")
install_github("JosephCrispell/basicPlotteR")

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

# Load the plotteR library
library(plotteR)

# Create vectors storing the X and Y coordinates
x = c(0.8846, 1.1554, 0.9317, 0.9703, 0.9053, 0.9454, 1.0146, 0.9012, 
      0.9055, 1.3307)
y = c(0.9828, 1.0329, 0.931, 1.3794, 0.9273, 0.9605, 1.0259, 0.9542, 
      0.9717, 0.9357)

# Store the labels to be plotted in a vector
ShortSci = c("MotAlb", "PruMod", "EriRub", "LusMeg", "PhoOch", "PhoPho", 
             "SaxRub", "TurMer", "TurPil", "TurPhi")

# Plot the X and Y coordinates without labels
plot(x, y, asp=1)
abline(h = 1, col = "green")
abline(v = 1, col = "green")

# Add non-overlapping text labels
addTextLabels(x, y, ShortSci, cex=0.9, col.background=rgb(0,0,0, 0.75), 
              col.label="white")

Работает путем автоматического выбора альтернативного местоположения из точной сетки точек. Ближайшие точки на сетке посещаются первыми и выбираются, если они не пересекаются с какими-либо нанесенными точками или метками. Посмотрите на источник код , если вам интересно.

Example Figure

2 голосов
/ 29 декабря 2014

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

Я иллюстрирую это с помощью ggplot2 потому что я более знаком с этим синтаксисом, чем графики с базовым R.

df <- data.frame(x = x, y = y, z = ShortSci)
library("ggplot2")
ggplot(data = df, aes(x = x, y = y, label = z)) + theme_bw() + 
    geom_point(shape = 1, colour = "green", size = 5) + 
    geom_text(data = within(df, c(y <- y+.01, x <- x-.01)), hjust = 0, vjust = 0)

Как вы можете видеть, в этом случае результат не идеален, но может быть достаточно хорошим для некоторых целей.И это довольно легко, как правило, что-то вроде этого достаточно within(df, y <- y+.01)

enter image description here

...