1

I'm building an app using Bubble and I have the Toolbox plugin which enables me to use the "Run javascript" step in a Workflow.

From the following NASA API url, I'm planning to read and analyze 20 years of data with values for every month (240 values): https://power.larc.nasa.gov/api/temporal/monthly/point?parameters=ALLSKY_SFC_SW_DNI&community=RE&longitude=48.0000&latitude=27.0000&format=JSON&start=2001&end=2020

Below is what I am trying to accomplish (with missing pieces of code):

  1. Read in the json data from the API and parse it into an Javascript object.

    const response = await fetch(api_url);

    const data = await response.json();

  2. Loop through the objects values of interest. Inside the loop calculate the average values for each month. January, February, March, etc.

    for(const entry of Object.entries(data.properties.parameters.ALLSKY_SFC_SW_DNI)){}

  3. Store the above 12 average values to the Bubble database.

  4. Loop through the 12 average values to find the two months with highest and lowest value.

  5. Store the above High/low months values to the Bubble database. For example January as lowest average value.

I have successfully learned how to do some basic Javascript operations in Bubble. Reading single values from the API, display them on the page, and store them in the Bubble database. But, I do not know how to read the values in to an JS array, and make the necessary loops and comparisons.

I found this older question but it's about a txt file instead of json in my case. Get an array of values using fetch api javascript

Appreciate any advice and directions. Thanks

