Подтвердить что ты не робот

Расположение большого количества графиков и соединение с линиями в r

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

От A до L - независимые графики. Сердечник их размещения указан.

enter image description here

координаты сетки сетки: PlotgridX и plotgridY могут решить, когда маленький участок должен быть центрирован

    plotcord <- data.frame (
plotname = c("A", "B", "C", "D",    "E",    "F",   "G", "H", "I", "J", "K", "L"),
plotgridX = c( 1.5, 2,   5,   5.5,   1.75,  5.25,  8   , 1 ,  2,   3.5,  6,  7.5),
 plotgridY = c( 3,  3,    3,    3,     2 ,    2,    2,   2  , 1,   1,   1,   1))


   plotname plotgridX plotgridY
1         A      1.50         3
2         B      2.00         3
3         C      5.00         3
4         D      5.50         3
5         E      1.75         2
6         F      5.25         2
7         G      8.00         2
8         H      1.00         2
9         I      2.00         1
10        J      3.50         1
11        K      6.00         1
12        L      7.50         1

Соединительные линии определяются с помощью следующего фрейма данных:

connectd <- data.frame (id = c(  "E",    "F", "I", "J", "K", "L"),
                        parent1 = c("A",  "C", "H", "E" ,"E", "F"),
                      parent2 = c("B",  "D",  "E", "F", "F", "G"))
connectd
  id parent1 parent2
1  E       A       B
2  F       C       D
3  I       H       E
4  J       E       F
5  K       E       F
6  L       F       G

Например, здесь цифра E должна быть подключена к ее родительскому 1 "A" и родительским 2 "B" цифрам в то же время "A", "B" следует подключить, чтобы сделать его "T-образным" соединением. Аналогично для других идентификаторов.

Хотя у меня есть другие детали для построения в каждом подзаголовке, так же, как доказательство концепции, я хотел бы построить один прямоугольник с каждой графикой с именами n1 и n2, чтобы сделать график следующим: enter image description here

4b9b3361

Ответ 1

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

Фон

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

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

Пользовательская визуализация? Введите "сетка"

Базовый пакет "grid" - это максимальная гибкость рисования, отчасти потому, что он расширяет функциональность функций построения базы, а не обертывает их. С помощью функций "сетки" мы получаем возможность создавать визуальные объекты с использованием различных единиц измерения для размещения и калибровки, и (это действительно важно) мы получаем возможность использовать обоснования для якорей наших объектов. Книга Пол Мурелла "R Graphics" - отличный ресурс, если вы хотите учиться. Копия его сидит на моем столе.

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

Процесс

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

Процесс "grid" работает в трех основных шагах:

  • Сделать окно просмотра
  • Нарисуйте некоторые объекты
  • Попасть в окно просмотра

При создании окна просмотра мы используем "pushViewport" для перемещения объекта "viewport", примерно так:

pushViewport(viewport(x=0, y=1, xscale=c(1, 10), yscale=c(0, 100), width=0.25, height=0.25, default.units="npc", just=c("left","bottom"), clip="off"))

У основного видового экрана есть набор "npc" единиц, где x идет от 0 до 1, слева направо, а y идет от 0 до 1, снизу вверх. Это означает, что начало координат находится в нижнем левом углу. Вышеуказанный видовой экран создается как одна четверть участка в нижнем левом углу. Однако, когда мы указываем "xscale" и "yscale", мы получаем возможность ссылаться на единицы "native" при рисовании объектов. Это означает, что мы можем использовать "родные" единицы для рисования данных и использовать единицы "npc" при рисовании таких объектов, как оси и метки.

При рисовании объектов мы используем такие функции, как "grid.lines", "grid.polygon", "grid.points", "grid.circle" и т.д. Каждая визуализация, которую я когда-либо делал, использовала эти объекты. Когда вы рисуете данные, задавая эти объекты вручную, вы получаете огромное количество контроля. Заполнение линейной диаграммы является одним из наиболее очевидных примеров добавленной возможности. Заполненная область представляет собой всего лишь многоугольник с точками многоугольника, указанными данными, и с добавлением двух опорных точек. Я использую это, чтобы выделить области линейной диаграммы или упростить чтение нескольких строк на одной диаграмме.

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

