เหตุใด geom_tile จึงพล็อตชุดย่อยของข้อมูลของฉัน แต่ไม่มากไปกว่านั้น

ฉันกำลังพยายามพล็อตแผนที่ แต่ฉันไม่สามารถเข้าใจได้ว่าเหตุใดสิ่งต่อไปนี้จึงไม่ทำงาน:

นี่เป็นตัวอย่างเล็กๆ น้อยๆ

testdf <- structure(list(x = c(48.97, 44.22, 44.99, 48.87, 43.82, 43.16, 38.96, 38.49, 44.98, 43.9), y = c(-119.7, -113.7, -109.3, -120.6,  -109.6, -121.2, -114.2, -118.9, -109.7, -114.1), z = c(0.001216,  0.001631, 0.001801, 0.002081, 0.002158, 0.002265, 0.002298, 0.002334, 0.002349, 0.00249)), .Names = c("x", "y", "z"), row.names = c(NA, 10L), class = "data.frame")

ใช้งานได้ 1-8 แถว:

ggplot(data = testdf[1,], aes(x,y,fill = z)) + geom_tile()
ggplot(data = testdf[1:8,], aes(x,y,fill = z)) + geom_tile()

แต่ไม่ใช่สำหรับ 9 แถว:

ggplot(data = testdf[1:9,], aes(x,y,fill = z)) + geom_tile()

ท้ายที่สุดแล้ว ฉันกำลังค้นหาวิธีลงจุดข้อมูลบนตารางที่ไม่ปกติ ไม่จำเป็นที่ฉันจะใช้ geom_tile แต่การแก้ไขแบบเติมพื้นที่เหนือจุดต่างๆ จะทำได้เช่นกัน

ชุดข้อมูลทั้งหมดมีอยู่ใน gist

testdf ด้านบนคือชุดย่อยเล็กๆ ของชุดข้อมูลทั้งหมด ซึ่งเป็นแรสเตอร์ที่มีความละเอียดสูงของสหรัฐอเมริกา (>7500 แถว)

require(RCurl) # requires libcurl; sudo apt-get install libcurl4-openssl-dev
tmp <- getURL("https://gist.github.com/raw/4635980/f657dcdfab7b951c7b8b921b3a109c7df1697eb8/test.csv")
testdf <- read.csv(textConnection(x))

สิ่งที่ฉันได้ลอง:

  1. การใช้ geom_point ใช้งานได้ แต่ไม่มีเอฟเฟกต์ตามที่ต้องการ:

    ggplot(data = testdf, aes(x,y,color=z)) + geom_point()
    
  2. ถ้าฉันแปลง อย่างใดอย่างหนึ่ง x หรือ y เป็นเวกเตอร์ 1:10 โครงเรื่องจะทำงานตามที่คาดไว้:

    newdf <- transform(testdf, y =1:10)
    
    ggplot(data = newdf[1:9,], aes(x,y,fill = z)) + geom_tile()
    
    newdf <- transform(testdf, x =1:10)
    ggplot(data = newdf[1:9,], aes(x,y,fill = z)) + geom_tile()
    

sessionInfo()R version 2.15.2 (2012-10-26) Platform: x86_64-pc-linux-gnu (64-bit)


> attached base packages: [1] stats     graphics  grDevices utils    
> datasets  methods   base     

> other attached packages: [1] reshape2_1.2.2 maps_2.3-0    
> betymaps_1.0   ggmap_2.2      ggplot2_0.9.3 

> loaded via a namespace (and not attached):  [1] colorspace_1.2-0   
> dichromat_1.2-4     digest_0.6.1        grid_2.15.2        
> gtable_0.1.2        labeling_0.1         [7] MASS_7.3-23        
> munsell_0.4         plyr_1.8            png_0.1-4          
> proto_0.3-10        RColorBrewer_1.0-5  [13] RgoogleMaps_1.2.0.2
> rjson_0.2.12        scales_0.2.3        stringr_0.6.2      
> tools_2.15.2