nik
  • 25
  • 1
  • 6
  • Hey nik, rambling questions with a lot of "_I want to..._" used throughout them don't usually go over well on StackOverflow. Try to rephrase your question by stating directly what you've tried and why it didn't work. Include some more code. You can even link other questions you think are similar and helpful but you don't understand. A [example] is always useful. – Randy Casburn Jan 02 '22 at 15:26
  • Good point @RandyCasburn. I have rephrased and hopefully made it more clear. – nik Jan 02 '22 at 17:34
  • couple clarifying questions: 1: the query produces 260 results rather than 240 2. why are there 13 values posted for each year? (that is the answer to #1 by the way). After you get the data from the API, the list of month's data can be seen by doing `console.log(data.properties.parameter.ALLSKY_SFC_SW_DNI);` – Randy Casburn Jan 02 '22 at 20:21
  • Thanks @RandyCasburn. I think I got one step further understanding how to loop over the values I'm interested in. (Updated my question). And to answer your questions: There is actually a 13'th value (yearly average I believe) for each year, which I do not need. – nik Jan 02 '22 at 20:37
  • change `const response = await fetch(api_url); const data = await response.json(); const parseData = JSON.parse(data);` to `const response = await fetch(api_url); const parseData = await response.json()` because response.json already parses the response as javascript object – The Bomb Squad Jan 02 '22 at 20:38
  • @TheBombSquad, Right. I have updated. – nik Jan 02 '22 at 20:47
  • @nik I just answered.. take a look :D – The Bomb Squad Jan 02 '22 at 21:06
  • 2 people have answered.. if any answer is correct, can you please mark? – The Bomb Squad Jan 10 '22 at 17:59

2 Answers2

0

Given what you showed me, I just fixed a couple lines and you say that you understand the bubble database end of whatever you're doing so here's how to get your data from the api, but as for the months.. something strange, apparently there are 13 data points per year ;-; strange

Nonetheless, I'd just have a list of 13 averages instead of 12 due to the data I'm getting

let api_url="https://power.larc.nasa.gov/api/temporal/monthly/point?parameters=ALLSKY_SFC_SW_DNI&community=RE&longitude=48.0000&latitude=27.0000&format=JSON&start=2001&end=2020"
var list={} //will store data points on each month "number"
let response = await fetch(api_url)
let parseData = await response.json()
let interest=parseData.properties.parameter.ALLSKY_SFC_SW_DNI
for(const entry of Object.entries(interest)){
  let [key,value]=entry //value is value xD
  key=key.substring(4,6) //key becomes month "number"
  list[key]=list[key]||{average:0,count:0}
  list[key].count++; list[key].average+=value
}
Object.entries(list).forEach(([_,month])=>{
  month.average/=month.count
})
console.log(list[12]) //sample of a month data
console.log(list) //full thing

Here's what it looks like enter image description here

The Bomb Squad
  • 4,192
  • 1
  • 9
  • 17
0

We know the data exists @ data.properties.parameter.ALLSKY_SFC_SW_DNI

The year and month are combined so the month must be extracted. Here is one simple way. (note I chose to remove the leading zero for a reason)

/* Given '202001' returns '1', given 202012' returns '12' */
function extractMonth(yearmonth){
  let month = yearmonth.substring(yearmonth.length-2);
  return month.startsWith('0')? month[month.length-1] : month;
}

If you store the data in a simple Array, the indexes can serve as the Month number. So index 1 will represent January. In order to do that the first element (index 0) will be set to null.

The reasons I took this approach is because the data structure is simple and it makes finding the lowest and highest values quite easy.

Now it is as easy as populating each Array element with the average value inside the loop. Each iteration of the loop updates the average for the month.

for(let [yearmonth, measurement] of Object.entries(data.properties.parameter.ALLSKY_SFC_SW_DNI)){
  const month = extractMonth(yearmonth);
  if(!tempsByMonth[month]) tempsByMonth[month] = 0;
  tempsByMonth[month] = (tempsByMonth[month] + measurement)/2;
}

It looks like this:

const data = {"type":"Feature","geometry":{"type":"Point","coordinates":[48.0,27.0,191.14]},"properties":{"parameter":{"ALLSKY_SFC_SW_DNI":{"200101":5.65,"200102":4.88,"200103":5.28,"200104":5.05,"200105":4.84,"200106":5.21,"200107":5.44,"200108":6.07,"200109":5.72,"200110":5.3,"200111":4.52,"200112":3.03,"200113":5.08,"200201":4.09,"200202":4.89,"200203":4.49,"200204":4.19,"200205":5.17,"200206":6.12,"200207":6.15,"200208":5.64,"200209":5.92,"200210":5.5,"200211":4.57,"200212":3.26,"200213":5.0,"200301":4.55,"200302":3.9,"200303":4.09,"200304":4.29,"200305":4.39,"200306":6.1,"200307":5.29,"200308":6.14,"200309":6.3,"200310":5.28,"200311":3.93,"200312":3.39,"200313":4.81,"200401":3.51,"200402":4.45,"200403":5.37,"200404":4.01,"200405":5.39,"200406":6.4,"200407":6.42,"200408":6.11,"200409":6.21,"200410":5.86,"200411":3.66,"200412":3.89,"200413":5.11,"200501":4.05,"200502":4.03,"200503":4.52,"200504":4.49,"200505":5.14,"200506":5.33,"200507":5.06,"200508":5.85,"200509":6.08,"200510":5.45,"200511":3.89,"200512":4.06,"200513":4.83,"200601":3.65,"200602":3.43,"200603":4.85,"200604":4.0,"200605":4.57,"200606":6.08,"200607":5.01,"200608":5.5,"200609":6.32,"200610":4.81,"200611":4.08,"200612":3.99,"200613":4.7,"200701":4.27,"200702":4.56,"200703":4.39,"200704":3.51,"200705":4.75,"200706":5.4,"200707":5.18,"200708":5.77,"200709":5.88,"200710":5.43,"200711":4.7,"200712":3.76,"200713":4.8,"200801":3.26,"200802":4.12,"200803":4.64,"200804":3.77,"200805":4.03,"200806":4.52,"200807":4.84,"200808":5.3,"200809":4.71,"200810":4.76,"200811":3.97,"200812":5.08,"200813":4.42,"200901":4.08,"200902":3.23,"200903":3.68,"200904":3.66,"200905":4.57,"200906":4.9,"200907":4.23,"200908":4.73,"200909":5.03,"200910":4.57,"200911":4.15,"200912":3.89,"200913":4.23,"201001":4.73,"201002":3.99,"201003":4.51,"201004":3.52,"201005":4.36,"201006":5.12,"201007":4.8,"201008":5.17,"201009":5.28,"201010":5.14,"201011":5.39,"201012":4.65,"201013":4.73,"201101":3.56,"201102":3.47,"201103":4.1,"201104":2.83,"201105":4.52,"201106":4.37,"201107":4.63,"201108":5.31,"201109":5.53,"201110":4.8,"201111":3.71,"201112":4.81,"201113":4.31,"201201":4.19,"201202":3.51,"201203":3.36,"201204":3.34,"201205":3.68,"201206":4.9,"201207":5.33,"201208":5.18,"201209":5.7,"201210":4.84,"201211":4.43,"201212":3.52,"201213":4.33,"201301":3.44,"201302":4.4,"201303":4.03,"201304":3.79,"201305":4.96,"201306":4.94,"201307":4.97,"201308":5.45,"201309":5.39,"201310":5.11,"201311":4.14,"201312":4.38,"201313":4.58,"201401":3.86,"201402":4.49,"201403":4.28,"201404":4.19,"201405":4.78,"201406":5.71,"201407":5.4,"201408":5.37,"201409":5.82,"201410":4.61,"201411":4.21,"201412":4.66,"201413":4.78,"201501":4.24,"201502":3.73,"201503":4.01,"201504":3.79,"201505":4.18,"201506":5.02,"201507":4.7,"201508":5.67,"201509":4.94,"201510":4.17,"201511":3.77,"201512":3.45,"201513":4.31,"201601":4.19,"201602":5.15,"201603":3.77,"201604":4.8,"201605":5.0,"201606":5.73,"201607":4.92,"201608":5.69,"201609":5.49,"201610":5.5,"201611":4.16,"201612":3.46,"201613":4.82,"201701":3.8,"201702":4.54,"201703":3.76,"201704":4.32,"201705":4.89,"201706":7.03,"201707":6.06,"201708":6.37,"201709":6.41,"201710":5.69,"201711":4.48,"201712":4.72,"201713":5.17,"201801":4.6,"201802":4.12,"201803":5.46,"201804":3.69,"201805":5.18,"201806":5.6,"201807":5.71,"201808":5.88,"201809":6.16,"201810":4.48,"201811":3.29,"201812":3.9,"201813":4.85,"201901":2.72,"201902":4.73,"201903":4.92,"201904":4.62,"201905":5.73,"201906":7.4,"201907":5.76,"201908":6.02,"201909":6.66,"201910":5.02,"201911":4.33,"201912":4.65,"201913":5.21,"202001":4.6,"202002":4.85,"202003":5.12,"202004":4.48,"202005":6.14,"202006":6.77,"202007":6.52,"202008":6.37,"202009":6.58,"202010":6.86,"202011":4.21,"202012":3.89,"202013":5.54}}},"header":{"title":"NASA/POWER CERES/MERRA2 Native Resolution Monthly and Annual","api":{"version":"v2.2.12","name":"POWER Monthly and Annual API"},"fill_value":-999.0,"start":"20010101","end":"20201231"},"messages":[],"parameters":{"ALLSKY_SFC_SW_DNI":{"units":"kW-hr/m^2/day","longname":"All Sky Surface Shortwave Downward Direct Normal Irradiance"}},"times":{"data":0.745,"process":0.02}};
const tempsByMonth = [null];

for(let [yearmonth, measurement] of Object.entries(data.properties.parameter.ALLSKY_SFC_SW_DNI)){
  const month = extractMonth(yearmonth);
  if(!tempsByMonth[month]) tempsByMonth[month] = 0;
  tempsByMonth[month] = (tempsByMonth[month] + measurement)/2;
}
function extractMonth(yearmonth){
  let month = yearmonth.substring(yearmonth.length-2);
  return month.startsWith('0')? month[month.length-1] : month;
}

console.log(tempsByMonth);

Finally, to find the lowest and highest average, you'll use Math.max and Math.min. Note that for the lowest average the null value was filtered out of the list:

console.log('Month with greatest value: ', tempsByMonth.indexOf(Math.max(...tempsByMonth)));
console.log('Month with lowest value: ', tempsByMonth.indexOf(Math.min(...tempsByMonth.filter(v=>v!==null))));

And here is the final result in action:

const data = {"type":"Feature","geometry":{"type":"Point","coordinates":[48.0,27.0,191.14]},"properties":{"parameter":{"ALLSKY_SFC_SW_DNI":{"200101":5.65,"200102":4.88,"200103":5.28,"200104":5.05,"200105":4.84,"200106":5.21,"200107":5.44,"200108":6.07,"200109":5.72,"200110":5.3,"200111":4.52,"200112":3.03,"200113":5.08,"200201":4.09,"200202":4.89,"200203":4.49,"200204":4.19,"200205":5.17,"200206":6.12,"200207":6.15,"200208":5.64,"200209":5.92,"200210":5.5,"200211":4.57,"200212":3.26,"200213":5.0,"200301":4.55,"200302":3.9,"200303":4.09,"200304":4.29,"200305":4.39,"200306":6.1,"200307":5.29,"200308":6.14,"200309":6.3,"200310":5.28,"200311":3.93,"200312":3.39,"200313":4.81,"200401":3.51,"200402":4.45,"200403":5.37,"200404":4.01,"200405":5.39,"200406":6.4,"200407":6.42,"200408":6.11,"200409":6.21,"200410":5.86,"200411":3.66,"200412":3.89,"200413":5.11,"200501":4.05,"200502":4.03,"200503":4.52,"200504":4.49,"200505":5.14,"200506":5.33,"200507":5.06,"200508":5.85,"200509":6.08,"200510":5.45,"200511":3.89,"200512":4.06,"200513":4.83,"200601":3.65,"200602":3.43,"200603":4.85,"200604":4.0,"200605":4.57,"200606":6.08,"200607":5.01,"200608":5.5,"200609":6.32,"200610":4.81,"200611":4.08,"200612":3.99,"200613":4.7,"200701":4.27,"200702":4.56,"200703":4.39,"200704":3.51,"200705":4.75,"200706":5.4,"200707":5.18,"200708":5.77,"200709":5.88,"200710":5.43,"200711":4.7,"200712":3.76,"200713":4.8,"200801":3.26,"200802":4.12,"200803":4.64,"200804":3.77,"200805":4.03,"200806":4.52,"200807":4.84,"200808":5.3,"200809":4.71,"200810":4.76,"200811":3.97,"200812":5.08,"200813":4.42,"200901":4.08,"200902":3.23,"200903":3.68,"200904":3.66,"200905":4.57,"200906":4.9,"200907":4.23,"200908":4.73,"200909":5.03,"200910":4.57,"200911":4.15,"200912":3.89,"200913":4.23,"201001":4.73,"201002":3.99,"201003":4.51,"201004":3.52,"201005":4.36,"201006":5.12,"201007":4.8,"201008":5.17,"201009":5.28,"201010":5.14,"201011":5.39,"201012":4.65,"201013":4.73,"201101":3.56,"201102":3.47,"201103":4.1,"201104":2.83,"201105":4.52,"201106":4.37,"201107":4.63,"201108":5.31,"201109":5.53,"201110":4.8,"201111":3.71,"201112":4.81,"201113":4.31,"201201":4.19,"201202":3.51,"201203":3.36,"201204":3.34,"201205":3.68,"201206":4.9,"201207":5.33,"201208":5.18,"201209":5.7,"201210":4.84,"201211":4.43,"201212":3.52,"201213":4.33,"201301":3.44,"201302":4.4,"201303":4.03,"201304":3.79,"201305":4.96,"201306":4.94,"201307":4.97,"201308":5.45,"201309":5.39,"201310":5.11,"201311":4.14,"201312":4.38,"201313":4.58,"201401":3.86,"201402":4.49,"201403":4.28,"201404":4.19,"201405":4.78,"201406":5.71,"201407":5.4,"201408":5.37,"201409":5.82,"201410":4.61,"201411":4.21,"201412":4.66,"201413":4.78,"201501":4.24,"201502":3.73,"201503":4.01,"201504":3.79,"201505":4.18,"201506":5.02,"201507":4.7,"201508":5.67,"201509":4.94,"201510":4.17,"201511":3.77,"201512":3.45,"201513":4.31,"201601":4.19,"201602":5.15,"201603":3.77,"201604":4.8,"201605":5.0,"201606":5.73,"201607":4.92,"201608":5.69,"201609":5.49,"201610":5.5,"201611":4.16,"201612":3.46,"201613":4.82,"201701":3.8,"201702":4.54,"201703":3.76,"201704":4.32,"201705":4.89,"201706":7.03,"201707":6.06,"201708":6.37,"201709":6.41,"201710":5.69,"201711":4.48,"201712":4.72,"201713":5.17,"201801":4.6,"201802":4.12,"201803":5.46,"201804":3.69,"201805":5.18,"201806":5.6,"201807":5.71,"201808":5.88,"201809":6.16,"201810":4.48,"201811":3.29,"201812":3.9,"201813":4.85,"201901":2.72,"201902":4.73,"201903":4.92,"201904":4.62,"201905":5.73,"201906":7.4,"201907":5.76,"201908":6.02,"201909":6.66,"201910":5.02,"201911":4.33,"201912":4.65,"201913":5.21,"202001":4.6,"202002":4.85,"202003":5.12,"202004":4.48,"202005":6.14,"202006":6.77,"202007":6.52,"202008":6.37,"202009":6.58,"202010":6.86,"202011":4.21,"202012":3.89,"202013":5.54}}},"header":{"title":"NASA/POWER CERES/MERRA2 Native Resolution Monthly and Annual","api":{"version":"v2.2.12","name":"POWER Monthly and Annual API"},"fill_value":-999.0,"start":"20010101","end":"20201231"},"messages":[],"parameters":{"ALLSKY_SFC_SW_DNI":{"units":"kW-hr/m^2/day","longname":"All Sky Surface Shortwave Downward Direct Normal Irradiance"}},"times":{"data":0.745,"process":0.02}};
const tempsByMonth = [null];

for(let [yearmonth, measurement] of Object.entries(data.properties.parameter.ALLSKY_SFC_SW_DNI)){
  const month = extractMonth(yearmonth);
  if(!tempsByMonth[month]) tempsByMonth[month] = 0;
  tempsByMonth[month] = (tempsByMonth[month] + measurement)/2;
}
function extractMonth(yearmonth){
  let month = yearmonth.substring(yearmonth.length-2);
  return month.startsWith('0')? month[month.length-1] : month;
}

console.log(tempsByMonth);
console.log('Month with greatest value: ',  tempsByMonth.indexOf(Math.max(...tempsByMonth)));
console.log('Month with lowest value: ',    tempsByMonth.indexOf(Math.min(...tempsByMonth.filter(v=>v!==null))));
Randy Casburn
  • 13,840
  • 1
  • 16
  • 31
  • This is awesome @RandyCasburn. Just what I needed. Now I'm getting "TypeError: response.json is not a function" when I try to run: const data = response.json(); – nik Jan 03 '22 at 12:01
  • I am using response.json() to parse the json format into a JS object before the looping. Is there an alternative for json() that does the same thing? – nik Jan 03 '22 at 12:06
  • Yes, I've answered your question about looping over the data and showed you how to get the highest and lowest values. I purposely did not use `fetch()` since that opens an entire quagmire of issues that are unrelated to this question. If you cannot get the data using `fetch()` please ask a different question on that topic. – Randy Casburn Jan 03 '22 at 15:29