Вот пример одной из диаграмм (без реального имени игрока), чтобы дать представление о том, насколько гибкими являются "сетчатые" визуальные эффекты:

Sample sophisticated chart

Доказательство концепции для вопроса

Теперь конкретно рассмотрим вопрос, заданный ОП. В вопросе OP подразумевает, что он/она будет строить диаграммы внутри каждой области. Это может оказаться сложным при использовании заранее построенных пакетов построения, так как большинство функций построения будут перезаписывать любые спецификации графика, которые вы уже настроили. Вместо этого более надежно использовать что-то вроде функций "сетки" базы, чтобы указать области построения, а затем нарисовать необходимые объекты данных в видовых экранах.

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

Код может выглядеть немного сложнее, но помните три шага "сетка": нажмите viewport, draw, pop viewport. Это то, что выполняет каждая функция. Для демонстрации работы я выполнил четыре различные функции рисования: заполненную линейную диаграмму, график рассеяния, гистограмму и чертеж коробки, как было предложено OP. Каждая функция достаточно гибкая, чтобы учитывать множество наборов значений данных в каждой диаграмме, устанавливая альфа-значения для компенсации и позволяя нам видеть значения, нанесенные поверх друг друга.

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

Вот результат демонстрационного кода, используя некоторые встроенные наборы данных R для упрощения данных (EuStockMarkets, nottem, sunspots.month):

Chart demo of grid functionality


Пользовательская библиотека функций:


library(grid)

# Specify general chart options.
chart_Fill = "lemonchiffon"
chart_Col = "snow3"
space_Background = "white"
title_CEX = 0.8
axis_CEX = 0.6
chart_Width <- 3/3
chart_Height <- 2/5

# Function to initialize a plotting area.
init_Plot <- function(
    .df,
    .x_Loc, 
    .y_Loc, 
    .justify, 
    .width, 
    .height
    ){

    # Initialize plotting area to fit data.
    # We have to turn off clipping to make it
    # easy to plot the labels around the plot.
    pushViewport(viewport(xscale=c(min(.df[,1]), max(.df[,1])), yscale=c(min(0,min(.df[,-1])), max(.df[,-1])), x=.x_Loc, y=.y_Loc, width=.width, height=.height, just=.justify, clip="off", default.units="native"))

    # Color behind text.
    grid.rect(x=0, y=0, width=unit(axis_CEX, "lines"), height=1, default.units="npc", just=c("right", "bottom"), gp=gpar(fill=space_Background, col=space_Background))
    grid.rect(x=0, y=1, width=1, height=unit(title_CEX, "lines"), default.units="npc", just=c("left", "bottom"), gp=gpar(fill=space_Background, col=space_Background))

    # Color in the space.
    grid.rect(gp=gpar(fill=chart_Fill, col=chart_Col))
}

# Function to finalize and label a plotting area.
finalize_Plot <- function(
    .df, 
    .plot_Title
    ){

    # Label plot using the internal reference
    # system, instead of the parent window, so
    # we always have perfect placement.
    grid.text(.plot_Title, x=0.5, y=1.05, just=c("center","bottom"), rot=0, default.units="npc", gp=gpar(cex=title_CEX))
    grid.text(paste(names(.df)[-1], collapse=" & "), x=-0.05, y=0.5, just=c("center","bottom"), rot=90, default.units="npc", gp=gpar(cex=axis_CEX))
    grid.text(names(.df)[1], x=0.5, y=-0.05, just=c("center","top"), rot=0, default.units="npc", gp=gpar(cex=axis_CEX))

    # Finalize plotting area.
    popViewport()
}

