Drawing a Square Line Chart using quantmod - r

Is there a way to get quantmod to draw a square line chart?
I've tried modifying my time series so that each data point is replicated one second before the next datapoint (hoping this would approximate a square line), but quantmod seems to data on the x axis sequentially & evenly spaces without regard to the actually values of x (i.e. the horizontal space between one point an the next is the same whether the delta-T is 1 second or 1 minute).
I suppose I could convert my timeseries from a sparse to a dense one (one entry per second instead of one entry per change in value), but this seems very kludgy and should be unnecessary.
I'm constructing my time series thus:
library(quantmod)
myNumericVector <- c(3,7,2,9,4)
myDateTimeStrings <- paste("2011-10-31", c("5:26:00", "5:26:10", "5:26:40", "5:26:50", "5:27:00"))
myXts <- xts(myNumericVector, order.by=as.POSIXct(myDateTimeStrings))
And drawing the chart like so:
chartSeries(myXts, type="line", show.grid="true", theme=chartTheme("black"))
To illustrate what I have vs. what I want, the result looks like the blue line below but I'd like something more like the green:
Also, for the curious, here is the code that replicates points in the time series such that the gap between one value and the next are as small as possible:
mySquareDateTimes <- rep(as.POSIXct(myDateTimeStrings),2)[-1]
mySquareDateTimes[seq(2,8,by=2)] <- mySquareDateTimes[seq(2,8,by=2)] - 1
mySquareXts <- xts(rep(myNumericVector,each=2)[-10], order.by=mySquareDateTimes)
chartSeries(mySquareXts, type="line", show.grid="true", theme=chartTheme("black"))
The results are less than ideal.

You want a line.type of "step":
chartSeries(myXts, line.type="s")
See ?plot, specifically "type" under ... in the Arguments section (you may want "S" instead of "s").

Related

Moving spatial data off gird cell corners

I have a seemingly simple question that I can’t seem to figure out. I have a large dataset of millions of data points. Each data point represents a single fish with its biological information as well as when and where it was caught. I am running some statistics on these data and have been having issues which I have finally tracked down to some data points having latitude and longitude values that fall exactly on the corners of the grid cells which I am using to bin my data. When these fish with lats and long that fall exactly onto grid cell corners are grouped into their appropriate grid cell, they end up being duplicated 4 times (one for each cell that touches the grid cell corner their lats and long identify).
Needless to say this is bad and I need to force those animals to have lats and long that don’t put them exactly on a grid cell corner. I realize there are probably lots of ways to correct something like this but what I really need is a simply way to identify latitudes and longitudes that have integer values, and then to modify them by a very small amount (randomly adding or subtracting) so as to shift them into a specific cell without creating a bias by shifting them all the same way.
I hope this explanation makes sense. I have included a very simple example in order to provide a workable problem.
fish <- data.frame(fish=1:10, lat=c(25,25,25,25.01,25.2,25.1,25.5,25.7,25,25),
long=c(140,140,140,140.23,140.01,140.44,140.2,140.05,140,140))
In this fish data frame there are 10 fish, each with an associated latitude and longitude. Fish 1, 2, 3, 9, and 10 have integer lat and long values that will place them exactly on the corners of my grid cells. I need some way of shifting just these values by something like plus are minus 0.01.
I can identify which lats or longs are integers easy enough with something like:
fish %>%
near(as.integer(fish$lat))
But am struggling to find a way to then modify all the integer values by some small amount.
To answer my own question I was able to work this out this morning with some pretty basic code, see below. All it takes is making a function that actually looks for whole numbers, where is.integer does not.
# Used to fix the is.integer function to actually work and not just look at syntax
is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol
# Use ifelse to change only whole number values of lat and long
fish$jitter_lat <- ifelse(is.wholenumber(fish$lat), fish$lat+rnorm(fish$lat, mean=0, sd=0.01), fish$lat)
fish$jitter_long <- ifelse(is.wholenumber(fish$long), fish$long+rnorm(fish$long, mean=0, sd=0.01), fish$long)

r Terra issue with multicategorical raster. How to properly extract the categories and their values into layers without losing data?

