Как создать вывод с координатной сеткой в ​​​​R и исключить квадраты сетки, которые не находятся над сушей?

Я пытаюсь получить данные об осадках с координатной сеткой над Великобританией, используя алгоритм Thin Plate Spline, и исключить значения, которые не относятся к суше, в R - процесс, который я пока могу выполнить только вручную. Проблема сложная (для меня) и даже сложная для объяснения, поэтому я пройдусь по тому, что я сделал до сих пор. Любая помощь будет принята с благодарностью.

Во-первых, я загружаю в R таблицу данных, которая представляет количество осадков за один день с нескольких метеостанций с точечным расположением, и каждая строка таблицы данных содержит дату, идентификатор станции, восточное и северное положение станции, суточное количество осадков на этом участке и среднее количество осадков за год. Я также загружаю поля библиотек, maptools и gstat.

library(fields)
library(maptools)
library(gstat)

dat <- read.table("1961month1day1.csv", header=T, sep=",", quote = "")
names(dat) <- c("easting", "northing", "dailyrainfall","avaerageyearlyrainfall")

Вот пример данных:

dput(head(dat, 20))
structure(list(easting = c(130000L, 145000L, 155000L, 170000L, 
180000L, 180000L, 180000L, 180000L, 185000L, 200000L, 200000L, 
205000L, 210000L, 220000L, 225000L, 230000L, 230000L, 230000L, 
230000L, 235000L), northing = c(660000L, 30000L, 735000L, 40000L, 
30000L, 45000L, 60000L, 750000L, 725000L, 50000L, 845000L, 65000L, 
770000L, 105000L, 670000L, 100000L, 620000L, 680000L, 95000L, 
120000L), dailyrainfall = c(9.4, 4.1, 12.4, 2.8, 1.3, 3.6, 4.8, 26.7, 19.8, 
4.6, 1.7, 4.1, 12.7, 1.8, 3, 5.3, 1, 1.5, 1.5, 4.6), averageyearlyrainfall = c(1334.626923, 
1123.051923, 2072.030769, 1207.584615, 928, 1089.334615, 880.0884615, 
2810.323077, 1933.719231, 1215.642308, 2644.171154, 1235.913462, 
2140.111538, 1010.436538, 1778.432692, 1116.934615, 912.2807692, 
1579.386538, 1085.498077, 1250.601923)), .Names = c("easting", 
"northing", "dailyrainfall", "averageyearlyrainfall"), row.names = c(NA, 20L), class = "data.frame")

Затем я могу подогнать к данным сплайн тонкой пластины, чтобы получить поверхность с сеткой, и построить поверхность:

fit <- Tps(cbind(dat$easting,dat$northing),dat$dailyrainfall)
surface(fit)

Затем я могу создать сетку Великобритании с шагом в 1 км, используя:

xvals <- seq(0, 700000, by=1000)
yvals <- seq(0, 1250000, by=1000)

а затем нанесите поверхность на эту сетку и запишите данные в таблицу:

griddf <- expand.grid(xvals, yvals)
griddf$pred <- predict(fit, x=as.matrix(griddf))
write.table(griddf, file="1Jan1961grid.csv", sep=",", qmethod="double")

Отлично - пока все хорошо. Теперь я преобразовал свои точечные данные в данные с координатной сеткой 1 км по всей сетке от 0 до 700000 (E) и от 0 до 1250000 (N). Таблица письменных данных представляет собой список, содержащий индекс, восточное и северное положение и прогнозируемое количество осадков.

Теперь задача — я хочу исключить из этого списка все значения, которые не относятся к суше. Я могу добиться этого вручную, загрузив данные в Excel (или Access) и сравнив данные с другим файлом, который содержит ту же сетку и среднегодовое количество осадков (файл называется 1kmgridaveragerainfall.csv). Вот пример этого файла:

dput(head(dat1, 20))
structure(list(easting = c(-200000L, -200000L, -200000L, -200000L, 
-200000L, -200000L, -200000L, -200000L, -200000L, -200000L, -200000L, 
-200000L, -200000L, -200000L, -200000L, -200000L, -200000L, -200000L, 
-200000L, -200000L), northing = c(1245000L, 1240000L, 1235000L, 
 1230000L, 1225000L, 1220000L, 1215000L, 1210000L, 1205000L, 1200000L, 
 1195000L, 1190000L, 1185000L, 1180000L, 1175000L, 1170000L, 1165000L, 
 1160000L, 1155000L, 1150000L), averageyearlyrainfall = c(-9999, -9999, -9999, 
 -9999, -9999, -9999, -9999, -9999, -9999, -9999, -9999, -9999, 
 -9999, -9999, -9999, -9999, -9999, -9999, -9999, -9999)), .Names = c("easting", 
 "northing", "averageyearlyrainfall"), row.names = c(NA, 20L), class = "data.frame")

В любом квадрате сетки, который не находится над сушей, среднегодовое количество осадков составляет -9999. Следовательно, после сопоставления (т. е. с использованием vlookup или запроса в Access) я могу отфильтровать значения, которые имеют это значение -9999, и это оставляет мне таблицу данных, в которой есть восточное и северное направление, дневные осадки и среднегодовые осадки только для значений земли. Затем я могу загрузить это обратно в R и построить это, используя:

quilt.plot(cbind(dat$easting,dat$northing),dat$mm, add.legend=TRUE, nx=654, ny=1209,xlim=c(0,700000),ylim=c(0,1200000))

и у меня остался участок осадков над территорией Великобритании (а не над морем).

Итак, может ли кто-нибудь предложить способ добиться того же, но без всей фильтрации и т. Д., Используя Excel или доступ, т. Е. Можно ли добиться того же, используя только R? Есть ли способ загрузить обе таблицы данных в R в начале и каким-то образом подогнать TPS точечных данных к средним данным, чтобы квадраты сетки, равные -9999, не отображались.

Я знаю, что TPS можно взвешивать с помощью ковариаты (Z) — это вообще помогает? то есть

fit <- Tps(cbind(dat$easting,dat$northing),dat$dailyrainfall, Z=dat$averageyearlyrainfall)

Кроме того, когда я выполняю поверхность (подгонку) исходного TPS, как мне расширить график до краев графика - я уверен, что читал это где-то, где вы вводите что-то вроде interp=TRUE, но это не так. работай.

Любая помощь будет принята с благодарностью

Спасибо, Тони