# Function to plot a filled line chart of
# the data in a data frame.  The first column
# of the data frame is assumed to be the
# plotting index, with each column being a
# set of y-data to plot.  All data is assumed
# to be numeric.
plot_Line_Chart <- function(
    .df,
    .x_Loc,
    .y_Loc,
    .justify,
    .width,
    .height,
    .colors,
    .plot_Title
    ){

    # Initialize plot.
    init_Plot(.df, .x_Loc, .y_Loc, .justify, .width, .height)

    # Calculate what value to use as the
    # return for the polygons.
    y_Axis_Min <- min(0, min(.df[,-1]))

    # Plot each set of data as a polygon,
    # so we can fill it in with color to
    # make it easier to read.
    for (i in 2:ncol(.df)){
        grid.polygon(x=c(min(.df[,1]),.df[,1], max(.df[,1])), y=c(y_Axis_Min,.df[,i], y_Axis_Min), default.units="native", gp=gpar(fill=.colors[i-1], col=.colors[i-1], alpha=1/ncol(.df)))
    }

    # Draw plot axes.
    grid.lines(x=0, y=c(0,1), default.units="npc")
    grid.lines(x=c(0,1), y=0, default.units="npc")

    # Finalize plot.
    finalize_Plot(.df, .plot_Title)

}

# Function to plot a scatterplot of
# the data in a data frame.  The
# assumptions are the same as 'plot_Line_Chart'.
plot_Scatterplot <- function(
    .df,
    .x_Loc,
    .y_Loc,
    .justify,
    .width,
    .height,
    .colors,
    .plot_Title
    ){

    # Initialize plot.
    init_Plot(.df, .x_Loc, .y_Loc, .justify, .width, .height)

    # Plot each set of data as colored points.
    for (i in 2:ncol(.df)){
        grid.points(x=.df[,1], y=.df[,i], pch=19, size=unit(1, "native"), default.units="native", gp=gpar(col=.colors[i-1], alpha=1/ncol(.df)))
    }

    # Draw plot axes.
    grid.lines(x=0, y=c(0,1), default.units="npc")
    grid.lines(x=c(0,1), y=0, default.units="npc")

    # Finalize plot.
    finalize_Plot(.df, .plot_Title)

}

# Function to plot a histogram of
# all the columns in a data frame,
# except the first, which is assumed to
# be an index.
plot_Histogram <- function(
    .df,
    .x_Loc,
    .y_Loc,
    .justify,
    .width,
    .height,
    .colors,
    .plot_Title,
    ...
    ){

    # Create a list containing the histogram
    # data for each data column and calculate
    # data ranges.  Any extra parameters
    # specified will pass to the 'hist' function.
    hist_Data <- list()
    hist_Count_Range <- c(0,NA)
    hist_Breaks_Range <- c(NA,NA)
    for (i in 2:ncol(.df)){
        hist_Data[[i]] <- hist(.df[,i], plot=FALSE, ...)
        hist_Count_Range[2] <- max(max(hist_Data[[i]]$counts), hist_Count_Range[2], na.rm=TRUE)
        hist_Breaks_Range <- c(min(min(hist_Data[[i]]$breaks), hist_Breaks_Range[1], na.rm=TRUE), max(max(hist_Data[[i]]$breaks), hist_Breaks_Range[2], na.rm=TRUE))
    }


    # Initialize plotting area to fit data.
    # We are doing this in a custom way to
    # allow more flexibility than built into
    # the 'init_Plot' function.
    # We have to turn off clipping to make it
    # easy to plot the labels around the plot.
    pushViewport(viewport(xscale=hist_Breaks_Range, yscale=hist_Count_Range, x=.x_Loc, y=.y_Loc, width=.width, height=.height, just=.justify, clip="off", default.units="native"))

    # Color behind text.
    grid.rect(x=0, y=0, width=unit(axis_CEX, "lines"), height=1, default.units="npc", just=c("right", "bottom"), gp=gpar(fill=space_Background, col=space_Background))
    grid.rect(x=0, y=1, width=1, height=unit(title_CEX, "lines"), default.units="npc", just=c("left", "bottom"), gp=gpar(fill=space_Background, col=space_Background))

    # Color in the space.
    grid.rect(gp=gpar(fill=chart_Fill, col=chart_Col))


    # Draw x axis.
    grid.lines(x=c(0,1), y=0, default.units="npc")

    # Plot each set of data as a histogram.
    for (i in 2:ncol(.df)){
        grid.rect(x=hist_Data[[i]]$mids, y=0, width=diff(hist_Data[[i]]$mids[1:2]), height=hist_Data[[i]]$counts, default.units="native", just=c("center","bottom"), gp=gpar(fill=.colors[i-1], col=.colors[i-1], alpha=1/ncol(.df)))
    }

    # Label plot using the internal reference
    # system, instead of the parent window, so
    # we always have perfect placement.
    grid.text(.plot_Title, x=0.5, y=1.05, just=c("center","bottom"), rot=0, default.units="npc", gp=gpar(cex=title_CEX))
    grid.text(paste(names(.df)[-1], collapse=" & "), x=-0.05, y=0.5, just=c("center","bottom"), rot=90, default.units="npc", gp=gpar(cex=axis_CEX))

    # Finalize plotting area.
    popViewport()
}

