2013-01-18 62 views
13

我想我的地理座標從度到小數轉換,我的數據如下:轉換地理距離度座標轉換爲十進制

  lat  long 
105252 30°25.264 9°01.331 
105253 30°39.237 8°10.811 
105255 31°37.760 8°06.040 
105258 31°41.190 8°06.557 
105259 31°41.229 8°06.622 
105260 31°38.891 8°06.281 

我有這樣的代碼,但我不明白爲什麼它不工作:

convert<-function(coord){ 
tmp1=strsplit(coord,"°") 
tmp2=strsplit(tmp1[[1]][2],"\\.") 
dec=c(as.numeric(tmp1[[1]][1]),as.numeric(tmp2[[1]])) 
return(dec[1]+dec[2]/60+dec[3]/3600) 
} 
don_convert=don1 
for(i in 1:nrow(don1)){don_convert[i,2]=convert(as.character(don1[i,2]));    don_convert[i,3]=convert(as.character(don1[i,3]))} 

轉換函數的工作原理,但我要求循環爲我做這項工作的代碼不起作用。

任何建議都可以解決。

+1

它看起來像轉換功能期望度,分鐘和秒,但你的輸入似乎有度和浮點分鐘,沒有秒字段。它看起來並不像正確處理負值。但不確定這些問題是否與您的問題有關。 –

回答

4

矢量和矩陣操作的一點會讓你的功能要簡單得多:

x <- read.table(text=" 
     lat  long 
105252 30°25.264 9°01.331 
105253 30°39.237 8°10.811 
105255 31°37.760 8°06.040 
105258 31°41.190 8°06.557 
105259 31°41.229 8°06.622 
105260 31°38.891 8°06.281", 
       header=TRUE, stringsAsFactors=FALSE) 

x 

函數本身利用了:

  • strsplit()與正則表達式模式"[°\\.]" - 這確實字符串分割在一個步驟中
  • sapply以遍歷載體

試試這個:

convert<-function(x){ 
    z <- sapply((strsplit(x, "[°\\.]")), as.numeric) 
    z[1, ] + z[2, ]/60 + z[3, ]/3600 
} 

試試:

convert(x$long) 
[1] 9.108611 8.391944 8.111111 8.254722 8.272778 8.178056 

免責聲明:我沒有檢查你的數學。自行決定使用。

5

嘗試使用sp庫中的char2dms函數。它還有其他功能,將額外做十進制轉換。

library("sp") 
?char2dms 
0

正如Jim Lewis評論之前似乎您使用的是浮點分鐘。然後,你只串連上

癸= C兩個元件(as.numeric(TMP1 [[1]] [1]),as.numeric(TMP2 [[1]]))

有度,分,秒的形式43°21'8.02這as.character()返回「43°21'8.02 \」」我是你的功能更新,以

convert<-function(coord){ 
    tmp1=strsplit(coord,"°") 
    tmp2=strsplit(tmp1[[1]][2],"'") 
    tmp3=strsplit(tmp2[[1]][2],"\"") 
    dec=c(as.numeric(tmp1[[1]][1]),as.numeric(tmp2[[1]][1]),as.numeric(tmp3[[1]])) 
    c<-abs(dec[1])+dec[2]/60+dec[3]/3600 
    c<-ifelse(dec[1]<0,-c,c) 
    return(c) 
} 

增加對負座標的選擇,以及偉大工程我仍然沒有得到爲什麼char2dms功能在sp庫二不爲我工作。

謝謝

0

另一個不太優雅的選項使用子字符串,而不是strsplit。這隻有在您的所有職位都有相同的數字位數時纔有效。對於負座標,正確的小數點乘以-1。

x$LatDD<-(as.numeric(substring(x$lat, 1,2)) 
+ (as.numeric(substring(x$lat, 4,9))/60)) 
x$LongDD<-(as.numeric(substring(x$long, 1,1)) 
     + (as.numeric(substring(x$long, 3,8))/60)) 
12

使用來自CRAN的measurements包,它已經具備了單元轉換功能,所以你不需要讓自己:

x = read.table(text = " 
    lat  long 
105252 30°25.264 9°01.331 
105253 30°39.237 8°10.811 
105255 31°37.760 8°06.040 
105258 31°41.190 8°06.557 
105259 31°41.229 8°06.622 
105260 31°38.891 8°06.281", 
header = TRUE, stringsAsFactors = FALSE) 

一旦你的data.frame設置則:

# change the degree symbol to a space 
x$lat = gsub('°', ' ', x$lat) 
x$long = gsub('°', ' ', x$long) 

# convert from decimal minutes to decimal degrees 
x$lat = measurements::conv_unit(x$lat, from = 'deg_dec_min', to = 'dec_deg') 
x$long = measurements::conv_unit(x$long, from = 'deg_dec_min', to = 'dec_deg') 

中端產品所造成:

    lat    long 
105252 30.4210666666667 9.02218333333333 
105253   30.65395 8.18018333333333 
105255 31.6293333333333 8.10066666666667 
105258   31.6865 8.10928333333333 
105259   31.68715 8.11036666666667 
105260 31.6481833333333 8.10468333333333 
+1

這可能是最簡單的解決方案(也可以免費獲得其他座標轉換)。我只想補充一點,現在這個功能已經被移動到'measurements'包中,並且在'birk'中被棄用。 –

+0

謝謝戈德!我忘了更新這個。 – CephBirk

0

感謝@Gord Stephen和@CephBirk的回答。當然幫助我。 我想我只是提到,我還發現measurements::conv_unit不處理「E/W」「N/S」條目,它需要積極/消極的程度。我的座標是字符串"1 1 1W",需要先轉換爲"-1 1 1"
我想我會分享我的解決方案。

df <- c("1 1 1E", "1 1 1W", "2 2 2N","2 2 2S") 
measurements::conv_unit(df, from = 'deg_min_sec', to = 'dec_deg') 
[1] "1.01694444444444" NA     NA     NA 
Warning message: 
In split(as.numeric(unlist(strsplit(x, " "))) * c(3600, 60, 1), : 
    NAs introduced by coercion 

ewns <- ifelse(str_extract(df,"\\(?[EWNS,.]+\\)?") %in% c("E","N"),"+","-") 
dms <- str_sub(df,1,str_length(df)-1) 
df2 <- paste0(ewns,dms) 

df_dec <- measurements::conv_unit(df2, 
            from = 'deg_min_sec', 
            to = 'dec_deg')) 
df_dec 
[1] "1.01694444444444" "-1.01694444444444" "2.03388888888889" "-2.03388888888889" 
as.numeric(df_dec) 
[1] 1.016944 -1.016944 2.033889 -2.033889