person Abe    schedule 24.01.2013    source แหล่งที่มา
comment
คุณมีข้อมูลเพิ่มเติมเกี่ยวกับแรสเตอร์ที่ข้อมูลนั้นมาหรือไม่ เช่นข้อมูลการฉายภาพ   -  person Simon O'Hanlon    schedule 12.03.2013
comment
@SimonO101 พวกมันถูกสร้างขึ้นบนตาราง 30x30 กม   -  person Abe    schedule 12.03.2013
comment
ตกลง. คุณจะต้องทำการสุ่มตัวอย่างข้อมูลของคุณใหม่ จุดเนื่องจากมีระยะห่างไม่เท่ากัน ซึ่งเป็นสาเหตุว่าทำไมคุณจึงใช้ geom_raster หรือ geom_tile ไม่ได้ ดูคำตอบของฉันสำหรับรายละเอียดและวิธีแก้ปัญหาที่ใช้ geom_raster   -  person Simon O'Hanlon    schedule 12.03.2013
comment
ด้านล่างนี้ใช้ได้กับระบบของคุณหรือไม่?   -  person Simon O'Hanlon    schedule 12.03.2013
comment
อาเบะ - ฉันใช้การแก้ไขที่คุณแนะนำอย่างถูกต้องแล้ว แต่ผู้ตรวจสอบปฏิเสธก่อนที่ฉันจะมีโอกาสยอมรับ! คุณพูดถูก สคริปต์ต้องการ RCurl   -  person Simon O'Hanlon    schedule 12.03.2013
comment
@ SimonO101 ใช่ - มันใช้งานได้ดี ขอบคุณสำหรับคำตอบ! แต่ฉันยังคงติดอยู่ (และจะแสดงความคิดเห็นด้านล่างคำตอบของคุณ)   -  person Abe    schedule 12.03.2013


คำตอบ (4)


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

คุณควรอ่าน raster:::projection และ rgdal:::spTransform เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับการฉายภาพแผนที่

require( RCurl )
require( raster )
require( sp )
require( ggplot2 )
tmp <- getURL("https://gist.github.com/geophtwombly/4635980/raw/f657dcdfab7b951c7b8b921b3a109c7df1697eb8/test.csv")
testdf <- read.csv(textConnection(tmp))
spdf <- SpatialPointsDataFrame( data.frame( x = testdf$y , y = testdf$x ) , data = data.frame( z = testdf$z ) )

# Plotting the points reveals the unevenly spaced nature of the points
spplot(spdf)

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

# You can see the uneven nature of the data even better here via the moire pattern
plot(spdf)

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

# Make an evenly spaced raster, the same extent as original data
e <- extent( spdf )

# Determine ratio between x and y dimensions
ratio <- ( e@xmax - e@xmin ) / ( e@ymax - e@ymin )

# Create template raster to sample to
r <- raster( nrows = 56 , ncols = floor( 56 * ratio ) , ext = extent(spdf) )
rf <- rasterize( spdf , r , field = "z" , fun = mean )

# Attributes of our new raster (# cells quite close to original data)
rf
class       : RasterLayer 
dimensions  : 56, 135, 7560  (nrow, ncol, ncell)
resolution  : 0.424932, 0.4248191  (x, y)
extent      : -124.5008, -67.13498, 25.21298, 49.00285  (xmin, xmax, ymin, ymax)

# We can then plot this using `geom_tile()` or `geom_raster()`
rdf <- data.frame( rasterToPoints( rf ) )    
ggplot( NULL ) + geom_raster( data = rdf , aes( x , y , fill = layer ) )

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

# And as the OP asked for geom_tile, this would be...
ggplot( NULL ) + geom_tile( data = rdf , aes( x , y , fill = layer ) , colour = "white" )

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

แน่นอนว่าฉันควรเสริมว่าข้อมูลนี้ค่อนข้างไม่มีความหมาย สิ่งที่คุณต้องทำจริงๆ คือนำ SpatialPointsDataFrame กำหนดข้อมูลการฉายภาพที่ถูกต้องให้กับมัน จากนั้นแปลงเป็นพิกัด Latlong ผ่าน spTransform จากนั้นจึงแรสเตอร์จุดที่แปลงแล้ว จริงๆ แล้ว คุณต้องมีข้อมูลเพิ่มเติมเกี่ยวกับข้อมูลแรสเตอร์ของคุณ สิ่งที่คุณมีในที่นี้เป็นเพียงการประมาณที่ใกล้เคียง แต่ท้ายที่สุดแล้ว มันไม่ได้สะท้อนข้อมูลที่แท้จริง