draw_Sample_Box <- function(
    .x_Loc,
    .y_Loc,
    .x_Scale,
    .y_Scale,
    .justify,
    .width,
    .height,
    .colors,
    .box_X,
    .box_Y,
    .plot_Title
    ){

    pushViewport(viewport(xscale=.x_Scale, yscale=.y_Scale, x=.x_Loc, y=.y_Loc, width=chart_Width, height=chart_Height, just=.justify, clip="off", default.units="native"))

    # Color behind text.
    grid.rect(x=0, y=1, width=1, height=unit(title_CEX, "lines"), default.units="npc", just=c("left", "bottom"), gp=gpar(fill=space_Background, col=space_Background))

    # Color in the space.
    grid.rect(gp=gpar(fill=chart_Fill, col=chart_Col))

    # Label plot.
    grid.text(.plot_Title, x=0.5, y=1.05, just=c("center","bottom"), rot=0, default.units="npc", gp=gpar(cex=title_CEX))

    # Draw box and label points.
    grid.polygon(x=.box_X, y=.box_Y, default.units="native", gp=gpar(fill=.colors[1], col=.colors[2]))
    grid.text(paste(.plot_Title, 1, sep=""), x=min(.box_X), y=min(.box_Y), default.units="native", just=c("right","top"), gp=gpar(cex=0.5))
    grid.text(paste(.plot_Title, 2, sep=""), x=max(.box_X), y=min(.box_Y), default.units="native", just=c("left","top"), gp=gpar(cex=0.5))

    # Finalize plot.
    popViewport()
}

Демо-код:


# Draw twelve independent charts as
# a demo and connect with lines similar
# to a heiritage chart.
grid.newpage()

# Initialize a viewport to make our locations
# easier to map.
pushViewport(viewport(x=0, y=0, width=1, height=1, just=c("left","bottom"), xscale=c(0,10), yscale=c(0,4)))

# Color background of overall plot.
grid.rect(gp=gpar(fill=space_Background, col=space_Background))

# Store plot locations for convenience.
plot_Loc <- data.frame(x=c(2,4,6,8,1,3,7,9,2,4,6,8), y=c(3,3,3,3,2,2,2,2,1,1,1,1))

# Draw connecting lines.
connections <- data.frame(a=c(1, 3, 5, 6, 7, 1, 3, 5, 7, 6), b=c(2, 4, 6, 7, 8, 2, 4, 6, 8, 7), c=c(NA, NA, NA, NA, NA, 6, 7, 9, 12, 10), d=c(NA, NA, NA, NA, NA, NA, NA, NA, NA, 11))
for (i in 1:nrow(connections)){
    if (is.na(connections$c[i])){
        grid.lines(x=plot_Loc$x[unlist(connections[i,1:2])], y=plot_Loc$y[unlist(connections[i,1:2])], default.units="native")
    } else if (is.na(connections$d[i])) {
        grid.lines(x=median(plot_Loc$x[unlist(connections[i,1:2])]), y=plot_Loc$y[unlist(connections[i,2:3])], default.units="native")
    } else {
        grid.lines(x=median(plot_Loc$x[unlist(connections[i,1:2])]), y=c(plot_Loc$y[connections[i,2]], median(plot_Loc$y[unlist(connections[i,2:3])])), default.units="native")
        grid.lines(x=plot_Loc$x[unlist(connections[i,3:4])], y=median(plot_Loc$y[unlist(connections[i,2:3])]), default.units="native")
        grid.lines(x=plot_Loc$x[connections[i,3]], y=c(median(plot_Loc$y[unlist(connections[i,2:3])]), plot_Loc$y[connections[i,3]]), default.units="native")
        grid.lines(x=plot_Loc$x[connections[i,4]], y=c(median(plot_Loc$y[unlist(connections[i,2:3])]), plot_Loc$y[connections[i,4]]), default.units="native")
    }
}


