r convert raster stack or brick to an animation - r

I have downloaded some NetCDF files of land use scenario results from http://luh.umd.edu/data.shtml. Each file at this location has values for 11 land use types with annual values from 2015 to 2100. I'd like to make an animated gif or movie that shows the changes over time. This seems like it should be straightforward but I've tried a variety of routes, none of which work, so I'm hoping for some that actually work.
1. One approach involves creating a raster stack or brick of one of the land use variables using the stack or brick functions from the raster package. then using the raster animate function. Unfortunately, I get the following error message "animation of RasterLayer [stack, brick] objects not supported".
Another option is to convert each year of the land use data into a SpatialPixelDataFrame and then into a data.frame, use ggplot to create a gif and then combine the gifs into an animated gif. But this process seems extremely convoluted.
An R script that contains my current efforts to do this is here.

Having a look through your code, I can make the code below work.
Basically, I'm making a big dataframe with data for all years.
mydf <- purrr::map_dfr(
as.list(ncin.brick),
~setNames(as.data.frame(as(., "SpatialPixelsDataFrame")), c('value', 'x', 'y')),
.id = 'year'
)
gg <- ggplot(
mydf,
aes(x = x, y = y, fill = value)
) +
geom_sf(data = borders, fill = "transparent", color = "black", inherit.aes = FALSE) +
geom_tile() +
scale_fill_viridis_c() +
ggthemes::theme_map()
gganim <- gg + transition_time(as.numeric(year)) #+ labs(title = "Year: {frame_time}")
gganim
The picture below is the result (animation is subtle).

Try raster::animate(), there are several incompatible animate functions across packages and this seems like a clash.
I usually animate using a loop to plot raster slices, and capture that using the animate package, e.g. with saveHTML().
For ggplot2 see the gganimate package, but it doesn't scale well given the need to expand the data out.

Related

reduce number of points of a geometry of sf object in R

I am facing the following problem:
when using the shape file of intercommunal limits in France (which you can download here: https://www.data.gouv.fr/fr/datasets/r/971027a8-3ceb-48c6-97e3-59deaf7e2704), plotting the map is really slow:
library(sf)
library(ggplot2)
epci_france <- read_sf("./epci_shape/EPCI_SHAPEFILE.shp")
ggplot()+
geom_sf(data = test,
aes(geometry = geometry),
color = "black")+
guides(fill = "none")+
theme_void()
I think this is due to the high number of points in the shapefile.
Following comments in here: https://github.com/tidyverse/ggplot2/issues/2655, I tried
sum(rapply(st_geometry(epci_france), nrow))
[1] 1913182
which looks like a lot of points. I am looking for a way to lower this number, i.e. lower the precision of the limits of the geometry. I tried smooth from library(smoothr), but it has the opposite effect: it increases the number of points. I tried to cast it to other formats with st_cast, but it did not work either.
How should I proceed? My objective is to have a simple delimitation of the intercommunal limits to make choropleth maps. Thanks!

Plotting graph from Text file using R

I am using an NS3 based simulator called NDNsim. I can generate certain trace files that can be used to analyze performance, etc. However I need to visualize the data generated.
I am a complete Novice with R, and would like a way to visualize. Here is how the output looks from which I would to plot. Any help is appreciated.
It's pretty difficult to know what you're looking for, since you have almost 50,000 measurements across 9 variables. Here's one way of getting a lot of that information on the screen:
df <- read.table(paste0("https://gist.githubusercontent.com/wuodland/",
"9b2c76650ea37459f869c59d5f5f76ea/raw/",
"6131919c105c95f8ba6967457663b9c37779756a/rate.txt"),
header = TRUE)
library(ggplot2)
ggplot(df, aes(x = Time, y = Kilobytes, color = Type)) +
geom_line() +
facet_wrap(~FaceDescr)
You could look into making sub structures from your input file and then graphing that by node, instead of trying to somehow invoke the plotter in just the right way.
df <- read.table(paste0("https://gist.githubusercontent.com/wuodland/",
"9b2c76650ea37459f869c59d5f5f76ea/raw/",
"6131919c105c95f8ba6967457663b9c37779756a/rate.txt"),
header = TRUE)
smaller_df <- df[which(df$Type=='InData'), names(df) %in% c("Time", "Node",
"FaceId", "FaceDescr", "Type", "Packets", "Kilobytes",
"PacketRaw", "KilobyteRaw")]
ggplot(smaller_df, aes(x = Time, y = Kilobytes, color = Type))
+ geom_line()
+ facet_wrap (~ Node)
The above snippet makes a smaller data frame from your original text data using only the "InData" Type, and then plots that by nodes.

Identifying grids into a map/shapefile

I have some questions about maps/shapefiles. I'm not a expert in R, so, to make it easier do understand what I'm going for, I'll enumerate:
1- Identify each grid on the map, and maybe omit some of these grids.
2- Color each grid by values from a data frame
I just made what i'm trying to make using Photoshop to help to illustrate my goal here
I made this map using the 'intersect' function with a shapefile I got from internet and a grid i made using 'rastertoPolygons' function, but I'm not sure if using a .shp is the best way to get what I want, altough it has been the only way I found to do this, since I got lost trying with ggplot2 options (and I'm very familiar with the package)
Any help or suggestion will be awesome.
Sorry if I made a stupid question and sorry for my bad english.
If you are asking how you can do this in ggplot, you can pretty easily. If not, can you clarify what you are asking?
You can draw the map of Brazil easily, and use your shapefile either directly, or with some adjustments. Since I don't have your shapefile, I'll use one of my own and you can adjust for yourself. I just made two arbitrary boxes, and labelled them with a field called id. Your grouping name may be different.
library(ggplot2)
library(maps)
library(rgdal)
brasilia <- borders("world", regions = "Brazil")
brazil <- ggplot() + brasilia + theme_bw() + xlab("Longitude (decimals)") + ylab("Latitude (decimals)") +
theme(panel.border = element_blank(), panel.grid.major = element_line(colour = "grey80"), panel.grid.minor = element_blank()) +
coord_fixed(1.0)
brazil # You can see just the map of Brazil
Next, import your shapefile using rgdal, which should read all the metadata so you don't have to tell it what projection, etc. Just tell it where it is, and what the shape file name is. See ?readOGR for help.
shapes <- readOGR(dsn = "C:/foo/GIS/Brazil", layer = "brazil_grid")
brazil_shapes <- brazil + geom_path(data = shapes, aes(x = long, y = lat, group = id), color = "red")
brazil_shapes
Filling them with the colors you want may take the most work, creating a table to map your fill levels to the grids. It looks like this answer can point you in the right direction though. R ggplot2 merge with shapefile and csv data to fill polygons
Here's a good overview of mapping in R. http://eriqande.github.io/rep-res-web/lectures/making-maps-with-R.html

