Исправление данных библиотеки карт для отображения по центру Тихого океана (долгота 0°-360°)
Я строю некоторые точки на карте мира, используя R maps
пакет, что-то вроде:
Команда для рисования базовой карты:
map("world", fill=TRUE, col="white", bg="gray", ylim=c(-60, 90), mar=c(0,0,0,0))
Но мне нужно отобразить карту по центру Тихого океана. я использую map("world2",
и т. д. использовать центральную карту по центру Тихого океана из пакета карт и преобразовывать координаты точек данных в моем фрейме данных (df
) с:
df$longitude[df$longitude < 0] = df$longitude[df$longitude < 0] + 360
Это работает, если я не использую fill
вариант, но с fill
многоугольники, которые пересекают 0°, вызывают проблемы.
Я думаю, мне нужно преобразовать данные многоугольника из maps
библиотека как-то разобраться, но я понятия не имею, как этого добиться.
Моим идеальным решением было бы нарисовать карты с левой границей под -20° и правой границей под -30° (то есть 330°). Следующее получает правильные точки и береговые линии на карту, но проблема пересечения нуля та же
df$longitude[df$longitude < -20] = df$longitude[d$longitude < -20] + 360
map("world", fill=TRUE, col="white", bg="gray", mar=c(0,0,0,0),
ylim=c(-60, 90), xlim=c(-20, 330))
map("world2", add=TRUE, col="white", bg="gray", fill=TRUE, xlim=c(180, 330))
Любая помощь будет принята с благодарностью.
4 ответа
Вы могли бы использовать тот факт, что внутри map
объект, возвращаемый map()
Функция может быть пересчитана и использована снова в map()
функция. Я бы создал список с отдельными полигонами, проверил, какие из них имеют очень разные значения долготы, и переставил бы их. Я привел пример такого подхода в функции ниже *, которая позволяет что-то вроде:
plot.map("world", center=180, col="white",bg="gray",
fill=TRUE,ylim=c(-60,90),mar=c(0,0,0,0))
получить
Если бы я был тобой, я бы изменил все немного больше, как в:
plot.map("world", center=200, col="white",bg="gray",
fill=TRUE,ylim=c(-60,90),mar=c(0,0,0,0))
Функция:
plot.map<- function(database,center,...){
Obj <- map(database,...,plot=F)
coord <- cbind(Obj[[1]],Obj[[2]])
# split up the coordinates
id <- rle(!is.na(coord[,1]))
id <- matrix(c(1,cumsum(id$lengths)),ncol=2,byrow=T)
polygons <- apply(id,1,function(i){coord[i[1]:i[2],]})
# split up polygons that differ too much
polygons <- lapply(polygons,function(x){
x[,1] <- x[,1] + center
x[,1] <- ifelse(x[,1]>180,x[,1]-360,x[,1])
if(sum(diff(x[,1])>300,na.rm=T) >0){
id <- x[,1] < 0
x <- rbind(x[id,],c(NA,NA),x[!id,])
}
x
})
# reconstruct the object
polygons <- do.call(rbind,polygons)
Obj[[1]] <- polygons[,1]
Obj[[2]] <- polygons[,2]
map(Obj,...)
}
* Обратите внимание, что эта функция принимает только положительные значения центра. Он легко адаптируется для учета значений центра в обоих направлениях, но я больше не беспокоился, поскольку это тривиально.
Установите последнюю версию карт (3.2.0).
сделай это:
d$lon2 <- ifelse(d$lon < -25, d$lon + 360, d$lon) # where d is your df
mapWorld <- map_data('world', wrap=c(-25,335), ylim=c(-55,75))
ggplot() +
geom_polygon(data = mapWorld, aes(x=long, y = lat, group = group)) +
geom_point(data = d, aes(x = lon2, y = lat))
Немного поздно, но вы также можете создать сдвинутую карту с помощью проекции (требуется пакет mapproj):
map("world", projection="rectangular", parameter=0,
orientation=c(90,0,180), wrap=TRUE, fill=T, resolution=0,col=0)
Это сместится на 180 градусов. Но разница с "world2" заключается в том, что координата долготы будет другой ([-pi,pi]). Все проекции этого пакета помещают 0 в центр. И в этом случае опция "обтекание" правильно определяет переход.
'resolution = 0' помогает получить более четкие границы.
Вы можете легко изменить центральную долготу, изменив значение "180" в описании проекции.
А как насчет этого решения?
xlims = c(0, 359) # these are the limits you want to change
ylims = c(-55,75)
mapWorld <- map_data('world', wrap=xlims, ylim=ylims)
head(mapWorld)
g1 <- ggplot() +
geom_polygon(data = mapWorld, aes(x=long, y = lat, group = group)) +
coord_map("rectangular", lat0=0, xlim=xlims, ylim=ylims)
g1