# Draw four independent line charts.
p <- 1
plot_Line_Chart(data.frame(time=1:1860, EuStockMarkets)[1:3], .x_Loc=plot_Loc$x[p], .y_Loc=plot_Loc$y[p], .just=c("center","center"), .width=chart_Width, .height=chart_Height, c("dodgerblue", "deeppink"), "EU Stocks")
p <- 2
plot_Line_Chart(data.frame(time=1:1860, EuStockMarkets)[c(1,4,5)], .x_Loc=plot_Loc$x[p], .y_Loc=plot_Loc$y[p], .just=c("center","center"), .width=chart_Width, .height=chart_Height, c("green", "purple"), "EU Stocks")
p <- 3
plot_Line_Chart(data.frame(time=1:(12*20), sunspots=sunspot.month[(171*12+1):(171*12+12*20)]), .x_Loc=plot_Loc$x[p], .y_Loc=plot_Loc$y[p], .just=c("center","center"), .width=chart_Width, .height=chart_Height, c("darkgoldenrod"), "Sunspots")
p <- 4
plot_Line_Chart(data.frame(time=1:(12*20), temp=nottem), .x_Loc=plot_Loc$x[p], .y_Loc=plot_Loc$y[p], .just=c("center","center"), .width=chart_Width, .height=chart_Height, c("red"), "Nottem")

# Draw four independent scatterplots.
p <- 5
plot_Scatterplot(data.frame(time=1:(1860 + 1 - 1000), DAX=rowMeans(embed(EuStockMarkets[,1], 1000)), FTSE=rowMeans(embed(EuStockMarkets[,4], 1000))), .x_Loc=plot_Loc$x[p], .y_Loc=plot_Loc$y[p], .just=c("center","center"), .width=chart_Width, .height=chart_Height, c("deeppink", "purple"), "Smooth")
p <- 6
plot_Scatterplot(data.frame(time=1:1860, EuStockMarkets)[c(1,2,5)], .x_Loc=plot_Loc$x[p], .y_Loc=plot_Loc$y[p], .just=c("center","center"), .width=chart_Width, .height=chart_Height, c("deeppink", "purple"), "EU Stocks")
p <- 9
plot_Scatterplot(data.frame(time=1:(1860 + 1 - 20), DAX=rowMeans(embed(EuStockMarkets[,1], 20)), FTSE=rowMeans(embed(EuStockMarkets[,4], 20))), .x_Loc=plot_Loc$x[p], .y_Loc=plot_Loc$y[p], .just=c("center","center"), .width=chart_Width, .height=chart_Height, c("deeppink", "purple"), "Smooth*20")
p <- 10
plot_Scatterplot(data.frame(time=1:(1860 + 1 - 100), DAX=rowMeans(embed(EuStockMarkets[,1], 100)), FTSE=rowMeans(embed(EuStockMarkets[,4], 100))), .x_Loc=plot_Loc$x[p], .y_Loc=plot_Loc$y[p], .just=c("center","center"), .width=chart_Width, .height=chart_Height, c("deeppink", "purple"), "Smooth*100")