person Simon O'Hanlon    schedule 12.03.2013
comment
ฉันขอโทษล่วงหน้าที่หนาแน่น - ฉันมีเรื่องต้องอ่าน - แต่ฉันไม่เข้าใจส่วนสุดท้าย เหตุใดข้อมูลจึงไม่มีความหมาย? ความไม่แน่นอนที่เกี่ยวข้องกับการสุ่มตัวอย่างใหม่นั้นมีน้อย และชุดข้อมูลมีทั้งละติจูดและลอน ดังนั้น เช่น ฉันเห็นว่ามิดเวสต์มีค่าสูงกว่าชายฝั่งตะวันตก โครงการเพิ่มข้อมูลอะไรบ้างนอกเหนือจากที่จำเป็นสำหรับการวางแผน การฉายภาพที่ใช้ในวัตถุ rf RasterLayer ผิดหรือไม่ มีข้อมูลเพิ่มเติมเกี่ยวกับข้อมูลนี้ที่ gis.SE ฉันติดอยู่กับการพยายามมอบหมาย gridded() <- TRUE - person Abe; 12.03.2013
comment
โอเค มันไม่ได้ค่อนข้างไร้ความหมาย แต่สิ่งที่เราทำอย่างมีประสิทธิภาพคือการซ้อนทับตารางปกติที่ด้านบนของสิ่งที่คุณเห็นในภาพแรก และกำหนดค่าให้กับตารางปกติตามตำแหน่งที่อยู่ในรูปภาพด้านล่าง นี่ไม่ถูกต้อง การแปลงข้อมูลโดยการฉายภาพใหม่จะทำให้จุดข้อมูลบางจุดมีการเลื่อนมากกว่าจุดอื่นๆ ตามฟังก์ชันของละติจูดและลองจิจูด หากคุณไม่สนใจเรื่องความถูกต้องและต้องการภาพรวมทั่วไป คุณอาจใช้สิ่งนี้ได้ แต่ฉันไม่คิดว่าจะไม่สามารถป้องกันได้มากนักในการตีพิมพ์ บางที @PaulHiemstra อาจอธิบายรายละเอียดเพิ่มเติมอีกหน่อยได้ไหม? - person Simon O'Hanlon; 12.03.2013
comment
@ SimonO101 ใช่คุณทำ - ขอบคุณสำหรับความช่วยเหลือของคุณ เมื่อพิจารณาจากสมมติฐานที่ใช้ในการสร้างแผนที่ (ไม่ใช่ 'ข้อมูล' แต่เป็นเอาต์พุตของโมเดล) เช่นเดียวกับความละเอียดที่จำกัดของระดับสี ฉันคิดว่ามันเป็นไปได้ที่จะพิสูจน์ข้อผิดพลาดบางอย่างที่เกิดขึ้นระหว่างการทำแผนที่ - กฎทั่วไปของฉันคือการเพิกเฉยต่อสิ่งที่คิดเป็น ‹ 5% หรือมากกว่านั้น ของความไม่แน่นอนทั้งหมด - person Abe; 12.03.2013

นี่จะไม่ใช่คำตอบสำหรับปัญหา geom_tile() แต่เป็นอีกวิธีหนึ่งในการวางแผนข้อมูล

เนื่องจากคุณมีพิกัด x และ y ของตาราง 30 กม. (ฉันถือว่าอยู่ตรงกลางของตารางนั้น) คุณสามารถใช้ geom_point() และลงจุดข้อมูลได้ คุณควรเลือกค่า shape= ที่เหมาะสม รูปทรง 15 จะลงจุดสี่เหลี่ยม

ปัญหาอีกประการหนึ่งคือค่า x และ y - เมื่อพล็อตข้อมูล ควรพล็อตเป็น x=y และ y=x เพื่อให้สอดคล้องกับละติจูดและลองจิจูด

coord_equal() จะตรวจสอบให้แน่ใจว่ามีอัตราส่วนภาพที่ถูกต้อง (ฉันพบวิธีแก้ปัญหานี้พร้อมอัตราส่วนตามตัวอย่างในเน็ต)

ggplot(data = testdf, aes(y,x,colour=z)) + geom_point(shape=15)+
  coord_equal(ratio=1/cos(mean(testdf$x)*pi/180))

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

person Didzis Elferts    schedule 11.03.2013

คำตอบ:

ข้อมูลถูกพล็อตแต่มีขนาดเล็กมาก


จากที่นี่:

"Tile plot as densely as possible, assuming that every tile is the same size.

พิจารณาโครงเรื่องนี้

ggplot(data = testdf[1:2,], aes(x,y,fill = z)) + geom_tile()

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

มีสองแผ่นในพล็อตด้านบน geom_tile กำลังพยายามทำให้พล็อตมีความหนาแน่นมากที่สุดโดยพิจารณาว่าแต่ละไทล์มีขนาดเท่ากัน ที่นี่เราสามารถทำให้สองแผ่นใหญ่ขนาดนี้โดยไม่ทับซ้อนกัน ทำให้มีพื้นที่เพียงพอสำหรับกระเบื้อง 4 แผ่น

ลองดูแปลงต่อไปนี้และดูว่าผลลัพธ์ที่ได้บอกอะไรคุณ:

df1 <- data.frame(x=c(1:3),y=(1:3))
#     df1
#  x   y
#1 1   1
#2 2   2
#3 3   3
ggplot(data = df1[1,], aes(x,y)) + geom_tile()   
ggplot(data = df1[1:2,], aes(x,y)) + geom_tile() 
ggplot(data = df1[1:3,], aes(x,y)) + geom_tile()

เปรียบเทียบกับตัวอย่างนี้:

 df2 <- data.frame(x=c(1:3),y=c(1,20,300))
 df2
 # x   y
#1 1   1
#2 2  20
#3 3 300

 ggplot(data = df2[1,], aes(x,y)) + geom_tile()
 ggplot(data = df2[1:2,], aes(x,y)) + geom_tile()
 ggplot(data = df2[1:3,], aes(x,y)) + geom_tile()

โปรดทราบว่าสำหรับสองแปลงแรกเหมือนกันสำหรับ df1 และ df2 แต่พล็อตที่สามสำหรับ df2 นั้นแตกต่างกัน เนื่องจากขนาดที่ใหญ่ที่สุดที่เราสามารถสร้างไทล์ได้คือระหว่าง (x[1],y[1]) ถึง (x[2],y[2]) หากมากกว่านั้นก็จะทับซ้อนกัน ซึ่งทำให้เหลือช่องว่างระหว่างไทล์ทั้งสองนี้กับไทล์ที่ 3 สุดท้ายที่ y=300

นอกจากนี้ยังมีพารามิเตอร์ width ใน geom_tile แม้ว่าฉันจะไม่แน่ใจว่าสิ่งนี้สมเหตุสมผลแค่ไหน คุณแน่ใจหรือว่าไม่ต้องการตัวเลือกอื่นที่มีข้อมูลที่กระจัดกระจายเช่นนี้

(ข้อมูลทั้งหมดของคุณยังคงถูกพล็อต: ดู ggplot(data = testdf, aes(x,y)) + geom_tile(width=1000)

person user1317221_G    schedule 24.01.2013
comment
ใช่ แต่บางทีคุณสามารถเพิ่มคำอธิบายเล็กน้อยเกี่ยวกับวิธีที่ geom_tile เลือกขนาดของไทล์โดยพิจารณาจากคะแนนที่ใกล้เคียงกัน...? - person joran; 25.01.2013
comment
คุณเสนอทางเลือกอื่นอะไรบ้าง? เฉพาะตัวอย่างขั้นต่ำเท่านั้นที่กระจัดกระจาย ชุดข้อมูลเต็มคือกระต่าย: betydb.org//miscanthusyield.csv - person Abe; 25.01.2013
comment
อย่างแน่นอน; เป็นแรสเตอร์ 7,500 แถวของสหรัฐอเมริกา โดยมีระยะห่างระหว่างตาราง 30 กม. ฉันเพิ่งลดปัญหาในขณะที่พยายามค้นหาคำตอบด้วยตัวเองและเพื่อความชัดเจนของคำถามนี้ ฉันได้ลบความคิดเห็นและลิงก์ก่อนหน้าแล้ว และเพิ่มตัวอย่างชุดข้อมูลแบบเต็มในคำถามของฉัน ฉันจะลอง width และติดต่อกลับหาคุณ ฉันคิดว่าปัญหาอาจเกิดจากการฉายภาพ ... - person Abe; 25.01.2013
comment
ฉันให้รางวัลกับคำถามนี้เพื่อค้นหาวิธีแก้ไขปัญหาในการวางแผนข้อมูลที่ฉันมี - person Abe; 11.03.2013

หากคุณต้องการใช้ geom_tile ฉันคิดว่าคุณจะต้องรวมข้อมูลก่อน:

# NOTE: tmp.csv downloaded from https://gist.github.com/geophtwombly/4635980/raw/f657dcdfab7b951c7b8b921b3a109c7df1697eb8/test.csv
testdf <- read.csv("~/Desktop/tmp.csv") 

# combine x,y coordinates by rounding
testdf$x2 <- round(testdf$x, digits=0)
testdf$y2 <- round(testdf$y, digits=0)

# aggregate on combined coordinates
library(plyr)
testdf <- ddply(testdf, c("x2", "y2"), summarize,
                z = mean(z))

# plot aggregated data using geom_tile
ggplot(data = testdf, aes(y2,x2,fill=z)) +
  geom_tile() +
  coord_equal(ratio=1/cos(mean(testdf$x2)*pi/180)) # copied from @Didzis Elferts answer--nice!

เมื่อเราทำทั้งหมดนี้แล้ว เราอาจจะสรุปได้ว่า geom_point() ดีกว่า ตามที่แนะนำโดย @Didzis Elferts

person Ista    schedule 11.03.2013