Mengapa geom_tile memplot sebagian data saya, tetapi tidak lebih?

Saya mencoba membuat plot peta, tetapi saya tidak tahu mengapa hal berikut ini tidak berhasil:

Berikut adalah contoh minimalnya

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

Ini berfungsi untuk 1-8 baris:

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

Tapi tidak untuk 9 baris:

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

Pada akhirnya, saya mencari cara untuk memplot data pada grid non-reguler. Saya tidak perlu menggunakan geom_tile, tetapi interpolasi pengisian ruang apa pun pada titik-titik tersebut bisa dilakukan.

Kumpulan data lengkap tersedia di intisari

testdf di atas adalah sebagian kecil dari kumpulan data lengkap, raster resolusi tinggi AS (>7500 baris)

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

Apa yang saya coba:

  1. menggunakan geom_point berfungsi, tetapi tidak memberikan efek yang diinginkan:

    ggplot(data = testdf, aes(x,y,color=z)) + geom_point()
    
  2. jika saya mengonversi x atau y ke vektor 1:10, plotnya berfungsi seperti yang diharapkan:

    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 sumber
comment
Apakah Anda memiliki informasi lebih lanjut tentang raster asal datanya? yaitu informasi proyeksi   -  person Simon O'Hanlon    schedule 12.03.2013
comment
@SimonO101 mereka dihasilkan pada jaringan 30x30km   -  person Abe    schedule 12.03.2013
comment
Oke. Anda perlu melakukan beberapa pengambilan sampel ulang pada data Anda. Jarak titik-titiknya tidak sama, itulah sebabnya Anda tidak dapat menggunakan geom_raster atau geom_tile. Lihat jawaban saya untuk detail dan solusi yang menggunakan geom_raster.   -  person Simon O'Hanlon    schedule 12.03.2013
comment
apakah cara di bawah ini berfungsi pada sistem Anda?   -  person Simon O'Hanlon    schedule 12.03.2013
comment
Abe - Saya menerapkan hasil edit yang Anda sarankan dengan benar tetapi ditolak oleh pengulas sebelum saya sempat menerimanya! Anda benar sekali, skripnya membutuhkan RCurl.   -  person Simon O'Hanlon    schedule 12.03.2013
comment
@ SimonO101 ya - ini berfungsi dengan baik. Terima kasih atas jawaban anda! Tapi saya masih terjebak (dan akan berkomentar di bawah jawaban Anda).   -  person Abe    schedule 12.03.2013


Jawaban (4)


Alasan Anda tidak dapat menggunakan geom_tile() (atau geom_raster() yang lebih tepat adalah karena kedua geoms ini mengandalkan ubin Anda dengan jarak yang sama, padahal sebenarnya tidak. Anda perlu memaksakan data Anda ke titik, dan mengambil sampel ulang ini ke raster dengan jarak yang sama yang kemudian dapat Anda plot dengan geom_raster(). Anda harus menerima bahwa Anda perlu sedikit mengambil sampel ulang data asli Anda untuk memplotnya sesuai keinginan.

Anda juga harus membaca di raster:::projection dan rgdal:::spTransform untuk informasi lebih lanjut tentang proyeksi peta.

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)

masukkan deskripsi gambar di sini

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

masukkan deskripsi gambar di sini

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

masukkan deskripsi gambar di sini

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

masukkan deskripsi gambar di sini

Tentu saja saya harus menambahkan bahwa data ini tidak ada artinya. Apa yang benar-benar harus Anda lakukan adalah mengambil SpatialPointsDataFrame, menetapkan informasi proyeksi yang benar ke dalamnya, dan kemudian mengubahnya menjadi koordinat lintang melalui spTransform dan kemudian melakukan rasterzie pada titik-titik yang diubah. Anda benar-benar perlu memiliki lebih banyak informasi tentang data raster Anda. Apa yang Anda dapatkan di sini adalah perkiraan yang mendekati, tetapi pada akhirnya ini bukan cerminan data yang sebenarnya.

