Search code examples
rrasterna

Conditional replacement of NAs in two rasters of same dimensions R


This question is linked to Conditional replacement of NAs in two dataframes R but I would like to do the same thing on a raster instead of converting df1 and df2 to dataframes.

Given two rasters (df1,df2) of equal dimensions:

df1: dimensions  : 510, 1068, 544680, 1  (nrow, ncol, ncell, nlayers)

df2: dimensions  : 510, 1068, 544680, 1  (nrow, ncol, ncell, nlayers)

How can one find all columns in df1where all rows are NAs, go to df2and set all values in matching columns to NAs?


Solution

  • First, the manner in which the OP generated the sample data in his comment to dracodoc is inconsistent with the OP's question:

    library(raster) 
    r <- raster(nrow=5, ncol=5) 
    df1 <- stack( sapply(1:5, function(i) setValues(r, rnorm(ncell(r), i, 3)))) 
    df2<- stack( sapply(1:5, function(i) setValues(r, rnorm(ncell(r), i, 3)))) 
    df1[1,]<-NA
    

    This will set the first row of each layer of df1 to NA. The question then should be:

    How can one find all rows in df1 where all columns are NAs, go to df2 and set all values in matching rows to NAs?

    I will answer this question first and then address the complement problem of:

    How can one find all columns in df1 where all rows are NAs, go to df2 and set all values in matching columns to NAs?

    which is the OP's original question.

    Set rows that are NA in df1 to NA in df2

    To answer the first question, simulate another example dataset with different numbers for layers, rows, and columns; then, set different rows in each layer of df1 to NA:

    set.seed(123) ## only for full reproducibility
    library(raster) 
    r <- raster(nrow=7, ncol=5)  ## 7 rows to differentiate from 5 columns
    nlayers <- 6
    df1 <- stack(sapply(1:nlayers, function(i) setValues(r, rnorm(ncell(r), i, 3)))) 
    df2<- stack(sapply(1:nlayers, function(i) setValues(r, rnorm(ncell(r), i, 3)))) 
    df1[[1]][1,]<-NA  ## set row 1 of layer 1 to NA 
    df1[[1]][2,]<-NA  ## set row 2 of layer 1 to NA 
    df1[[2]][2,]<-NA  ## set row 2 of layer 2 to NA 
    df1[[3]][2,]<-NA  ## set row 2 of layer 3 to NA 
    df1[[4]][5,]<-NA  ## set row 5 of layer 4 to NA 
    df1[[5]][5,]<-NA  ## set row 5 of layer 5 to NA 
    df1[[6]][3,]<-NA  ## set row 3 of layer 6 to NA 
    

    Note that df1 looks like:

    df1[]
    ##         layer.1    layer.2    layer.3    layer.4    layer.5   layer.6
    ## [1,]         NA  4.0659208  1.5269065  3.8649168  7.1053530  2.712011
    ## [2,]         NA  3.6617530 -3.9275066  1.6452866  4.2134075  6.113365
    ## [3,]         NA  1.8142649  6.0172156 -1.0038258  0.2835675  6.931442
    ## [4,]         NA  1.0821120  0.8723977  2.8593204  0.4559970  7.309570
    ## [5,]         NA  0.8585870  0.9359742  6.7569898  0.1953915  4.624904
    ## [6,]         NA         NA         NA  2.2739591  3.4072804  2.810022
    ## [7,]         NA         NA         NA  5.8238930  0.6147332  9.789556
    ## [8,]         NA         NA         NA -0.8536481  7.0637503  4.951049
    ## [9,]         NA         NA         NA  3.8333141 11.3003268  3.403461
    ##[10,]         NA         NA         NA  5.5582216  1.1389086  5.291161
    ##[11,]  4.6722454 -1.3693257  3.0172926  4.9034601  7.3632165        NA
    ##[12,]  2.0794415  0.7913455  4.1558412  4.3170286  7.3071267        NA
    ##[13,]  2.2023144  0.6000339  1.8880199  2.0778820  5.9966077        NA
    ##[14,]  1.3320481  4.3398954  4.9331296  1.4508870  1.9748702        NA
    ##[15,] -0.6675234  1.7498928  2.3385403  0.9276136  4.6416422        NA
    ##[16,]  6.3607394  2.7599555  3.9953459  4.3529398  4.1588140  6.643336
    ##[17,]  2.4935514  1.9143597  6.2905170  1.1575762  6.6889686  5.025942
    ##[18,] -4.8998515  1.8713886  4.3055445  2.5283277  3.8826837  6.283751
    ##[19,]  3.1040677  6.1058069  2.0222052  3.2317234  7.9309202  3.313910
    ##[20,] -0.4183742  1.3226870  6.4464229  9.5315860  3.8762574  2.067595
    ##[21,] -2.2034711  6.5494118  5.9805116         NA         NA 11.991640
    ##[22,]  0.3460753 -2.6462584  4.6451909         NA         NA  7.802126
    ##[23,] -2.0780133  3.7538412  3.7161952         NA         NA  2.246186
    ##[24,] -1.1866737  2.3715627  1.1162818         NA         NA  4.166502
    ##[25,] -0.8751178  2.6478247  7.0819573         NA         NA  2.443560
    ##[26,] -4.0600799  3.1389184  1.1992212  8.3336526  5.8946828 12.596431
    ##[27,]  3.5133611  0.4930296  9.5619990  5.3545122  6.9097090  9.937239
    ##[28,]  1.4601194  1.0003778  7.5978319  4.1236988  3.5486581  5.204565
    ##[29,] -2.4144108 -1.0557261  2.2928989  2.7325095  6.5505861  7.629582
    ##[30,]  4.7614448 -1.2153737 -0.0792627 -2.1597417  6.1068936  4.756980
    ##[31,]  2.2793927  2.9105859  0.8687803  7.3940116  4.3538585  4.571259
    ##[32,]  0.1147856  3.3446293  3.7706511 -0.3819202  5.1958791  3.634191
    ##[33,]  3.6853770  2.1590127  2.2599244  6.2198425  4.8977982  4.216148
    ##[34,]  3.6344005  4.7668024  1.9573722  9.7273107 11.3853557 10.952722
    ##[35,]  3.4647432  8.1502541  0.1451443 -0.3316795  2.7759917  5.837916
    

    Note that it is now clear that each layer column in this display is a raster in row-major order.

    To find the rows in df1 that are all NAs in each layer, we borrow akrun's solution from the OP's linked SO question/answer, which works just as well for Raster* objects:

    inds <- which(!rowSums(!is.na(df1)), arr.ind=TRUE)
    ##     row col
    ##[1,]   1   1
    ##[2,]   2   1
    ##[3,]   2   2
    ##[4,]   2   3
    ##[5,]   5   4
    ##[6,]   5   5
    ##[7,]   3   6
    

    The which(..., arr.ind=TRUE) returns as its first column the row and as its second column the layer in df that are all NAs. Then we can subset df2 using a loop over layers to set those rows to NA:

    ## loop over layers and set the appropriate row for each layer
    for (i in seq_len(nrow(inds))) df2[[inds[i,2]]][inds[i,1],] <- NA
    df2[]
    ##        layer.1      layer.2    layer.3     layer.4    layer.5   layer.6
    ## [1,]          NA  7.707085465 -2.0024253  6.11057171  8.0448295 10.135710
    ## [2,]          NA  1.697075344  5.2094879  3.68298600 -0.9782455  7.368709
    ## [3,]          NA -2.079522111  4.1580797  0.22405412  3.7181621  2.593235
    ## [4,]          NA  0.005691694  2.2030451  9.05330712  5.3499119  4.693064
    ## [5,]          NA  3.456379937  3.3544335  6.73417388  2.3203773  7.038311
    ## [6,]          NA           NA         NA  4.71229082  6.0017088  4.058863
    ## [7,]          NA           NA         NA  7.65432583  6.2342898 -0.472939
    ## [8,]          NA           NA         NA -0.01632286  4.9008915  8.652752
    ## [9,]          NA           NA         NA  5.98246089 -2.3976946  3.511567
    ##[10,]          NA           NA         NA  2.43126287 12.7143744  4.279319
    ##[11,] -0.72192044  1.734304664  6.5051516  6.05123657  4.3841022        NA
    ##[12,]  2.85395745  5.242398488  6.1625431  3.81753414  6.9535798        NA
    ##[13,]  4.32954442  3.892262347  6.4357893  5.89888214  5.8212995        NA
    ##[14,]  3.12276506  1.659080313  1.2675960  8.00655285  8.0740197        NA
    ##[15,] -0.09097189 -2.598706009  9.0074482  4.02187027  7.4529783        NA
    ##[16,]  1.17924981  0.436648047  3.2001026  7.05267591  4.3706205  5.779332
    ##[17,] -1.11378939  0.530388641  8.6005555  0.43469789  6.1345033  2.494046
    ##[18,] -1.15165448  2.141463298 -1.0527081  1.83518668  2.1637735  4.095755
    ##[19,]  3.65395150  5.900596033  3.0629508  8.55765313  7.5707690  5.913475
    ##[20,] -2.04677774  8.879236921  6.7497437  5.13216392  3.6168850  8.012088
    ##[21,]  6.86588190  6.642743177  0.8542734          NA         NA  1.048360
    ##[22,]  0.72904122  1.600547107  0.7419331          NA         NA  4.950737
    ##[23,]  1.64361648 -3.269582187  0.1843839          NA         NA  8.269219
    ##[24,] -1.21558311  0.833660408 -0.1575398          NA         NA  4.383573
    ##[25,] -0.72316607  2.267621669  1.6885214          NA         NA  6.681876
    ##[26,] -2.95104840  4.535039012  3.9935375  5.87256242  3.2315569  7.476686
    ##[27,]  0.45122383  4.887583905 -3.0426315  6.87701613  2.0096578  6.803505
    ##[28,]  2.25694721  4.052928288  3.6359413  9.01316449  5.4334271  7.959773
    ##[29,]  1.97291303 -2.185823049  6.7100251  4.16805020  4.9570778  5.631874
    ##[30,] -1.34460946  4.548929137  9.1127221  3.84405428 -0.3708437  4.758970
    ##[31,] -1.36586591  0.660328351  6.9035280 -1.25971208  5.1036532 -1.929447
    ##[32,] -0.50659616  2.524408100  5.2703243  4.29798278  5.5706909  5.721177
    ##[33,]  5.48818201  2.223653532 -2.1801912  2.28444983  5.5241792  7.290854
    ##[34,] -2.41191086  3.284500295  1.1954799  1.07797125  1.8349489  7.606197
    ##[35,]  0.46284522  2.074024948  1.9438606  3.46028131  6.4283998  4.334165
    

    Set columns that are NA in df1 to NA in df2

    For the complement question, simulate the data set as:

    set.seed(123) ## only for full reproducibility
    library(raster) 
    r <- raster(nrow=7, ncol=5)
    nlayers <- 6
    df1 <- stack(sapply(1:nlayers, function(i) setValues(r, rnorm(ncell(r), i, 3)))) 
    df2<- stack(sapply(1:nlayers, function(i) setValues(r, rnorm(ncell(r), i, 3)))) 
    df1[[1]][,1]<-NA  ## set column 1 of layer 1 to NA 
    df1[[1]][,2]<-NA  ## set column 2 of layer 1 to NA 
    df1[[2]][,2]<-NA  ## set column 2 of layer 2 to NA 
    df1[[3]][,2]<-NA  ## set column 2 of layer 3 to NA 
    df1[[4]][,5]<-NA  ## set column 5 of layer 4 to NA 
    df1[[5]][,5]<-NA  ## set column 5 of layer 5 to NA 
    df1[[6]][,3]<-NA  ## set column 3 of layer 6 to NA 
    

    Note that df1 now looks like:

    df1[]
    ##         layer.1     layer.2    layer.3    layer.4    layer.5   layer.6
    ## [1,]         NA  4.06592076  1.5269065  3.8649168  7.1053530  2.712011
    ## [2,]         NA          NA         NA  1.6452866  4.2134075  6.113365
    ## [3,]  5.6761249  1.81426487  6.0172156 -1.0038258  0.2835675        NA
    ## [4,]  1.2115252  1.08211201  0.8723977  2.8593204  0.4559970  7.309570
    ## [5,]  1.3878632  0.85858700  0.9359742         NA         NA  4.624904
    ## [6,]         NA -0.08412094  6.0767141  2.2739591  3.4072804  2.810022
    ## [7,]         NA          NA         NA  5.8238930  0.6147332  9.789556
    ## [8,] -2.7951837 -1.79618905 -0.6621531 -0.8536481  7.0637503        NA
    ## [9,] -1.0605586  8.50686790  3.5439104  3.8333141 11.3003268  3.403461
    ##[10,] -0.3369859  5.62388599  2.5833259         NA         NA  5.291161
    ##[11,]         NA -1.36932575  3.0172926  4.9034601  7.3632165  5.408472
    ##[12,]         NA          NA         NA  4.3170286  7.3071267  9.329761
    ##[13,]  2.2023144  0.60003394  1.8880199  2.0778820  5.9966077        NA
    ##[14,]  1.3320481  4.33989536  4.9331296  1.4508870  1.9748702  8.262161
    ##[15,] -0.6675234  1.74989280  2.3385403         NA         NA  4.502124
    ##[16,]         NA  2.75995554  3.9953459  4.3529398  4.1588140  6.643336
    ##[17,]         NA          NA         NA  1.1575762  6.6889686  5.025942
    ##[18,] -4.8998515  1.87138863  4.3055445  2.5283277  3.8826837        NA
    ##[19,]  3.1040677  6.10580685  2.0222052  3.2317234  7.9309202  3.313910
    ##[20,] -0.4183742  1.32268704  6.4464229         NA         NA  2.067595
    ##[21,]         NA  6.54941181  5.9805116  2.0441503  8.1581344 11.991640
    ##[22,]         NA          NA         NA  4.7061597  1.8524690  7.802126
    ##[23,] -2.0780133  3.75384125  3.7161952  4.2338825  1.2195343        NA
    ##[24,] -1.1866737  2.37156273  1.1162818  1.1144301 14.7231198  4.166502
    ##[25,] -0.8751178  2.64782471  7.0819573         NA         NA  2.443560
    ##[26,]         NA  3.13891845  1.1992212  8.3336526  5.8946828 12.596431
    ##[27,]         NA          NA         NA  5.3545122  6.9097090  9.937239
    ##[28,]  1.4601194  1.00037785  7.5978319  4.1236988  3.5486581        NA
    ##[29,] -2.4144108 -1.05572615  2.2928989  2.7325095  6.5505861  7.629582
    ##[30,]  4.7614448 -1.21537368 -0.0792627         NA         NA  4.756980
    ##[31,]         NA  2.91058592  0.8687803  7.3940116  4.3538585  4.571259
    ##[32,]         NA          NA         NA -0.3819202  5.1958791  3.634191
    ##[33,]  3.6853770  2.15901268  2.2599244  6.2198425  4.8977982        NA
    ##[34,]  3.6344005  4.76680240  1.9573722  9.7273107 11.3853557 10.952722
    ##[35,]  3.4647432  8.15025406  0.1451443         NA         NA  5.837916
    

    The solution is the same except now we use colSums instead of rowSums, and we set the column instead of the row for each layer:

    inds <- which(!colSums(!is.na(df1)), arr.ind=TRUE)
    ## loop over layers and set the appropriate column for each layer
    for (i in seq_len(nrow(inds))) df2[[inds[i,2]]][,inds[i,1]] <- NA
    df2[]
    ##        layer.1      layer.2    layer.3     layer.4     layer.5   layer.6
    ## [1,]          NA  7.707085465 -2.0024253  6.11057171  8.04482952 10.135710
    ## [2,]          NA           NA         NA  3.68298600 -0.97824547  7.368709
    ## [3,]  4.69742764 -2.079522111  4.1580797  0.22405412  3.71816214        NA
    ## [4,] -0.54819149  0.005691694  2.2030451  9.05330712  5.34991185  4.693064
    ## [5,] -1.97752145  3.456379937  3.3544335          NA          NA  7.038311
    ## [6,]          NA  0.873191385  3.4021159  4.71229082  6.00170883  4.058863
    ## [7,]          NA           NA         NA  7.65432583  6.23428976 -0.472939
    ## [8,] -1.16919791  0.968248298  7.9225385 -0.01632286  4.90089152        NA
    ## [9,] -2.70881936  2.271489941  2.3428489  5.98246089 -2.39769458  3.511567
    ##[10,] -2.85414717  6.795526313  3.5041962          NA          NA  4.279319
    ##[11,]          NA  1.734304664  6.5051516  6.05123657  4.38410223 10.511702
    ##[12,]          NA           NA         NA  3.81753414  6.95357984  3.677565
    ##[13,]  4.32954442  3.892262347  6.4357893  5.89888214  5.82129947        NA
    ##[14,]  3.12276506  1.659080313  1.2675960  8.00655285  8.07401970  2.217951
    ##[15,] -0.09097189 -2.598706009  9.0074482          NA          NA  4.936373
    ##[16,]          NA  0.436648047  3.2001026  7.05267591  4.37062049  5.779332
    ##[17,]          NA           NA         NA  0.43469789  6.13450332  2.494046
    ##[18,] -1.15165448  2.141463298 -1.0527081  1.83518668  2.16377351        NA
    ##[19,]  3.65395150  5.900596033  3.0629508  8.55765313  7.57076903  5.913475
    ##[20,] -2.04677774  8.879236921  6.7497437          NA          NA  8.012088
    ##[21,]          NA  6.642743177  0.8542734 -2.15666846 12.25032006  1.048360
    ##[22,]          NA           NA         NA -0.09211236  0.04685331  4.950737
    ##[23,]  1.64361648 -3.269582187  0.1843839  3.39765695  3.60803827        NA
    ##[24,] -1.21558311  0.833660408 -0.1575398  6.59733821  7.47613959  4.383573
    ##[25,] -0.72316607  2.267621669  1.6885214          NA          NA  6.681876
    ##[26,]          NA  4.535039012  3.9935375  5.87256242  3.23155688  7.476686
    ##[27,]          NA           NA         NA  6.87701613  2.00965777  6.803505
    ##[28,]  2.25694721  4.052928288  3.6359413  9.01316449  5.43342711        NA
    ##[29,]  1.97291303 -2.185823049  6.7100251  4.16805020  4.95707776  5.631874
    ##[30,] -1.34460946  4.548929137  9.1127221          NA          NA  4.758970
    ##[31,]          NA  0.660328351  6.9035280 -1.25971208  5.10365320 -1.929447
    ##[32,]          NA           NA         NA  4.29798278  5.57069095  5.721177
    ##[33,]  5.48818201  2.223653532 -2.1801912  2.28444983  5.52417919        NA
    ##[34,] -2.41191086  3.284500295  1.1954799  1.07797125  1.83494887  7.606197
    ##[35,]  0.46284522  2.074024948  1.9438606          NA          NA  4.334165