Çizgi şekil dosyasını raster biçimine dönüştürün, değer = hücre içindeki satırların toplam uzunluğu


14

Bir yol ağını temsil eden bir çizgi şekil dosyam var. Rasterdeki sonuç değerleri, hücre hücresine düşen çizgilerin toplam uzunluğunu gösterecek şekilde bu verileri rasterleştirmek istiyorum.

Veriler İngiliz Ulusal Şebeke projeksiyonundadır, böylece birimler metre olacaktır.

İdeal olarak bu işlemi kullanarak yapmak istiyorum ve paketin fonksiyonunun bunu başarmada bir rol oynayacağını Rtahmin ediyorum, sadece uygulanan fonksiyonun ne olması gerektiğini çalışamıyorum.rasterizeraster


Belki vignette('over', package = 'sp')yardımcı olabilir.

Yanıtlar:


12

Yakın tarihli bir soruyu takiben , sorununuzu çözmek için rgeos paketi tarafından sunulan işlevlerden faydalanmak isteyebilirsiniz . Tekrarlanabilirlik nedeniyle, DIVA- GIS'ten Tanzanya yollarının şekil dosyasını indirdim ve mevcut çalışma dizinime koydum. Gelecek görevler için üç pakete ihtiyacınız olacak:

  • Genel konumsal veri işleme için rgdal
  • şekil dosyası verilerinin rasterleştirilmesi için raster
  • Raster şablonu ile yolların kesişimini kontrol etmek ve yol uzunluklarını hesaplamak için rgeos

Sonuç olarak, ilk satırlarınız şöyle görünmelidir:

library(rgdal)
library(raster)
library(rgeos)

Bundan sonra şekil dosyası verilerini içe aktarmanız gerekir. DIVA-GIS şekil dosyalarının EPSG: 4326'da dağıtıldığını, bu nedenle şekil dosyasını derece yerine metre ile başa çıkmak için EPSG: 21037'ye (UTM 37S) yansıtacağım.

roads <- readOGR(dsn = ".", layer = "TZA_roads")
roads_utm <- spTransform(roads, CRS("+init=epsg:21037"))

Sonraki rasterleştirme için, şekil dosyanızın uzamsal boyutunu kapsayan bir raster şablonuna ihtiyacınız olacaktır. Raster şablonu varsayılan olarak 10 satır ve 10 sütundan oluşur, bu nedenle çok kapsamlı hesaplama sürelerinden kaçınır.

roads_utm_rst <- raster(extent(roads_utm), crs = projection(roads_utm))

Şablon ayarlandığına göre, rasterdeki tüm hücreler arasında döngü yapın (şu anda yalnızca NA değerlerinden oluşmaktadır). Geçerli hücreye '1' değeri atayarak ve daha sonra çalıştırarak rasterToPolygons, elde edilen 'tmp_shp' şekil dosyası o anda işlenen pikselin boyutunu otomatik olarak tutar. gIntersectsbu boyutun yollarla örtüşüp örtüşmediğini tespit eder. Değilse, işlev '0' değerini döndürür. Aksi takdirde, yol şekil dosyası geçerli hücre tarafından kırpılır ve o hücre içindeki toplam 'SpatialLines' uzunluğu kullanılarak hesaplanır gLength.

lengths <- sapply(1:ncell(roads_utm_rst), function(i) {
  tmp_rst <- roads_utm_rst
  tmp_rst[i] <- 1
  tmp_shp <- rasterToPolygons(tmp_rst)

  if (gIntersects(roads_utm, tmp_shp)) {
    roads_utm_crp <- crop(roads_utm, tmp_shp)
    roads_utm_crp_length <- gLength(roads_utm_crp)
    return(roads_utm_crp_length)
  } else {
    return(0)
  }
})

Son olarak, hesaplanan uzunlukları (kilometreye dönüştürülen) raster şablonuna ekleyebilir ve sonuçlarınızı görsel olarak doğrulayabilirsiniz.

roads_utm_rst[] <- lengths / 1000

library(RColorBrewer)
spplot(roads_utm_rst, scales = list(draw = TRUE), xlab = "x", ylab = "y", 
       col.regions = colorRampPalette(brewer.pal(9, "YlOrRd")), 
       sp.layout = list("sp.lines", roads_utm), 
       par.settings = list(fontsize = list(text = 15)), at = seq(0, 1800, 200))

lines2raster


Bu harika! Değiştim sapply()için pbsapply()ve küme argümanı kullanılır cl = detectCores()-1. Şimdi bu örneği paralel çalıştırabiliyorum!
philiporlando

11

Aşağıdakiler Jeffrey Evans'ın çözeltisinden değiştirilmiştir. Rasterleştirme kullanmadığından bu çözüm çok daha hızlıdır