person AntonyDW    schedule 06.12.2013    source источник
comment
Некоторые советы. (a) Вернитесь назад и отметьте ответ на ваш вопрос - люди хотите знать, что их усилия, чтобы помочь вам, будут вознаграждены. (b) Задавайте один вопрос на пост. В этом случае, я думаю, вы спрашиваете, как отфильтровать фрейм данных, что не должно быть проблемой. (c) Предоставьте образец данных из каждого фрейма данных, возможно, используя dput(head(mydata1, 20) и скопировав полученный результат structure в свой вопрос. Подробнее см. здесь.   -  person SlowLearner    schedule 06.12.2013


Ответы (2)


Если вы уже дошли до того, что у вас есть два фрейма данных, вы сможете объединить их в новый фрейм данных и отфильтровать/подмножить результат.

set.seed(1234) # for reproducibility

# "The written data table is a list containing an index, an easting,
# a northing and the predicted rainfall value"
# Create a simple data frame containing made-up data
mydf1 <- data.frame(index = 1:10,
                    easting = c(1, 1, 3, 4, 5, 5, 5, 5, 6, 6),
                    northing = c(12, 13, 13, 13, 14, 14, 15, 17, 18, 20),
                    predicted = runif(10, 500, 1000))

# "...comparing the data to another file that contains the same grid
# and the average yearly rainfall"
# Second data frame is similar, but has rainfall instead of predicted
mydf2 <- data.frame(index = 1:10,
                    easting = c(1, 1, 3, 4, 5, 5, 5, 5, 6, 6),
                    northing = c(12, 13, 13, 13, 14, 14, 15, 17, 18, 20),
                    rainfall = c(runif(9, 500, 1000), -9999))

# If data frames are of same size and have mostly common columns,
# merging them probably makes it easy to manipulate the data
mydf.merged <- merge(mydf1, mydf2)

# Finally, filter the merged data frame so that it only contains
# rainfall values that are not the -9999 value that denotes sea
mydf.final <- mydf.merged[mydf.merged$rainfall > -9999, ]

Это первый фрейм данных:

> mydf1
   index easting northing predicted
1      1       1       12  556.8517
2      2       1       13  811.1497
3      3       3       13  804.6374
4      4       4       13  811.6897
5      5       5       14  930.4577
6      6       5       14  820.1553
7      7       5       15  504.7479
8      8       5       17  616.2753
9      9       6       18  833.0419
10    10       6       20  757.1256
> 

Это второй кадр данных:

> mydf2
   index easting northing   rainfall
1      1       1       12   846.7956
2      2       1       13   772.4874
3      3       3       13   641.3668
4      4       4       13   961.7167
5      5       5       14   646.1579
6      6       5       14   918.6478
7      7       5       15   643.1116
8      8       5       17   633.4104
9      9       6       18   593.3614
10    10       6       20 -9999.0000
> 

Объединенный кадр данных:

> mydf.merged
   index easting northing predicted   rainfall
1      1       1       12  556.8517   846.7956
2     10       6       20  757.1256 -9999.0000
3      2       1       13  811.1497   772.4874
4      3       3       13  804.6374   641.3668
5      4       4       13  811.6897   961.7167
6      5       5       14  930.4577   646.1579
7      6       5       14  820.1553   918.6478
8      7       5       15  504.7479   643.1116
9      8       5       17  616.2753   633.4104
10     9       6       18  833.0419   593.3614
> 

Окончательный кадр данных с удаленной строкой -9999:

> mydf.final
   index easting northing predicted rainfall
1      1       1       12  556.8517 846.7956
3      2       1       13  811.1497 772.4874
4      3       3       13  804.6374 641.3668
5      4       4       13  811.6897 961.7167
6      5       5       14  930.4577 646.1579
7      6       5       14  820.1553 918.6478
8      7       5       15  504.7479 643.1116
9      8       5       17  616.2753 633.4104
10     9       6       18  833.0419 593.3614
> 
person SlowLearner    schedule 06.12.2013
comment
Отлично - это достигает всего, что я хотел. Спасибо. - person AntonyDW; 10.12.2013

Хорошо, мы не можем реплицировать ваши данные, поэтому вот несколько указателей с некоторыми примерами:

Сначала создайте матрицу с вашими среднесуточными данными об осадках с отметкой -9999, не относящейся к земле:

> m=matrix(1:12,3,4)
> m[2,1]=-9999
> m[2,3]=-9999
> m
      [,1] [,2]  [,3] [,4]
[1,]     1    4     7   10
[2,] -9999    5 -9999   11
[3,]     3    6     9   12

Затем создайте матрицу, которая будет вашей сеткой значений:

> r=matrix(runif(12),3,4)
> r
          [,1]      [,2]      [,3]      [,4]
[1,] 0.9410278 0.3333299 0.5925126 0.3803659
[2,] 0.9169051 0.9797365 0.6504944 0.3154179
[3,] 0.9130946 0.7032607 0.5418443 0.8637259

Теперь мы хотим заменить все значения в r, где m имеет значение -9999, на NA:

> r
          [,1]      [,2]      [,3]      [,4]
[1,] 0.9410278 0.3333299 0.5925126 0.3803659
[2,]        NA 0.9797365        NA 0.3154179
[3,] 0.9130946 0.7032607 0.5418443 0.8637259

Теперь, если вы можете перевести это на свои объекты данных, тогда работа сделана, верно?

person Spacedman    schedule 06.12.2013
comment
Привет, спасибо, я вроде понял твою точку зрения. Как заменить 1:12 моими фактическими данными (примерно восемьсот тысяч строк данных)? И как мне тогда заменить -9999 на NA - ты не сказал? Я ценю вашу помощь. - person AntonyDW; 06.12.2013
comment
Много вопросов, и я думаю, что вам нужно сначала немного изучить R. - person Spacedman; 07.12.2013