В настоящее время я пытаюсь получить некоторые данные в R из таблицы.

У меня есть набор данных с двумя разными переменными, годовым диапазоном и среднегодовым значением мировой температуры поверхности моря (SST). У меня есть эти значения для каждого уровня широты (от 90 до -90) и долготы (от 180 до -180).

Я хотел бы получить среднее значение вышеупомянутых переменных (годовой диапазон и среднегодовое значение) для ячеек сетки 5x5 широты / долготы. Например, мне нужно знать среднее значение «годового диапазона» для долготы от -180 до -176 и широты от 90 до 86, и так далее, пока не получу среднее значение этой переменной для всех возможных ячеек сетки 5x5.

Мои данные выглядят так:

lon lat ANNUAL_MEAN ANNUAL_RANGE 1 0.5 89.5 -1.8 0 2 1.5 89.5 -1.8 0 3 2.5 89.5 -1.8 0 4 3.5 89.5 -1.8 0 5 4.5 89.5 -1.8 0 6 5.5 89.5 -1.8 0 ... 52001 354.5 -89.5 -1.8 0 52002 355.5 -89.5 -1.8 0 52003 356.5 -89.5 -1.8 0 52004 357.5 -89.5 -1.8 0 52005 358.5 -89.5 -1.8 0 52006 359.5 -89.5 -1.8 0

Заранее спасибо

2
Diego Cepeda 25 Сен 2018 в 13:13

2 ответа

Лучший ответ

Вы можете использовать пакет raster и его функцию focal для вычислений с движущимся окном.

Сначала я создам фиктивный data.frame, который представляет ваши данные.

# Prepare dummy data.frame
set.seed(2222)
lonlat <- expand.grid(1:10, 1:10)
df <- data.frame( lon = lonlat[, 1],
                  lat = lonlat[, 2],
                  ANNUAL_MEAN = rnorm(100),
                  ANNUAL_RANGE = runif(100, 1, 5)
                )

Теперь нам нужно преобразовать фрейм данных в растр и выполнить усреднение движущегося окна.

library(raster)

# Convert data frame to raster object
rdf <- df
coordinates(rdf) <- ~ lon + lat
gridded(rdf) <- TRUE
rdf <- brick(rdf) # our raster brick

## Perform moving window averaging

# prepare weights matrix (5*5)
w <- matrix(1, ncol = 5, nrow = 5)

# perform moving window averaging
ANNUAL_MEAN_AVG <- focal(rdf[[1]], w, mean, pad = TRUE, na.rm = TRUE)
ANNUAL_RANGE_AVG <- focal(rdf[[2]], w, mean, pad = TRUE, na.rm = TRUE)

# Append new data to initial data.frame
df$ANNUAL_MEAN_AVG <- as.data.frame(ANNUAL_MEAN_AVG)
df$ANNUAL_RANGE_AVG <- as.data.frame(ANNUAL_RANGE_AVG)

Теперь каждая ячейка в df$ANNUAL_MEAN_AVG и df$ANNUAL_RANGE_AVG содержит среднее значение соответствующего квадрата 5 * 5.

UPD 1. Понижение частоты дискретизации 5x5

Если вам нужна фиксированная сетка 5x5 ячеек со средними значениями на ячейку, вы можете использовать функцию raster::agregate.

Работа с растровым кирпичом rdf из предыдущего примера.

# perform an aggregation with given downsampling factor
rdf_d <- aggregate(rdf, fact=5, fun = mean)

# Now each pixel in the raster `rdf_d` contains a mean value of 5x5 pixels from initial `rdf`
# we need to get pixels coordinates and their values
coord <- coordinates(rdf_d)
vals <- as.data.frame(rdf_d)
colnames(coord) <- c("lon", "lat")
colnames(vals) <- c("ANNUAL_MEAN_AVG", "ANNUAL_RANGE_AVG")

res <- cbind(coord, vals)
3
Istrel 26 Сен 2018 в 14:07

Это решение, в котором используется пакет dplyr, входящий в состав tidyverse. Это должно быть легко, шаг за шагом.

library(tidyverse)

# set.seed() assures reproducability of the example with identical random numbers
set.seed(42)


# build a simulated data set as described in the question
lats <- seq(from = -90, to = 90, by = 0.5)
lons <- seq(from = -180, to = 179.5, by = 0.5) # we must omit +180 or we would
                                               # double count those points
                                               # since they coincide with -180

    # combining each latitude point with each longitude point
coord <- merge(lats, lons) %>%
    rename(lat = x) %>% 
    rename(lon = y) %>%
    # adding simulated values
    mutate(annual_mean = runif(n = nrow(.), min = -2, max = 2)) %>%
    mutate(annual_range = runif(n = nrow(.), min = 0, max = 3)) %>% 
    # defining bands of 5 latitude and 5 longitude points by using integer division
    mutate(lat_band = lat%/%5) %>% 
    mutate(lon_band = lon%/%5) %>% 
    # creating a name label for each unique 5x5 gridcell
    mutate(gridcell_5x5 = paste(lat_band, lon_band, sep = ",")) %>%
    # group-by instruction, much like in SQL
    group_by(lat_band, lon_band, gridcell_5x5) %>% 
    # sorting to get a nice order
    arrange(lat_band, lon_band) %>% 
    # calculating minimum and maximum latitude and longitude for each gridcell
    # calculating the mean values per gridcell
    summarize(gridcell_min_lat = min(lat), 
              gridcell_max_lat = max(lat),
              gridcell_min_lon = min(lon),
              gridcell_max_lon = max(lon),
              gridcell_mean_annual_mean = round(mean(annual_mean), 3),
              gridcell_mean_annual_range = round(mean(annual_range), 3) )
1
stenevang 25 Сен 2018 в 12:44