Інтелектуальне розміщення мітки в R


102

1) Чи є бібліотека / функція R, яка могла б реалізувати розміщення міток INTELLIGENT у 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)

Заздалегідь спасибі!

EDIT: todo: спробуйте labcurve {Hmisc} .


2
На жаль, відповіді на питання R, на жаль, рівномірно розподілені між StackOverflow та CrossValidated. У цьому випадку питання є дублікатом запису, який розпочався 4 дні тому .
Ед Штауб

3
Я зіткнувся з подібною проблемою і написав базовий пакет, який використовує силове моделювання поля для регулювання місця розташування об'єкта. Хоча можливе багато вдосконалення, включаючи інтеграцію з ggplot тощо, схоже, це може виконати завдання. Далі ілюструється функціональність. Якщо хтось install.packages("FField") library(FField) FFieldPtRepDemo()
зіткнеться

Чи можу я попросити вас спробувати ggrepel ?
Каміль Слайковський

Шановний @Joran, будь ласка, викладіть свій коментар "6) Для ggplot2 графіків існує новий варіант, який називається ggrepel, який багатьом людям подобається". у коментарі чи відповіді. Тут я включив лише список варіантів, які я спробував, але не є задовільним . Якщо це щось добре працює, то воно повинно бути у відповіді.
TMS

Відповіді:


49

По-перше, ось результати мого вирішення цієї проблеми:

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

Я зробив це вручну в Preview (дуже базовий переглядач PDF / зображень на OS X) всього за кілька хвилин. ( Редагувати: робочий процес був саме таким, який ви очікували. Я зберег сюжет як PDF від R, відкрив його в «Попередньому перегляді» і створив текстові поля з потрібними мітками (9pt Helvetica), а потім просто перетягнув їх за допомогою миші, поки вони не подивилися добре. Тоді я експортував у PNG для завантаження в SO.)

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

Шукати алгоритмічні рішення - це цілком чудово, і (IMHO) дійсно цікаво. Але, на мене, ситуації з маркування точок поділяються приблизно на три категорії:

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

: підйом на мильницю:

Оскільки такі люди, як ми, любимо автоматизацію, я думаю, що ми часто потрапляємо в пастку, думаючи, що майже кожен аспект створення гарної статистичної графіки повинен бути автоматизований. Я з повагою (смиренно!) Не згоден.

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

: спускається з мильної коробки:

Я також зазначу, що я думаю, що всім нам вдасться розробити розсіювачі з <10-15 балів, які неможливо буде чітко позначити навіть вручну, і це, швидше за все, порушить будь-яке автоматичне рішення, яке хтось придумає.

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

Тому я опублікував цю відповідь в тому, що я вважаю, що це питання повинно бути канонічним питанням «маркування точки в R» для майбутніх дублікатів, і я думаю, що рішення, пов’язані з маркуванням вручну, заслуговують на місце, і це все.


10
Інший ручний спосіб - зберегти сюжет як SVG та відредагувати його за допомогою Inkscape, а потім створити з нього PDF.
Spacedman

Привіт Джоран, дякую за вашу відповідь. Гаразд, я приймаю це рішення, хоча я думаю, що комп’ютер повинен зробити це найкраще в першу чергу, а потім вимагати вручну втручання. Тут я шукаю найбільш комфортне і швидке рішення. Скажіть, будь ласка, крок за кроком, як ви робили сюжет? Що ви створили за допомогою R, експорту, переміщення міток у "Попередній перегляд" тощо?
TMS

1
@TomasT. О Я бачу. У такому випадку мене "обдурили", начебто. Я створив один pdf з мітками, використовуючи один із ваших методів вище та один без, і використовував той із мітками як керівництво.
joran

1
+1 Це чудова відповідь. Деякі пояснення того, чому з’являється мета-CV : дивіться коментарі там.
бер

1
Переміщення невеликого набору етикеток вручну здається розумним, але ви можете спершу створити їх автоматично , а потім перемістити. Таким чином ви заощаджуєте багато роботи, а також зменшуєте ймовірність неправильного маркування ...
naught101

42

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)

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


10

Ви спробували пакет прямої позначки ?

І, BTW, аргументи pos і offset можуть приймати вектори, щоб дозволити вам перевести їх у правильні позиції, коли достатньо кількості балів за декілька етапів сюжету.


Чи можна використовувати пакет прямої етикетки із звичайним plot()сюжетом? Мені не вдалося так пробувати ... Дякую! PS: @SpacedMan & Ben, я очистив свої коментарі щодо оновлення R, оскільки вони не так цікаві - ви можете зробити те саме.
TMS

6

Я знайшов якесь рішення! Це не надзвичайно і ідеально, але це найкраще для мене зараз. Це наполовину алгоритмічний, наполовину ручний, тому економить час порівняно з чистим ручним рішенням, накресленим Джораном.

Я не помітив дуже важливу частину ?identifyдопомоги!

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

Отже, якщо ви використовуєте identify()рішення, як я писав у своєму запитанні, то ви можете вплинути на позицію етикетки, не натиснувши безпосередньо на цю точку, а натиснувши поруч із цією точкою відносно у потрібному напрямку !!! Працює просто чудово!

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

PS: Я ще не пробував рішення directlabels решетка / ggplot, я все одно вважаю за краще використовувати базову бібліотеку сюжетів.


4

Я б запропонував вам поглянути на wordcloudпакунок. Я знаю, що цей пакет фокусується не саме на пунктах, а на самих етикетках, а також стиль здається досить виправленим. Але все ж результати, отримані від його використання, були досить приголомшливими. Також зауважте, що розглянутий варіант упаковки був випущений приблизно у той момент, коли ви задали це питання, тому він все ще дуже новий.

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


3

Я написав функцію 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")

Це працює, автоматично вибираючи альтернативне місце з тонкої сітки точок. Найближчі точки в сітці відвідуються спочатку та вибираються, якщо вони не перетинаються з якимись накресленими точками чи мітками. Погляньте на вихідний код , якщо вам це цікаво.

Приклад рисунка


2

Не відповідь, але занадто довго для коментаря. Дуже простий підхід, який може працювати в простих випадках, десь між пост-обробкою Джорана і більш досконалими алгоритмами, які були представлені, - це зробити 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)

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


2
Замість того, щоб модифікувати dfвикористання within, я часто це роблю, коригуючи естетику: geom_text(aes(x = x - .01, y = y + .01), hjust = 0, vjust = 0)здається чистішою.
Грегор Томас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.