person Simon O'Hanlon    schedule 12.03.2013
comment
Saya minta maaf sebelumnya karena padat - ada beberapa yang harus saya baca - tetapi saya tidak mengerti bagian terakhirnya. Mengapa datanya tidak ada artinya? Ketidakpastian yang terkait dengan pengambilan sampel ulang tergolong kecil, dan kumpulan datanya memiliki garis lintang dan bujur, jadi, misalnya, saya dapat melihat bahwa wilayah barat tengah memiliki nilai yang lebih tinggi daripada wilayah pantai barat. Informasi apa yang ditambahkan oleh suatu proyek selain yang diperlukan untuk membuat plot? Apakah proyeksi yang digunakan pada objek rf RasterLayer salah? Terdapat informasi lebih lanjut tentang data ini di gis.SE. Saya terjebak saat mencoba menetapkan gridded() <- TRUE. - person Abe; 12.03.2013
comment
Oke, ini bukannya tidak ada artinya, tapi secara efektif apa yang telah kita lakukan adalah melapisi grid biasa di atas apa yang Anda lihat di gambar pertama dan memberikan nilai ke grid reguler berdasarkan lokasinya di gambar yang mendasarinya. Ini tidak benar. Mengubah data dengan memproyeksikan ulang akan menyebabkan beberapa titik data Anda bergeser lebih banyak dibandingkan titik data lainnya berdasarkan fungsi lintang dan bujurnya. Jika Anda tidak peduli dengan keakuratan dan menginginkan gambaran umum maka mungkin Anda dapat menggunakan ini, tetapi menurut saya ini tidak akan dapat dipertahankan dalam sebuah publikasi. Mungkin @PaulHiemstra bisa menjelaskan lebih lanjut? - person Simon O'Hanlon; 12.03.2013
comment
@ SimonO101 ya - terima kasih atas bantuan Anda. Mengingat asumsi yang digunakan untuk menghasilkan peta (bukan 'data' tetapi keluaran model) serta resolusi skala warna yang terbatas, menurut saya beberapa kesalahan yang terjadi selama pemetaan dapat dibenarkan - aturan umum saya adalah mengabaikan hal-hal yang menyumbang ‹ 5% atau lebih dari ketidakpastian total. - person Abe; 12.03.2013

Ini bukan jawaban untuk masalah geom_tile() tetapi cara lain untuk memplot data.

Karena Anda memiliki koordinat x dan y dari grid 30 km (saya berasumsi di tengah grid itu) maka Anda dapat menggunakan geom_point() dan memplot data. Anda harus memilih nilai shape= yang sesuai. Bentuk 15 akan memplot persegi panjang.

Masalah lainnya adalah nilai x dan y - saat memplot data, nilai tersebut harus diplot sebagai x=y dan y=x agar sesuai dengan garis lintang dan garis bujur.

coord_equal() akan memastikan bahwa ada rasio aspek yang benar (saya menemukan solusi ini dengan rasio sebagai contoh di internet).

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

masukkan deskripsi gambar di sini

person Didzis Elferts    schedule 11.03.2013

menjawab:

data diplot tetapi sangat kecil.


Dari sini:

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

Pertimbangkan plot ini

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

masukkan deskripsi gambar di sini

Ada dua ubin pada plot di atas. geom_tile berusaha membuat plot sepadat mungkin mengingat setiap ubin berukuran sama. Di sini kita bisa membuat dua ubin sebesar ini tanpa tumpang tindih. membuat ruang yang cukup untuk 4 ubin.

Coba lihat plot berikut dan lihat apa yang disampaikan oleh plot yang dihasilkan:

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

bandingkan dengan contoh ini:

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

Perhatikan bahwa dua plot pertama sama untuk df1 dan df2 tetapi plot ketiga untuk df2 berbeda. Ini karena ubin terbesar yang bisa kita buat adalah antara (x[1],y[1]) dan (x[2],y[2]). Jika lebih, ubin tersebut akan tumpang tindih sehingga menyisakan banyak ruang antara kedua ubin ini dan ubin ke-3 terakhir di y=300.

Ada juga parameter width di geom_tile meskipun saya tidak yakin seberapa masuk akalnya hal ini di sini. apakah Anda yakin tidak menyukai opsi lain dengan data yang sangat sedikit?

(Data lengkap Anda masih diplot: lihat ggplot(data = testdf, aes(x,y)) + geom_tile(width=1000)

person user1317221_G    schedule 24.01.2013
comment
Ya, tapi mungkin Anda bisa menambahkan sedikit penjelasan tentang bagaimana geom_tile memilih ukuran ubin berdasarkan seberapa dekat titik-titiknya...? - person joran; 25.01.2013
comment
Opsi lain apa yang Anda sarankan? Hanya contoh minimal saja yang jarang; kumpulan data lengkapnya adalah kelinci: betydb.org//miscanthusyield.csv - person Abe; 25.01.2013
comment
Tepat; ini adalah raster 7500 baris AS dengan jarak grid 30 km; Saya hanya mereduksi masalahnya sambil mencoba mencari jawabannya sendiri, dan untuk kejelasan pertanyaan ini. Saya telah menghapus komentar dan tautan sebelumnya dan menambahkan contoh kumpulan data lengkap ke pertanyaan saya. Saya akan mencoba width dan menghubungi Anda kembali. Saya pikir masalahnya mungkin adalah proyeksinya... - person Abe; 25.01.2013
comment
Saya memberikan hadiah pada pertanyaan ini untuk mencari solusi untuk merencanakan data yang saya miliki. - person Abe; 11.03.2013

Jika Anda ingin menggunakan geom_tile, saya rasa Anda harus melakukan agregat terlebih dahulu:

# 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!

Setelah kita melakukan semua ini, kita mungkin akan menyimpulkan bahwa geom_point() lebih baik, seperti yang disarankan oleh @Didzis Elferts.

person Ista    schedule 11.03.2013