I am working with rTerra and having an issue with the CONUS historical disturbance dataset from LANDFIRE found here:https://landfire.gov/version_download.php (HDist is the name). To summarize what I want to do, I want to take this dataset, crop and project to my extent, then take the values of the cells and separate them as layers. So I want a layer for severity, one for disturbance type, etc. The historical disturbance data has these things all in one attribute table. In terra, this attribute table is set up under categories and this is providing a lot of problems. I have not had issues with the crop nor reproject, it is getting into the values and separating the categories into layers. I have the following code
library(terra)
setwd("your pathway to historical disturbance tif here")
h1 <- terra::rast("LC16_HDst_200.tif") #read in the Hdist tif
h2 <- terra::project(h1, "EPSG:5070", method = "near") #project it using nearest neighbor
h3 <- crop(h2, ext([xmin,xmax,ymin,ymax]) #crop to the extent
h3
This then gives the output in the extent and projection I want but the main focus is the categories
categories : Count, HDIST_ID, DISTCODE_V, DIST_TYPE, TYPE_CONFI, SEVERITY, SEV_CONFID, HDIST_CAT, FDIST, R, G, B
So I learned that with these kinds of datasets, the values are stored under these categories.
if I plot with plot(h3)
I only get the first row of the count category. In order to switch that category I can use
activeCat(h3) <- 4
h3
and I would get
name : DIST_TYPE
min value : Clearcut
max value : Wildland Fire Use
The default active category was count, but now its DIST_TYPE, the fourth category, nothing too crazy. I try plotting
plot(h3)
I only get NoData plotted. None of the others. There is a function called catalyze() That claims to take your categories and converts them all into numerical layers
h4 <- catalyze(h3)
which gave me a thirteen layer dataset, which makes sense because there are 13 categories and it takes them and converts them into numeric layers. I tried plotting
plot(h4, 4) #plot h4 layer 4, which would correspond to DIST_TYPE category
it only plots a value of 8, and it looks to only show what is likely noData values. The map is mostly green, which is inline with the NoData from HDist.
Anytime I try directly accessing values, it crashes. When I look at the min and max values I get 8 and 8 for min and max for that 'name" names: DIST_TYPE min values: 8 max values: 8. Other categories show a similar pattern. So it appeared to just take the first row of values for each category and make that the entire layer.
In summary, it is clear that terra stores all of the values that would easily be seen in an attribute table if the dataset were brought into arcgis. However, whenever I try to plot it or work with it, even before any real manipulation, it only accesses the top row of that attribute table, and when I catalyze, it just seems to mess everything up even more. I know this is really easy to solve in arcgis pro, but I want to keep everything in r from a documentation coherency standpoint. Any terra whizzes know what to do about this? I figure it has to be something very easy, but I don't really know what else to try. Maybe it is some major issue too. I have the same issue with LANDFIRE evt data. I have not had this issue with simple rasters such as dem, canopy cover, etc. It is only with these rasters with multiple categories (or columns in an attribute table)
edit
this is the break image
That failed because the (ESRI) VAT IDs are not in the expected (for GDAL categories) 0..255 range. This has now been fixed and I get:
library(terra)
#terra version 1.4.6
r <- rast("LC16_HDst_200.tif")
activeCat(r) <- 4
r <- crop(r, ext(-93345, -57075, 1693125, 1716735))
plot(r)

Plot along different dimensions

I have the following basic code. The first line sums p along dimension 1 to create a 1 x column array. The next line plot A. Unfortunately, it seems that Julia assumes it must plot many lines (in this case just points) along dimension 2.
A = sum(p,dims = 1)
plot(A)
So, my question is, how can I plot a simple line when the data is in a 1 x column array?
I assume you use Plots.jl. The following is from Plots.jl's documentation.
If the argument [to plot] is a "matrix-type", then each column will map to a series, cycling through columns if there are fewer columns than series. In this sense, a vector is treated just like an "nx1 matrix".
The number of series plot(a) tries to plot is the number of columns in a.
To get a single series, you can do one of the followings
plot(vec(a)) # `vec` will give you a vector view of `a` without an allocation
plot(a') # or `plot(transpose(a))`. `transpose` does not allocate a new array
plot(a[:]) # this allocates a new array so you should probably avoid it

Vectorizing raster brick objects with r-raster so that I can count them

I have an image of columns of red and blue bordered circles like so:
Where the columns alternate red and blue (in this example the first column is red)
I have been able to create a raster brick and plot the image in RGB layers but I want to count these columns into a vector like this (from above example). Values 1(red) and 2(blue)
1,1,1,1,2,2,2,1,1,2,1,1,1 ...
Is it possible to clear out areas of the brick I don't need for counting and collapse the brick down into values I could then convert into the numbers or labels I want? Or is there a much simpler way that I'm unable to locate? Also long term I want to be able to point the program at several images without opening them myself.
Edit: To clear somethings up, I want to count the circles top to bottom, left to right. For example once the first col is counted, I want to start over at the top of the next column on the right. Also I'm not sure if I'm headed in the right direction but I was able to remove all background cells from the image. leaving me with a plot of only values where the circles are.
Edit 2:
The current code I have for the image above.
color.image <- brick("image")
color.image = dropLayer(color.image,4) #gets rid of a channel
plot(color.image)
e <- extent(-10, 240, 45, 84.8) #xmin,xmax, ymin,ymax
ccolor.image <- crop(color.image, e)
plot(ccolor.image)
#thresholding to simplify what I was dealing with
mini=ccolor.image[ccolor.image > 97] = NA
mini=ccolor.image[ccolor.image < 15] = NA
mini=ccolor.image[ccolor.image > 20] = 80
plot(ccolor.image)
mcolor = as.matrix(ccolor.image)
colSums(ccolor.image)
rowSums(ccolor.image)
Edit 3:
I figured it out! Or at least found a round about way to do it, will post code later once I clean it up some. I still however would like input on creating a vector based on the matrix of values I have for my simplified raster brick matrix. Code coming soon!
The fastest way to count values in a raster is freq(x, merge=T). This will give you the value in one column and the frequency in as many columns as you have rows. In this way we the need to poll a value of interest and sum all the other columns (the counts). Hope that helps!
freq_vals <- freq ( rasterbrick , merge = T )
sum( freq_vals [ which ( freq_vals$value == 1 ) , 2 : ncol ( freq_vals ) ] )

Making multiple graphs from individual lines in R, iterating through a dataset

I have a dataset that looks like this:
> averages
compound control.0 control.30 surgery.0 surgery.30
1. A 3.609958 3.578200086 3.556325 3.669107598
2. B 4.984090 4.798330495 4.965342 4.812247664
I want to make a graph for only compound A that plots two lines- one connecting (0, control.0) to (30, control.30) and one that plots (0, surgery.0) to (30, surgery.30). I also have 200 compounds so I would ideally like to be able to have the program go down the list and spit out a graph for each compound without me manually going in and changing the line number. How would I go about doing this?
For two line segments per graph, use this:
with(subset(averages, compound=="A"), plot(c(0,30,NA,0,30),c(control.0,control.30,NA,surgery.0,surgery.30), type="l"))
Then change the subset condition to create a loop.

Resources