Controlling alpha in ggparcoord (from GGally package)

I am trying to build from a question similar to mine (and from which I borrowed the self-contained example and title inspiration). I am trying to apply transparency individually to each line of a ggparcoord or somehow add two layers of ggparcoord on top of the other. The detailed description of the problem and format of data I have for the solution to work is provided below.
I have a dataset with thousand of lines, lets call it x.
library(GGally)
x = data.frame(a=runif(100,0,1),b=runif(100,0,1),c=runif(100,0,1),d=runif(100,0,1))
After clustering this data I also get a set of 5 lines, let's call this dataset y.
y = data.frame(a=runif(5,0,1),b=runif(5,0,1),c=runif(5,0,1),d=runif(5,0,1))
In order to see the centroids y overlaying x I use the following code. First I add y to x such that the 5 rows are on the bottom of the final dataframe. This ensures ggparcoord will put them last and therefore stay on top of all the data:
df <- rbind(x,y)
Next I create a new column for df, following the question advice I referred such that I can color differently the centroids and therefore can tell it apart from the data:
df$cluster = "data"
df$cluster[(nrow(df)-4):(nrow(df))] <- "centroids"
Finally I plot it:
p <- ggparcoord(df, columns=1:4, groupColumn=5, scale="globalminmax", alphaLines = 0.99) + xlab("Sample") + ylab("log(Count)")
p + scale_colour_manual(values = c("data" = "grey","centroids" = "#94003C"))
The problem I am stuck with is from this stage and onwards. On my original data, plotting solely x doesn't lead to much insight since it is a heavy load of lines (on this data this is equivalent to using ggparcoord above on x instead of df:
By reducing alphaLines considerably (0.05), I can naturally see some clusters due to the overlapping of the lines (this is again running ggparcoord on x reducing alphaLines):
It makes more sense to observe the centroids added to df on top of the second plot, not the first.
However, since everything it is on a single dataframe, applying such a high value for alphaLine makes the centroid lines disappear. My only option is then to use ggparcoord (as provided above) on df without decreasing the alphaValue:
My goal is to have the red lines (centroid lines) on top of the second figure with very low alpha. There are two ways I thought so far but couldn't get it working:
(1) Is there any way to create a column on the dataframe, similar to what is done for the color, such that I can specify the alpha value for each line?
(2) I originally attempted to create two different ggparcoords and "sum them up" hoping to overlay but an error was raised.
The question may contain too much detail, but I thought this could motivate better the applicability of the answer to serve the interest of other readers.
The answer I am looking for would use the provided data variables on the current format and generate the plot I am looking for. Better ways to reconstruct the data is also welcomed, but using the current structure is preferred.
In this case I think it easier to just use ggplot, and build the graph yourself. We make slight adjustments to how the data is represented (we put it in long format), and then we make the parallel coordinates plot. We can now map any attribute to cluster that you like.
library(dplyr)
library(tidyr)
# I start the same as you
x <- data.frame(a=runif(100,0,1),b=runif(100,0,1),c=runif(100,0,1),d=runif(100,0,1))
y <- data.frame(a=runif(5,0,1),b=runif(5,0,1),c=runif(5,0,1),d=runif(5,0,1))
# I find this an easier way to combine the two data.frames, and have an id column
df <- bind_rows(data = x, centroids = y, .id = 'cluster')
# We need to add id's, so we know which points to connect with a line
df$id <- 1:nrow(df)
# Put the data into long format
df2 <- gather(df, 'column', 'value', a:d)
# And plot:
ggplot(df2, aes(column, value, alpha = cluster, color = cluster, group = id)) +
geom_line() +
scale_colour_manual(values = c("data" = "grey", "centroids" = "#94003C")) +
scale_alpha_manual(values = c("data" = 0.2, "centroids" = 1)) +
theme_minimal()

