แปลง shapefile บรรทัดเป็นแรสเตอร์, ค่า = ความยาวทั้งหมดของบรรทัดภายในเซลล์


14

ฉันมีไฟล์รูปร่างเส้นเป็นตัวแทนเครือข่ายถนน ฉันต้องการ rasterize ข้อมูลนี้ด้วยค่าผลลัพธ์ในแรสเตอร์ที่แสดงความยาวรวมของบรรทัดที่อยู่ในเซลล์แรสเตอร์

ข้อมูลอยู่ในการประมาณการกริดแห่งชาติของอังกฤษดังนั้นหน่วยจะเป็นเมตร

เป็นการดีที่ฉันต้องการใช้การดำเนินการนี้Rและฉันคาดเดาว่าrasterizeฟังก์ชั่นจากrasterแพคเกจจะมีส่วนร่วมในการบรรลุเป้าหมายนี้ฉันแค่ไม่สามารถทำงานออกได้ว่าควรจะใช้ฟังก์ชั่นใด


บางทีvignette('over', package = 'sp')อาจจะช่วย

คำตอบ:


12

ตามคำถามล่าสุดคุณอาจต้องการใช้ฟังก์ชันที่เสนอโดยแพ็คเกจrgeosเพื่อแก้ปัญหาของคุณ ด้วยเหตุผลของการทำซ้ำฉันดาวน์โหลดรูปร่างของถนนแทนซาเนียจากDIVA-GISและวางไว้ในไดเรกทอรีการทำงานปัจจุบันของฉัน สำหรับงานที่จะเกิดขึ้นคุณจะต้องมีสามแพ็คเกจ:

  • rgdalสำหรับการจัดการข้อมูลเชิงพื้นที่ทั่วไป
  • rasterสำหรับการแรสเตอร์ของข้อมูล shapefile
  • rgeosเพื่อตรวจสอบจุดตัดของถนนที่มีแม่แบบแรสเตอร์และคำนวณความยาวของถนน

ดังนั้นบรรทัดแรกของคุณควรมีลักษณะเช่นนี้:

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

หลังจากนั้นคุณต้องนำเข้าข้อมูลรูปร่าง โปรดทราบว่า DIVA-GIS shapefiles ถูกกระจายใน EPSG: 4326 ดังนั้นฉันจะฉายรูปร่างของไฟล์เป็น EPSG: 21037 (UTM 37S) เพื่อจัดการกับเมตรมากกว่าองศา

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

สำหรับแรสเตอร์ในภายหลังคุณจะต้องใช้เทมเพลตแรสเตอร์ที่ครอบคลุมขอบเขตเชิงพื้นที่ของรูปร่างไฟล์ของคุณ เทมเพลตแรสเตอร์ประกอบด้วย 10 แถวและ 10 คอลัมน์โดยค่าเริ่มต้นจึงหลีกเลี่ยงเวลาการคำนวณที่กว้างขวางเกินไป

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

หลังจากตั้งค่าเทมเพลตแล้วให้วนรอบทุกเซลล์ของแรสเตอร์ (ซึ่งปัจจุบันประกอบด้วยค่า NA เท่านั้น) โดยการกำหนดค่า '1' ให้กับเซลล์ปัจจุบันและดำเนินการในภายหลังrasterToPolygonsไฟล์รูปร่างที่ได้ผลลัพธ์ 'tmp_shp' จะเก็บขอบเขตของพิกเซลที่ประมวลผลในปัจจุบันโดยอัตโนมัติ gIntersectsตรวจพบว่าขอบเขตนี้ทับซ้อนกับถนนหรือไม่ มิฉะนั้นฟังก์ชันจะส่งคืนค่า '0' มิฉะนั้น shapefile ถนนถูกตัดโดยเซลล์ปัจจุบันและความยาวรวมของ 'SpatialLines' 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)
  }
})

สุดท้ายคุณสามารถแทรกความยาวที่คำนวณได้ (ซึ่งถูกแปลงเป็นกิโลเมตร) ลงในเทมเพลตแรสเตอร์และตรวจสอบผลลัพธ์ของคุณ

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


นี่มันเจ๋งมาก! ผมเปลี่ยนsapply()ไปใช้อาร์กิวเมนต์คลัสเตอร์pbsapply() cl = detectCores()-1ตอนนี้ฉันสามารถรันตัวอย่างนี้แบบขนาน!
philiporlando

11

ด้านล่างนี้ได้รับการแก้ไขจากโซลูชันของ Jeffrey Evans วิธีนี้เร็วกว่ามากเนื่องจากไม่ได้ใช้ rasterize

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

ดูเหมือนว่าวิธีการที่มีประสิทธิภาพและสวยงามที่สุดของรายการเหล่านั้น นอกจากนี้ยังไม่เคยเห็นมาก่อนผมชอบที่มันรวมคุณลักษณะของคุณลักษณะตัดที่แตกต่างจากraster::intersect() rgeos::gIntersection()
แมตต์เอสเอ็ม

+1 ดีเสมอที่เห็นโซลูชันที่มีประสิทธิภาพมากขึ้น!
Jeffrey Evans

@ Robert ฉันพยายามใช้วิธีแก้ปัญหานี้สำหรับปัญหาอื่นที่ฉันต้องการทำเช่นเดียวกับที่ถามในหัวข้อนี้ แต่ด้วยรูปร่างไฟล์ขนาดใหญ่ของถนน (สำหรับทั้งทวีป) ดูเหมือนว่าจะได้ผล แต่เมื่อฉันพยายามทำร่างตามที่ @ fdetsch ฉันไม่ได้รับกริดที่ต่อเนื่องกัน แต่มีเพียงสองสามสีในรูปภาพ (ดูในtinypic.com/r/20hu87k/9 )
Doon_Bogan