library(raster)
library(rgdal)
library(rgeos)

roads <- shapefile("TZA_roads.shp")
roads <- spTransform(roads, CRS("+proj=utm +zone=37 +south +datum=WGS84"))
rs <- raster(extent(roads), crs=projection(roads))
rs[] <- 1:ncell(rs)

# Intersect lines with raster "polygons" and add length to new lines segments
rsp <- rasterToPolygons(rs)
rp <- intersect(roads, rsp)
rp$length <- gLength(rp, byid=TRUE) / 1000
x <- tapply(rp$length, rp$layer, sum)
r <- raster(rs)
r[as.integer(names(x))] <- x

Listelenenlerin en verimli ve zarif yöntemi gibi görünüyor. Ayrıca, daha raster::intersect() önce görmemiştim , aksine kesişen özelliklerin özelliklerini birleştirmeyi seviyorum rgeos::gIntersection().
Matt SM

+1 daha verimli çözümler görmek her zaman güzel!
Jeffrey Evans

@RobertH, başka bir sorun için bu çözümü kullanmayı denedim, burada bu konuda sorulanla aynı şeyi yapmak istiyorum, ancak yolların çok büyük bir şekil dosyasıyla (tüm bir kıta için). Çalışmış gibi görünüyor, ancak @ fdetsch tarafından yapılan şekli yapmaya çalıştığımda, bitişik bir ızgara almıyorum, ancak resimde sadece birkaç renkli kare var (bkz. Tinypic.com/r/20hu87k/9 ).
Doon_Bogan

Ve en verimli şekilde ... örnek veri setimle: bu çözüm için çalışma süresi 0.6sn, en yüksek puanlar çözümü için 8.25sn.
user3386170

1

For döngüsüne ihtiyacınız yoktur. Her şeyi bir kerede kesiştirin ve sonra sp'deki "SpatialLinesLengths" işlevini kullanarak yeni çizgi segmentlerine satır uzunlukları ekleyin. Daha sonra, raster paket rasterize işlevini fun = sum argümanıyla kullanarak, her bir hücreyi kesişen satır uzunluklarının toplamıyla bir raster oluşturabilirsiniz. Yukarıdaki yanıtı ve ilişkili verileri burada kullanmak, aynı sonuçları üretecek koddur.

require(rgdal)
require(raster)
require(sp)
require(rgeos)

setwd("D:/TEST/RDSUM")
roads <- readOGR(getwd(), "TZA_roads")
  roads <- spTransform(roads, CRS("+init=epsg:21037"))
    rrst <- raster(extent(roads), crs=projection(roads))

# Intersect lines with raster "polygons" and add length to new lines segments
rrst.poly <- rasterToPolygons(rrst)
  rp <- gIntersection(roads, rrst.poly, byid=TRUE)
    rp <- SpatialLinesDataFrame(rp, data.frame(row.names=sapply(slot(rp, "lines"), 
                               function(x) slot(x, "ID")), ID=1:length(rp), 
                               length=SpatialLinesLengths(rp)/1000) ) 

# Rasterize using sum of intersected lines                            
rd.rst <- rasterize(rp, rrst, field="length", fun="sum")

# Plot results
require(RColorBrewer)
spplot(rd.rst, scales = list(draw=TRUE), xlab="x", ylab="y", 
       col.regions=colorRampPalette(brewer.pal(9, "YlOrRd")), 
       sp.layout=list("sp.lines", rp), 
       par.settings=list(fontsize=list(text=15)), at=seq(0, 1800, 200))