# Draw two independent histograms.
p <- 7
plot_Histogram(data.frame(time=1:(12*20), sunspots=sunspot.month[(171*12+1):(171*12+12*20)]), .x_Loc=plot_Loc$x[p], .y_Loc=plot_Loc$y[p], .just=c("center","center"), .width=chart_Width, .height=chart_Height, c("darkgoldenrod"), "Sunspots", breaks=6)
p <- 8
plot_Histogram(data.frame(time=1:(12*20), temp=nottem), .x_Loc=plot_Loc$x[p], .y_Loc=plot_Loc$y[p], .just=c("center","center"), .width=chart_Width, .height=chart_Height, c("red"), "Nottem", breaks=6)

# Draw sample objects in two charts spaces.
p <- 11
draw_Sample_Box(.x_Loc=plot_Loc$x[p], .y_Loc=plot_Loc$y[p], .x_Scale=c(0,10), .y_Scale=c(-10,0), .justify=c("center","center"), .width=chart_Width, .height=chart_Height, .colors=c("dodgerblue","blue"), .box_X=c(4,6,6,4), .box_Y=c(-4,-4,-5,-5), .plot_Title="K")
p <- 12
draw_Sample_Box(.x_Loc=plot_Loc$x[p], .y_Loc=plot_Loc$y[p], .x_Scale=c(-1,1), .y_Scale=c(0,1), .justify=c("center","center"), .width=chart_Width, .height=chart_Height, .colors=c("dodgerblue","blue"), .box_X=c(-0.5,0,0,-0.5), .box_Y=c(0.8,0.8,0.7,0.7), .plot_Title="L")

Ответ 2

ИЗМЕНИТЬ после запуска бонуса:

  • Как вычислить координаты строк: нет необходимости использовать слияние
  • Измените способ рисования связанных строк: довольно связанные строки.

enter image description here

Прежде всего, мне нужно преобразовать ваши подключенные данные из меток точек в скоординированные точки (x, y)

## here the edit 
dat.lines <- do.call(cbind,apply(connectd,2,
                                 function(x){
                                   id <- match(x,plotcord$plotname)
                                   plotcord[id,c(2,3)]}))

colnames(dat.lines) <- paste(rep(c('x','y'),3),rep(1:3,each=2),sep='')

Вот как это выглядит: dat.lines:

     x1 y1   x2 y2   x3 y3
1 1.750  2 1.50  3 2.00  3
2 5.250  2 5.00  3 5.50  3
3 1.375  1 1.00  2 1.75  2
4 3.500  1 1.75  2 5.25  2
5 6.000  1 1.75  2 5.25  2
6 7.500  1 5.25  2 8.00  2

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

library(latticeExtra))
xyplot(plotgridY~plotgridX,data= plotcord,
       panel=function(x,y,...){
     apply(dat.lines,1,function(x){
       panel.segments(x0=x['x2'],y0=x['y2'],x1=x['x3'],y1=x['y3'])
       boxh <- 0.5
       x1=x['x1']
       y1=x['y1']
       y2 <- x['y2']
       x2 <- (x['x2']+x['x3'])/2
       ydelta <- (y2 - y1)/2
       browser()
       panel.segments(c(x1, x1, x2), c(y1, y1 + ydelta, y2 - 
                                   ydelta), c(x1, x2, x2), c(y1 + ydelta, y2 - 
                                                               ydelta, y2))
     })

         panel.rect(x=x,y=y,width=unit(2,'cm'),
                    height=unit(2,'cm'),col='lightyellow')
         panel.xyplot(x,y,...)
         panel.text(x,y,adj=c(0,-3),
                    label=plotcord$plotname,cex=1.5)

         ## add some prove of concept detail 
         panel.rect(x=x,y=y,width=unit(0.5,'cm'),
                    height=unit(0.5,'cm'),col='lightblue',lty=2)
         panel.text(x,y,adj=c(1,2),
                    label=paste(plotcord$plotname,1,sep=''),cex=1,col='blue')
         panel.text(x,y,adj=c(-0.5,2),
                    label=paste(plotcord$plotname,2,sep=''),
                    cex=1,col='blue')


         },ylim=extendrange(plotcord$plotgridY,f=0.5),xlab='',ylab='', axis = axis.grid,
   main='Arrangement of large number of plots \n and connect with lines ')