ggplot boxplots with scatterplot overlay (same variables)

I'm an undergrad researcher and I've been teaching myself R over the past few months. I just started trying ggplot, and have run into some trouble. I've made a series of boxplots looking at the depth of fish at different acoustic receiver stations. I'd like to add a scatterplot that shows the depths of the receiver stations. This is what I have so far:
data <- read.csv(".....MPS.csv", header=TRUE)
df <- data.frame(f1=factor(data$Tagging.location), #$
f2=factor(data$Station),data$Detection.depth)
df2 <- data.frame(f2=factor(data$Station), data$depth)
df$f1f2 <- interaction(df$f1, df$f2) #$
plot1 <- ggplot(aes(y = data$Detection.depth, x = f2, fill = f1), data = df) + #$
geom_boxplot() + stat_summary(fun.data = give.n, geom = "text",
position = position_dodge(height = 0, width = 0.75), size = 3)
plot1+xlab("MPS Station") + ylab("Depth(m)") +
theme(legend.title=element_blank()) + scale_y_reverse() +
coord_cartesian(ylim=c(150, -10))
plot2 <- ggplot(aes(y=data$depth, x=f2), data=df2) + geom_point()
plot2+scale_y_reverse() + coord_cartesian(ylim=c(150,-10)) +
xlab("MPS Station") + ylab("Depth (m)")
Unfortunately, since I'm a new user in this forum, I'm not allowed to upload images of these two plots. My x-axis is "Stations" (which has 12 options) and my y-axis is "Depth" (0-150 m). The boxplots are colour-coded by tagging site (which has 2 options). The depths are coming from two different columns in my spreadsheet, and they cannot be combined into one.
My goal is to to combine those two plots, by adding "plot2" (Station depth scatterplot) to "plot1" boxplots (Detection depths). They are both looking at the same variables (depth and station), and must be the same y-axis scale.
I think I could figure out a messy workaround if I were using the R base program, but I would like to learn ggplot properly, if possible. Any help is greatly appreciated!
Update: I was confused by the language used in the original post, and wrote a slightly more complicated answer than necessary. Here is the cleaned up version.
Step 1: Setting up. Here, we make sure the depth values in both data frames have the same variable name (for readability).
df <- data.frame(f1=factor(data$Tagging.location), f2=factor(data$Station), depth=data$Detection.depth)
df2 <- data.frame(f2=factor(data$Station), depth=data$depth)
Step 2: Now you can plot this with the 'ggplot' function and split the data by using the `col=f1`` argument. We'll plot the detection data separately, since that requires a boxplot, and then we'll plot the depths of the stations with colored points (assuming each station only has one depth). We specify the two different plots by referencing the data from within the 'geom' functions, instead of specifying the data inside the main 'ggplot' function. It should look something like this:
ggplot()+geom_boxplot(data=df, aes(x=f2, y=depth, col=f1)) + geom_point(data=df2, aes(x=f2, y=depth), colour="blue") + scale_y_reverse()
In this plot example, we use boxplots to represent the detection data and color those boxplots by the site label. The stations, however, we plot separately using a specific color of points, so we will be able to see them clearly in relation to the boxplots.
You should be able to adjust the plot from here to suit your needs.
I've created some dummy data and loaded into the chart to show you what it would look like. Keep in mind that this is purely random data and doesn't really make sense.

Resources