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 df1
where all rows are NAs
, go to df2
and set all values in matching columns to NAs
?
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 areNA
s, go todf2
and set all values in matching rows toNA
s?
I will answer this question first and then address the complement problem of:
How can one find all columns in
df1
where all rows areNA
s, go todf2
and set all values in matching columns toNA
s?
which is the OP's original question.
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 NA
s 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 NA
s. 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
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