İlk gördüğümde SpatialLinesLengths. Öğrenmek için asla geç değildir, teşekkür ederim (: rasterizeoldukça uzun sürüyor, ancak (makinemdeki üst yaklaşımdan 7 kat daha uzun).
fdetsch

Rasterleştirmenin yavaş olduğunu fark ettim. Ancak, büyük problemler için bir for döngüsü gerçekten işleri yavaşlatacak ve rasterleştirmeyle çok daha optimize edilmiş bir çözüm göreceğinizi düşünüyorum. Ayrıca raster paketinin geliştiricisi, her sürümü daha optimize ve daha hızlı hale getirmek için çalışıyor.
Jeffrey Evans

Bu teknikle bulduğum potansiyel bir sorun, rasterize()fonksiyonun belirli bir hücreye temas eden tüm çizgileri içermesidir . Bu, çizgi segment uzunluklarının bazı durumlarda iki kez sayılmasıyla sonuçlanır: bir kez hücrede olması ve bir kez çizginin uç noktasının dokunduğu bitişik hücrede.
Matt SM

Evet, ancak "rp" çokgenlerin ve noktaların kesiştiği rasterleştirilen nesnedir.
Jeffrey Evans

1

İşte başka bir yaklaşım. spatstatPaketi kullanarak daha önce verilenlerden farklıdır . Anlayabildiğim kadarıyla, bu paketin mekansal nesnelerin (ör. Nesneler imvs. raster) kendi sürümleri vardır , ancak maptoolspaket spatstatnesneler ve standart mekansal nesneler arasında ileri geri dönüşüme izin verir .

Bu yaklaşım, bu R-sig-Geo görevinden alınmıştır .

require(sp)
require(raster)
require(rgdal)
require(spatstat)
require(maptools)
require(RColorBrewer)

# Load data and transform to UTM
roads <- shapefile('data/TZA_roads.shp')
roadsUTM <- spTransform(roads, CRS("+init=epsg:21037"))

# Need to convert to a line segment pattern object with maptools
roadsPSP <- as.psp(as(roadsUTM, 'SpatialLines'))

# Calculate lengths per cell
roadLengthIM <- pixellate.psp(roadsUTM, dimyx=10)

# Convert pixel image to raster in km
roadLength <- raster(dtanz / 1000, crs=projection(roadsUTM))

# Plot
spplot(rtanz, scales = list(draw=TRUE), xlab="x", ylab="y", 
       col.regions=colorRampPalette(brewer.pal(9, "YlOrRd")), 
       sp.layout=list("sp.lines", roadsUTM), 
       par.settings=list(fontsize=list(text=15)), at=seq(0, 1800, 200))

Imgur

En yavaş bit, yolları SpatialLinesbir Çizgi Segmenti Paternine (yani spatstat::psp) dönüştürmektir. Bu yapıldıktan sonra, gerçek uzunluk hesaplama parçaları çok daha yüksek çözünürlüklerde bile oldukça hızlıdır. Örneğin, eski 2009 MacBook'umda:

system.time(pixellate(tanzpsp, dimyx=10))
#    user  system elapsed 
#   0.007   0.001   0.007

system.time(pixellate(tanzpsp, dimyx=1000))
#    user  system elapsed 
#   0.146   0.032   0.178 

Hmmmm ... Eminim bu eksenler bilimsel gösterimde olmasaydı. Bunu nasıl düzeltebilecek kimse var mı?
Matt SM

Küresel R ayarlarını değiştirebilir ve gösterimi kullanarak kapatabilirsiniz: options (scipen = 999)), ancak kafesin global ortam ayarlarına uyup uymayacağını bilmiyorum.
Jeffrey Evans

0

Size uzaysal çizgileri çalışmak ve sf ve data almak için çeşitli işlevlerle paket damarını sunmama izin verin.

library(vein)
library(sf)
library(cptcity)
data(net)
netsf <- st_as_sf(net) #Convert Spatial to sf
netsf <- st_transform(netsf, 31983) # Project data
netsf$length_m  <- st_length(netsf)
netsf <- netsf[, "length_m"]
g <- make_grid(netsf, width = 1000) #Creat grid of 1000m spacing with columns id for each feature
# Number of lon points: 12
# Number of lat points: 11

gnet <- emis_grid(netsf, g)
plot(gnet["length_m"])

sf_to_raster <- function(x, column, ncol, nrow){
  x <- sf::as_Spatial(x)
  r <- raster::raster(ncol = ncol, nrow = nrow)
  raster::extent(r) <- raster::extent(x)
  r <- raster::rasterize(x, r, column)
  return(r)
}

rr <- sf_to_raster(gnet, "length_m", 12, 11)
spplot(rr, sp.layout = list("sp.lines", as_Spatial(netsf)),
       col.regions = cpt(), scales = list(draw = T))
spplot(rr, sp.layout = list("sp.lines", as_Spatial(netsf)),
       col.regions = cpt(pal = 5176), scales = list(draw = T))
spplot(rr, sp.layout = list("sp.lines", as_Spatial(netsf)),
       col.regions = lucky(), scales = list(draw = T))
# Colour gradient: neota_flor_apple_green, number: 6165

resim açıklamasını buraya girin

resim açıklamasını buraya girin

resim açıklamasını buraya girin


-1

Bu biraz naif gelebilir, ancak bir yol sistemi ise yolları seçin ve bir klibi panosuna kaydedin, sonra panoya bir tampon eklemenize izin veren bir araç bulun, böylece yolun yasal genişliğine ayarlayın, yani 3 metre +/- arabellek her iki taraf için orta çizgiden kenara * 2 i olduğunu unutmayın, bu nedenle 3 metrelik bir tampon aslında yan yana 6 metrelik bir yoldur.


Yol genişliğinin yol uzunluğu ile ne ilgisi vardır. Bu cevap soruyu ele almıyor.
alphabetasoup
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.