และด้วยประสิทธิภาพสูงสุด ... ด้วยชุดข้อมูลตัวอย่างของฉัน: รันไทม์ 0.6sec สำหรับโซลูชันนี้เทียบกับ 8.25sec สำหรับโซลูชัน upvotes ที่สุด
user3386170

1

คุณไม่จำเป็นต้องห่วง เพียงแค่ตัดทุกอย่างพร้อมกันแล้วเพิ่มความยาวของบรรทัดในส่วนของบรรทัดใหม่โดยใช้ฟังก์ชัน "SpatialLinesLengths" ใน sp จากนั้นใช้ฟังก์ชั่นแรสเตอร์แพ็คเกจ rasterize กับอาร์กิวเมนต์ fun = sum คุณสามารถสร้างแรสเตอร์ด้วยผลรวมของความยาวบรรทัดที่ตัดกันแต่ละเซลล์ การใช้คำตอบข้างต้นและข้อมูลที่เกี่ยวข้องที่นี่คือรหัสที่จะสร้างผลลัพธ์เดียวกัน

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))

SpatialLinesLengthsครั้งแรกที่ผมเห็น คาดเดาว่ามันจะไม่สายเกินไปที่จะเรียนรู้ขอบคุณ (: rasterizeใช้เวลาค่อนข้างนาน ((ยาวกว่าวิธีที่สูงกว่าบนเครื่องของฉัน 7 เท่า)
fdetsch

ฉันสังเกตว่า rasterize กำลังช้า อย่างไรก็ตามสำหรับปัญหาใหญ่ a สำหรับลูปจะทำให้สิ่งต่าง ๆ ช้าลงและฉันคิดว่าคุณจะเห็นโซลูชันที่ปรับให้เหมาะสมยิ่งขึ้นด้วยการแรสเตอร์ นอกจากนี้ผู้พัฒนาแพคเกจแรสเตอร์พยายามที่จะทำให้ทุกรุ่นมีประสิทธิภาพมากขึ้นและเร็วขึ้น
Jeffrey Evans

ปัญหาที่อาจเกิดขึ้นอย่างหนึ่งที่ฉันพบด้วยเทคนิคนี้คือrasterize()ฟังก์ชั่นรวมทุกบรรทัดที่สัมผัสเซลล์ที่ระบุ ซึ่งส่งผลให้ความยาวของส่วนบรรทัดถูกนับเป็นสองเท่าในบางกรณี: หนึ่งครั้งในเซลล์ที่พวกเขาควรจะและอีกครั้งในเซลล์ที่อยู่ติดกันที่จุดสิ้นสุดบรรทัดเพียงแค่สัมผัส
แมตต์เอสเอ็ม

ใช่ แต่ "rp" เป็นวัตถุที่มีการแรสเตอร์ซึ่งเป็นจุดตัดของรูปหลายเหลี่ยมและจุด
Jeffrey Evans

1

นี่คือวิธีการอื่น มันเบี่ยงเบนจากที่ได้รับมาแล้วจากการใช้spatstatแพ็คเกจ เท่าที่ฉันจะบอกได้แพ็คเกจนี้มีเวอร์ชั่นของวัตถุเชิงพื้นที่ (เช่นimกับrasterวัตถุ) แต่maptoolsแพ็คเกจอนุญาตให้ทำการแปลงไปมาระหว่างspatstatวัตถุกับวัตถุเชิงพื้นที่มาตรฐาน

วิธีการนี้จะนำมาจากนี้ R-sig-Geo โพสต์

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

บิตที่ช้าที่สุดคือการแปลงถนนจากSpatialLinesเป็นรูปแบบส่วนของเส้น (เช่นspatstat::psp) เมื่อเสร็จแล้วชิ้นส่วนการคำนวณความยาวจริงจะค่อนข้างรวดเร็วแม้จะมีความละเอียดสูงกว่ามาก ตัวอย่างเช่น MacBook รุ่นเก่าของฉัน:

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 

อืมมม ... ฉันแน่ใจว่าหวังว่าขวานเหล่านั้นจะไม่ได้อยู่ในเครื่องหมายทางวิทยาศาสตร์ ใครมีความคิดวิธีการแก้ไขนั้น
แมตต์เอสเอ็ม

คุณสามารถปรับเปลี่ยนการตั้งค่าส่วนกลาง R และปิดสัญกรณ์โดยใช้: ตัวเลือก (scipen = 999)) อย่างไรก็ตามฉันไม่ทราบว่าตาข่ายจะปฏิบัติตามการตั้งค่าสภาพแวดล้อมทั่วโลกหรือไม่
Jeffrey Evans

0

ผมขอนำเสนอแพคเกจหลอดเลือดดำที่มีฟังก์ชั่นหลายอย่างในการทำงานกับเส้นอวกาศและนำเข้าsfและdata.table

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

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่


-1

สิ่งนี้อาจฟังดูไร้เดียงสา แต่ถ้าเป็นระบบถนนให้เลือกถนนและบันทึกลงในคลิปบอร์ดแล้วมองหาเครื่องมือที่ช่วยให้คุณเพิ่มบัฟเฟอร์ไปยังคลิปบอร์ดตั้งค่าความกว้างตามกฎหมายของถนนเช่น 3 เมตร +/- โปรดจำไว้ว่าบัฟเฟอร์นั้นมาจากเส้นกลางถึงขอบ * 2 i สำหรับแต่ละด้านดังนั้นบัฟเฟอร์ 3 เมตรเป็นถนน 6 เมตรจากทางด้านข้าง


ความกว้างของถนนเกี่ยวข้องกับความยาวของถนนอย่างไร คำตอบนี้ไม่ได้ตอบคำถาม
alphabetasoup
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.