Удобная оболочка для графиков, линий и точек
Одна из вещей, которая меня больше всего беспокоит в R, это разделение команд графика, точек и линий. Несколько раздражает необходимость менять график на какой-либо вариант для первого сделанного графика и выполнять повторный график с нуля, если вы изначально не установили правильные значения ylim и xlim. Не было бы неплохо иметь одну команду, которая:
Выбирает линии, точки или оба через аргумент, как в
plot(..., type = "l")
?По умолчанию выбирается, создавать ли новый график или добавлять к существующему в зависимости от того, является ли текущее устройство пустым или нет.
Масштабирует оси автоматически, если добавленные элементы на график превышают текущие границы.
Кто-нибудь сделал что-нибудь подобное? Если нет, и нет веских причин, почему это невозможно, я сам на это отвечу немного...
2 ответа
Некоторые возможные функции, которые могут помочь с тем, что вы хотите:
matplot
Функция использует базовую графику и построит несколько наборов точек или линий за один шаг, определив правильные диапазоны за один шаг.
Есть update
метод для решетчатой графики, который можно использовать для добавления / изменения объектов на графике и, следовательно, приведет к автоматическому пересчету таких вещей, как пределы и оси.
Если вы добавите дополнительную информацию (используя +
) на график ggplot2, то вещи, которые автоматически рассчитываются, будут пересчитаны.
Вы уже нашли zoomplot
и всегда есть подход написания вашей собственной функции, как вы сделали.
Во всяком случае, это то, что я придумал: (Он использует zoomplot
от TeachingDemos
)
fplot <- function(x, y = NULL, type = "l", new = NULL, xlim, ylim, zoom = TRUE,...){
require(TeachingDemos)
if (is.null(y)){
if (length(dim(x)) == 2){
y = x[,2]
x = x[,1]
} else {
y = x
x = 1:length(y)
}
}
if ( is.null(new) ){
#determine whether to make a new plot or not
new = FALSE
if (is.null(recordPlot()[[1]])) new = TRUE
}
if (missing(xlim)) xlim = range(x)
if (missing(ylim)) ylim = range(y)
if (new){
plot(x, y, type = type, xlim = xlim, ylim = ylim, ...)
} else {
if (type == "p"){
points(x,y, ...)
} else {
lines(x,y, type = type, ...)
}
if (zoom){
#rescale plot
xcur = par("usr")[1:2]
ycur = par("usr")[3:4]
#shrink coordinates and pick biggest
xcur = (xcur - mean(xcur)) /1.08 + mean(xcur)
ycur = (ycur - mean(ycur)) /1.08 + mean(ycur)
xlim = c(min(xlim[1], xcur[1]), max(xlim[2], xcur[2]))
ylim = c(min(ylim[1], ycur[1]), max(ylim[2], ycur[2]))
#zoom plot
zoomplot(xlim, ylim)
}
}
}
Так что вы можете сделать, например,
dev.new()
fplot(1:4)
fplot(1:4 +1, col = 2)
fplot(0:400/100 + 1, sin(0:400/10), type = "p")
dev.new()
for (k in 1:20) fplot(sort(rnorm(20)), type = "b", new = (k==1) )
par(mfrow) и логарифмическая ось в настоящее время плохо работают с масштабированием, но это начало...