I am trying to count the number of group of depressions (negative values) from a climate data set and have least idea on how to go about it. Let me explain the scenario. I have a raster brick with 468 layers and and each layer has 7458 cells.
> cntneg
class : RasterBrick
dimensions : 66, 113, 7458, 468 (nrow, ncol, ncell, nlayers)
resolution : 0.108, 0.108 (x, y)
extent : 77.946, 90.15, 24.946, 32.074 (xmin, xmax, ymin, ymax)
coord. ref. : NA
values : in memory
min values : -359.51 -341.21 -315.45 -148.10 -187.39 -52.87 -66.72 -52.17 -286.81 -306.74 ...
max values : -7.589 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 ...
Now for example lets take the 5000th pixel
> cntneg[5000]
Which will give me 468 values of that pixel over time.
[1] -90.795107 -89.990016 -94.840754 0.000000 -15.085517 0.000000
[7] 0.000000 0.000000 0.000000 -12.469657 -114.757702 -115.372023
[13] -107.194478 -92.916680 -115.105817 -113.205776 -115.003430 -62.175070
[19] 0.000000 0.000000 0.000000 -72.358073 -105.006508 -115.372023
[25] -48.836959 -102.314928 -113.271826 -115.372023 -79.530055 0.000000
[31] 0.000000 0.000000 0.000000 -15.048987 -115.208204 -115.372023
[37] -115.003430 -108.757617 -113.122594 -115.372023 -111.699048 -17.618498
[43] 0.000000 0.000000
Now here I need to do two tasks
1) count number of times the rainfall went below the average - those with negative values. And zeros are with positive RF values (which i converted to zero using reclass) for the ease of calculation. In the above example I want to pick the group of negative numbers and count. ie, (-90.795107 -89.990016 -94.840754), (-15.085517), ( -12.469657 -114.757702 -115.372023, -107.194478 -92.916680 -115.105817 -113.205776 -115.003430 -62.175070), (-72.358073 -105.006508 -115.372023, -48.836959 -102.314928 -113.271826 -115.372023 -79.530055) etc. The resulted layer pixel value should be the count of these groups, which in this case is 5. Like wise need to do for all the pixels along time dimension.
2) For each group I want to pick the minimum values and resulted pixel will have the sum of those minimum values. If a group has one value, keep the same.
I am stuck to start with this process. I am assuming I need to convert the brick into dataframe and do this.
Can any one help me in giving a lead on how to go about it?
Really appreciate any help.
Sorry if the explanation is confusing.
Regards SP
There is a nice function called rle
that finds contiguous elements of a vector satisfying a condition. The function call res<-rle(vector<0)
gives back res$lengths
and res$values
, containing the length and the value of the blocks in your vector, respectively.
So we can do it like this
sample.data <- rnorm(20)
b <- (1:length(rle(sample.data<0)$lengths))
c <- rle(sample.data<0)$lengths
aggregate(sample.data,by = list(unlist(mapply(rep,b,c))),min)
(Sorry for the list(unlist()), apparently I don't know how to flatten a list in R)
The mapply
command creates a list of identifiers for each block, numbered from 1 to total number of blocks. The rep command ensures that each identifier is repeated as long as its respective block. Then we aggregate our sample data, applying the min function on all entries with the same identifier. The resulting data.frame has alternating positive and negative entries. The negative entries are the desired minima of the negative blocks.
The result (in my case):
sample.data
[1] 0.781352094 0.005568218 1.230054543 -0.825140291 0.861346012
[6] -0.829708513 -0.452102503 -0.559146728 -1.017299175 -0.979450702
[11] -1.492603312 -0.466351610 1.189238669 -0.674493774 -0.120572288
[16] -0.336176940 0.348560999 0.420171989 1.459037512 0.056945430
aggregate(sample.data,by = list(unlist(mapply(rep,b,c))),min)
Group.1 x
1 1 0.005568218
2 2 -0.825140291
3 3 0.861346012
4 4 -1.492603312
5 5 1.189238669
6 6 -0.674493774
7 7 0.056945430
We can print out only the minima like this
agg.df <- aggregate(sample.data,by = list(unlist(mapply(rep,b,c))),min)
agg.df[,2][rle(sample.data<0)$value]
[1] -0.8251403 -1.4926033 -0.6744938