Tips for merging time-series datasets with varying time intervals into one visual representation using Google Earth Engine

Currently, I am facing a challenge in plotting monthly and yearly soil moisture time-series in the same chart. The ImageCollection contains 480 images (one per month) for the monthly data and another ImageCollection with 40 images (one per year) for the yearly data.

I have managed to plot them individually, but I'm struggling to combine both plots into a single chart. I explored options such as using innerJoin() beforehand, which resulted in downsampling the monthly collection from 480 to 40 images. Another option was to fill gaps in the yearly collection with Na values, similar to fillNa in pandas, but I couldn't find a suitable method to do so.

Below is a snippet of the code:

// --- GLOBALS ---

var dateStart = ee.Date('1980-01-01'); 
var dateEnd = ee.Date('2019-12-31');
var scale = 1000;
var studyArea = ee.FeatureCollection('TIGER/2018/States').filterMetadata('NAME', 'equals', 'Nevada');

var monthlySoil = ee.ImageCollection('IDAHO_EPSCOR/TERRACLIMATE') // Load data
                .filter(ee.Filter.date(dateStart, dateEnd))
                .select('soil');

// --- TIME SERIES ---

// Create list of dates for time series
var dateListYearly = ee.List.sequence(0,dateEnd.difference(dateStart,'year').round(),1);
var makeDateListYearly = function(n) {return dateStart.advance(n,'year')};
dateListYearly = dateListYearly.map(makeDateListYearly);

// Yearly data
var yearlySoil = [];
yearlySoil = dateListYearly.map(function(d){ // Resample yearly
  var start = ee.Date(d);
  var end = ee.Date(d).advance(1,'year');
  var dateRange = ee.DateRange(start,end);
  var yearlySoilInter = monthlySoil
                      .filterDate(dateRange)
                      .mean()
                      .clip(studyArea)
                      .rename('Yearly');
  return(yearlySoilInter.set('system:time_start', start.millis())); // Add time band
});
yearlySoil = ee.ImageCollection(yearlySoil);

// --- PLOT ---

var options1 = { // Monthly 
  title: 'SM Monthly',
  fontSize: 12,
  hAxis: {title: 'Date'},
  vAxis: {title: 'SM (mm)'},
  series: {0: {color: 'red'}}
};
print(ui.Chart.image.series(monthlySoil, studyArea, ee.Reducer.mean(), scale).setOptions(options1));

var options2 = { // Yearly 
  title: 'SM Yearly',
  fontSize: 12,
  hAxis: {title: 'Date'},
  vAxis: {title: 'SM (mm)'},
  series: {0: {color: 'blue'}}
};
print(ui.Chart.image.series(yearlySoil, studyArea, ee.Reducer.mean(), scale).setOptions(options2));

For the full code implementation, please visit this link.

Answer №1

One way to enhance the concept of filling in gaps with NAs is by introducing an empty band to each collection that aligns with the corresponding band in the other collection. Upon merging the collections, a chart can be generated displaying the combined data.

s2sr = s2sr.filterBounds(roi).filter(ee.Filter.calendarRange(2020, 2020, 'year'))
l8sr = l8sr.filterBounds(roi).filter(ee.Filter.calendarRange(2020, 2020, 'year'))

// Creating additional bands for each collection
var addS2Bands = function(image){
  var s2nd = image.normalizedDifference(['B4','B3']).rename('s2_nd')
  var l8nd = ee.Image().rename('l8_nd') // Adding an empty band for select() to work on all images
  return image.addBands(s2nd).addBands(l8nd)
}
var addL8Bands = function(image){
  var l8nd = image.normalizedDifference(['B4','B3']).rename('l8_nd')
  var s2nd = ee.Image().rename('s2_nd')
  return image.addBands(l8nd).addBands(s2nd)
}
l8sr = l8sr.map(addL8Bands)
s2sr = s2sr.map(addS2Bands)


// Merging the collections
var merged = l8sr.merge(s2sr).select(['l8_nd', 's2_nd'])

// Displaying the collection
var chart = ui.Chart.image.series({
  imageCollection: merged,
  region: roi,
  reducer: ee.Reducer.mean(),
  scale: 30
})
print(chart)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Why is receiving input value in React not successful?

