1

所以我正在创建映射函数,它用点绘制各种端口的坐标。我想创建一个功能,允许用户选择他们想要标记的端口,然后更改标签位置。

以下是各个港口及其坐标:

           Labels       Lon      Lat
1     Halifax, NS -63.59341 44.68068
2  St. John's, NL -52.73304 47.59341
3  Saint John, NB -66.05236 45.27925
4    Portland, ME -70.24435 43.68068
5  Woods Hole, MA -70.68068 41.62832
6 Nuuk, Greenland -51.75049 64.17453
7      Boston, MA -71.08727 42.36652

我的功能:

    port.label <- function (pos1, cex1 = 0.6, offset1 = 0.2, col1 = "deeppink") {
      port.file<-read.csv("V:/Science/Finalised Map Files/Ports.csv")
      Lon <- port.file$Lon
      Lat <- port.file$Lat
      Lab <- paste(port.file$Lab) 
      a <- locator()
      ay <- unlist(a[2])
      aylab <- sapply (ay, function (x) which.min (abs (x - Lat)))
      b <- for (i in (1:length (aylab))) {
        text (x = Lon [aylab[i]], y = Lat [aylab[i]], labels = Lab [aylab[i]],
        pos = pos1, cex = cex1, offset = offset1, col = col1) 
      }
    }

现在,当我尝试使用以下命令运行它时:port.label(pos1=c(1,2,3,4))单击四个点后,它仅使用第一个值 (1) 返回标签,因此低于该点。所以它只取第一个值。我尝试将 pos1 长度预先设置为与单击的端口数相关,但这也无济于事。

关于为什么它只取第一个 pos1 值而不是整个向量的任何想法?谢谢。

4

2 回答 2

1

嗯,因为对于 text() 的每次调用,您都使用完整的向量来调用它。由于每次调用仅针对一个标签,因此您需要使用pos=pos1[i]. 不幸的是,只使用 1 个参数调用 port.label 将需要额外检查 pos1() 长度。比如说,你想让所有标签都在同一个位置,底部,所以你调用port.label( pos1= 1 ). 有了i=2pos1[i]就会取值NApos1因此,如果它的长度等于 1 ,您将不得不展开。

像这样称呼它会更有效:

port.label <- function (pos1, cex1 = 0.6, offset1 = 0.2, col1 = "deeppink") {
  port.file<-read.csv("V:/Science/Finalised Map Files/Ports.csv")
  Lon <- port.file$Lon
  Lat <- port.file$Lat
  Lab <- paste(port.file$Lab) 
  a <- locator()
  ay <- unlist(a[2])
  aylab <- sapply (ay, function (x) which.min (abs (x - Lat)))
  text( x= Lon[aylab], y= Lat[aylab], labels= Lab[aylab], 
        pos= pos1, cex= cex1, offset= offset1, col= col1 )
}
于 2013-07-10T17:57:54.730 回答
0

It's helpful to use dput to output your data in a form that easier for readers to run in R.

mydat <- structure(list(Lab = c("Halifax, NS", "St. John's, NL", "Saint John, NB", 
    "Portland, ME", "Woods Hole, MA", "Nuuk, Greenland", "Boston, MA"), 
    Lon = c(-63.59341, -52.73304, -66.05236, -70.24435, -70.68068, -51.75049, -71.08727), 
    Lat = c(44.68068, 47.59341, 45.27925, 43.68068, 41.62832, 64.17453, 42.36652)), 
    .Names = c("Labels", "Lon", "Lat"), class = "data.frame", row.names = c(NA, -7L))

It's not at all clear to me why you would want a function that does this. I'm thinking there may be a better way to do what you really want to do. But, here is an attempt to modify your code so that it does what you want. I made use of the identify() function as @droopy suggested.

port.label <- function (data, posn, cex1=0.6, offset1=0.2, col1="deeppink") {
    j <- identify(mydat$Lon, mydat$Lat, mydat$Lab, plot=FALSE)
    for(i in 1:length(j)) {
        text(x=data$Lon[j[i]], y=data$Lat[j[i]], labels=data$Lab[j[i]], pos=posn[i], cex=cex1, offset=offset1, col=col1)
        }
    }

plot(mydat$Lon, mydat$Lat)
port.label(mydat, posn=c(1, 2, 3, 4))
于 2013-07-10T18:11:57.457 回答