Attempted to retrieve input value when user clicks search, but encountered difficulties. var Login = React.createClass({ getInitialState: function () { return {name: ''}; }, handleSearch(){ alert(this.state.name); // Why isn't ...

I am attempting to change a "+" symbol to a "-" symbol using a Bootstrap toggle feature

Click on the text to reveal more information that drops down below. I am using Bootstrap icons and attempting to show a "+" icon when the toggle is collapsed, and a "-" icon when it's open. I've been trying to use display properties, but haven&ap ...

Redefining irregular time series data with interpolation in R

In my quest for linear interpolation of time series data in R, I came across suggestions to utilize the na.approx() function from the zoo package. However, when working with irregular time series, I encountered issues where interpolated values were evenly ...

I encountered a problem with routing in my MERN project while trying to implement a feature I learned from a YouTube tutorial

My first question on stackoverflow. To summarize: I followed a YouTube video and downloaded the course code from the GitHub link provided, but I'm encountering routing issues despite reading similar questions on stackoverflow. I've been followi ...

Regular expression designed to admit only a maximum of two underscore characters, as well as no other special characters, with the condition that the character prior or

Looking for a specific format within a string, such as SOM_P9ERR96M27VP4_PL. The conditions are: must have exactly two underscores, not at the beginning or end of the string, and no other special characters like "&*$," following the underscore. Additiona ...

Django template experiences issue with AJAX functionality when attempting to open a new window through right-click action

I have successfully created a link using AJAX with the following HTML code: <a id="post_click" href="{{ post.online_url}}" rel="nofollow"> <button class="w-100 " type="button" name="button& ...

Get canvas picture through JS Jquery

I've been attempting to save a canvas image to my desktop using this code: <script type="text/javascript"> var canvas; $(document).ready(function() { if ($('#designs-wrapper').length) { $('.design').eac ...

Choose a cell from a separate column within a React application

Currently, I've been developing a puzzle game using React JS. My goal is to be able to choose one cell in each column, but I haven't been successful in achieving that yet. You can find the code sample here. Any assistance you can provide would be ...

Utilizing a Custom Hook for Updating Components in useEffect

I am facing an issue with the following code snippet: function checklogin(callback) { if (!state.user.authenticated) pushhistory("/accounts/login", function(){teamhome2_message();}); else callback(); } // TRYING TO CONVERT IT INTO ...

JavaScript - Matching overlapping time intervals

Struggling to develop a custom filter using Javascript, I aim to determine if two time ranges in millisecond getTime() format match. The first time range is retrieved from an object while the second comes from user input for filtering. Currently, my code c ...

Looking for the function to activate when the enter key is pressed

I have a search box which is a text type and has a click button that initiates the Find() function. How can I enable searching by pressing Enter inside the textbox? ...

Tips for successfully passing a component within a React Material-UI MenuItem

I included the Report.js component and successfully used it within a "button" element import Reports from 'new-components/Reports/Reports' //ontop <Button> <Reports pid={pid} /> //working </Button> However, ...

Shining a component (or persona) however essentially duplicate a distinct term

Is it possible to highlight an element or word, but still copy a different word when hitting ctrl+c? For example, imagine I have an emoji represented by: Original text: :heart: Output in HTML: <span background={...logic here}></span> I am ...

How can the color of the wishlist icon be modified in Reactjs when the item is available in the database?

Is there a way to change the color of the wishlist icon based on whether the item is in the database? If the item is present, its color should be brown, and if it's not present, the color should be black. Additionally, I want the ability to toggle be ...

Challenges in creating an alternative path in ExpressJS

I am currently working on a website for my studies. I decided to use nodejs/Express, as the technology is free. The first route /home was successful, but I am having trouble creating more routes. https://i.sstatic.net/6oseq.png Although I thought I had a ...

JavaScript challenge at an electronics store coding competition

Hello, I recently attempted a code challenge but unfortunately only passed 9 out of the 16 tests. I am seeking feedback on what may be going wrong in my code. The problem link can be found here: function getMoneySpent(keyboards, drives, budget) { l ...

When hovering over the background, it will enlarge but the text in front will remain the same size

As the user hovers over the image, the image enlarges. However, there is also some information that needs to be displayed in front of the image. This is my current implementation: .home-about-link { overflow: hidden; width: 100%; } .home-about { ...

Capture the output information and utilize it in a separate function

There are two functions in the code snippet below: 1: add-new-widget", function(). This piece of code is used for inserting JSON data and retrieving the last inserted ID from a table. In this code, the ID is obtained. alert(response['id']) ...

What purpose does generating a JSON file serve when invoking getStaticProps in Next.js?

Just diving into the world of Next.js. I've been going through the Next.js documentation and stumbled upon this: Next.js creates a JSON file that contains the outcome of executing getStaticProps. This JSON file is used in client-side routing via nex ...

Steps to generate a nested list with heading tag elements in the exact order as in the DOM structure

My HTML document is full of h1, h2, h3, h4 tags with nesting. Let's take a look at an example. <h2>About cars</h2> <p>Information about cats</p> <h2>About bikes</h2> <p>Information about bikes</p> ...