d3.js graphing sub arrays from JSON - arrays

So I am attempting to draw a simple line graph. The path to the arrays are fairly long, It seems the forEach function is not looping through the array? Am I missing a function to successfully create d.date which comes out as 'null' and d.air which comes out as 'NaN'?
data[0].STATION[0].OBSERVATIONS.date_time, and data[0].STATION[0].OBSERVATIONS.air_temp_set_1 are the arrays I want to plot
Here it is on blockbuilder:
http://blockbuilder.org/TMoore24/b9906fd3893034b91f13e0c86acb2f75
Many thanks!

There are two things going on here.
(1):
data.forEach(function(d) {
d.date = format(data[0].STATION[0].OBSERVATIONS.date_time);
d.air = +data[0].STATION[0].OBSERVATIONS.air_temp_set_1;
});
These don't work because both data[0].STATION[0].OBSERVATIONS.date_time, and data[0].STATION[0].OBSERVATIONS.air_temp_set_1 are arrays.
What you probably want is this.
var obs = data[0].STATION[0].OBSERVATIONS;
var dates = obs.date_time.map(format);
var air = obs.air_temp_set_1.map(function(d){ return +d; });
data.date = dates;
data.air = air;
What this leaves you with is an array of dates and and array of air temps.
Unfortunately, this leads to issue #2.
(2)
var line = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.air); });
This function assumes that each object, d, takes the form {date: SINGLE_DATE_VALUE, air: SINGLE_NUMERIC_VALUE, etc} but what you actually have is data = {date:[ARRAY_OF_DATES, air: ARRAY_OF_TEMPERATURES, etc...}
To use the line function above, then you need to create an array of objects of the form {date: DATE_VALUE, air: AIR_TEMPERATURE_VALUE}. There are various ways you can do that depending on how you want your final data structured. Here's one way:
data.airTempByDate = data.date.map(function(d, i){
return {
date: d,
air: air[i]
};
});
Hope this makes sense! Here's a working block on blockbuilder with the fixes above.

Related

Is there a way to filter an array for strings in google apps script?

I am trying to filter the array 'employee_name' consisting of NaNs and one string element, to exclude any element BUT the string. The context is that I have a spreadsheet containing employee's birth dates, and I'm sending an email notification in case there's a birthday two days from today. My variables look like this:
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Employees');
var range = ss.getRange(2, 1, ss.getLastRow()-1, 1); // column containing the birth dates
var birthdates = range.getValues(); // get the `values` of birth date column
var today = new Date ();
var today = new Date(today.getTime());
var secondDate = new Date(today.getTime() + 48 * 60 * 60 * 1000);
var employee_name = new Array(birthdates.length-1);
And the loop:
for (var i=0;i<=birthdates.length-1;i=i+1){
var fDate = new Date(birthdates[i][0]);
if (fDate.getDate() == secondDate.getDate() &&
fDate.getMonth() == secondDate.getMonth()){
//define variables for outgoing email
for (var j=0; j<=birthdates.length-1;j=j+1){
employee_name[j] = [NaN];
}
employee_name[i] = ss.getRange(i+2,6);
employee_name[i] = employee_name[i].getValues();
}
}
after which the array in question looks like this
Logger.log(employee_name);
[[[Mia-Angelica]], [NaN], [NaN], [NaN], ..., [NaN]]
I have already tried the filter(Boolean), but this isn't working:
employee_name_filtered = employee_name.filter(Boolean);
Logger.log(employee_name_filtered);
returns [[[Mia-Angelica]], [NaN], [NaN], [NaN], ..., [NaN]].
I have also tried filling the non-string array entries with numeric values (instead of NaN) and then apply
employee_name_filtered = employee_name.filter(isFinite);
Logger.log(employee_name_filtered);
returns [[1.0], [2.0], [3.0], ..., [72.0]], so this filter method is working, but then I would need the 'inverse' of that because I want to keep the string.
I need the array within array to store the values at the position of the counter variable where the condition's met (similar to How to store data in Array using For loop in Google apps script - pass array by value).
This is my first time posting a question on SO, so if I overlooked any 'rules' about posting, just let me know and I will provide additional info.
Any help will be appreciated!
EDIT:
what I would like to receive in the end is simply
[[Mia-Angelica]].
The array you are using a 2 dimensional array - meaning it's an array of arrays so the filter method you are using cannot be applied in the same manner.
For this, I suggest you try the below snippet.
function cleanArray() {
var initialArray = [
['Mia-Angelica'],
['Space'],
['2'],
[NaN],
[NaN],
[NaN],
[NaN]
];
var finalArray = [];
for (let i = 0; i < initialArray.length; i++) {
var midArray = initialArray[i].filter(item => (Number.isFinite(item) && item.id !== 0) || !Object.is(item, NaN));
finalArray.push(midArray);
}
console.log(finalArray.filter(item => item != ''));
}
Note
Please bear in mind that getValues will return an Object[][] which is a two-dimensional array of values.
Reference
Apps Script Range Class;
Array.prototype.filter().

Iterate over ee.FeatureCollection to compute regional statistics of an ee.ImageCollection

Dear Earth Engine community,
Can someone help me solving the following problem:
I want to compute the aggregate nightlight intensities (sum) within all first level administrative regions of the world. For that purpose I use a shapefile which contains the regional boundaries (GADM) and raster data on nightlight (VIIRS).
The issue with the following code is that 1) I am getting an error that say "Unknown element type provided: object. Expected: ee.Image, ee.ImageCollection, ee.FeatureCollection or ee.Element." for the nighttime.reduceRegion operation and 2) that only the last feature of the selection is returned on print(final).
Unfortunately I do not manage to solve these problems. It would be great if someone could help me improving the code. I am sure there are many issues since Javascript and the Earth Engine API are completely new to me..
Thanks a lot in advance!
// Import nighttime raster data.
var nighttimeCollection = ee.ImageCollection('NOAA/VIIRS/DNB/MONTHLY_V1/VCMSLCFG');
// Import shapefile containing region boundaries.
var region_boundaries = ee.FeatureCollection("users/hendrikscheewel/gadm_level_1");
// Select a specific year ::: Later this should be done within a loop.
var year = "2014";
// Aggregate monthly nighttime data to year x.
var nighttime = nighttimeCollection
.filter(ee.Filter.date(year+'-01-01', year+'-12-31'))
.select('avg_rad')
.reduce(ee.Reducer.mean());
// This function does the following:
// * Aggregrate nightlight data within a shape/feature by taking its sum,
// * Assign the result to the feature,
// * Create copy of feature with simplified geometry (centroid) and fewer columns,
// * Return the copy.
var compute_nightlight = function(feature) {
// Compute mean of average radiance for feature shape
var result = nighttime.reduceRegion({
geometry: feature.geometry(),
reducer: ee.Reducer.sum(),
scale: 30,
maxPixels: 1e9,
});
// Set "nightlight" as a new property.
feature = ee.Feature(feature.set('nightlight',result.get('avg_rad_mean')));
// Get the centroid of the feature's geometry.
var featureSimplified = feature.centroid();
// Keep this list of properties.
var keepProperties = ['GID_0','GID_1','NAME_0','NAME_1','nightlight'];
featureSimplified = featureSimplified.copyProperties(feature, keepProperties);
// Return a new Feature, copying properties from the old Feature.
return featureSimplified;
};
//print(compute_nightlight(region_boundaries.first()));
var final = region_boundaries.filter(ee.Filter.eq('NAME_0','Belgium')).iterate(compute_nightlight);
print(final)
Export.table.toDrive({
collection: final,
description: 'nl_'+year,
fileFormat: 'CSV'
});
Ok, I found my main mistake: Instead of using the .iterate() method I should have used the .map() method.
After some cleaning the code looks like this:
// Select a specific year
var year = "2014";
// Aggregate monthly nighttime data to year x.
var nighttime = nighttimeCollection
.filter(ee.Filter.date(year+'-01-01', year+'-12-31'))
.select('avg_rad')
.reduce(ee.Reducer.mean());
// This function does the following:
// * Aggregrate nightlight data within a shape/feature by taking its sum,
// * Assign the result to the feature,
// * Create copy of feature with simplified geometry (centroid) and fewer columns,
// * Return the copy.
var compute_nightlight = function(feature) {
// Compute mean of average radiance for feature shape
var result = nighttime.reduceRegion({
geometry: feature.geometry(),
reducer: ee.Reducer.sum(),
scale: 30,
maxPixels: 1e9,
});
// Set "nightlight" as a new property.
feature = ee.Feature(feature.set('nightlight',result.get('avg_rad_mean')));
// Return a new Feature, copying properties from the old Feature.
return feature.centroid();
};
var final = ee.FeatureCollection((region_boundaries).map(compute_nightlight));
Export.table.toDrive({
collection: final,
description: 'nl_'+year,
fileFormat: 'CSV'
});

Google Earth Engine: set Feature to FeatureCollection, but not a whole Array

I try to add a new Feature to the large Feature Collection, but with a function set() its override the whole list to each feature. But my purpose is to add each value from the array to the corresponding FeatureCollection. Can anybody help me?
var table = ee.FeatureCollection(ft:.....blablabla);
**//Create an Array from the property DN in the FeatureCollection:**
var propert = table.limit(100).aggregate_array('DN');
*// Values less than 1 will be set to 1, larger than 1== 0:*
var limit = ee.Array(propert).lt(1);
print(limit);
//Function, that add the list! of features (limit) to new property (Class) in the FeatureCollection ("table").
var addFeature = function(ar) {
return ar.set({Class: limit});
//Map throw the Featurecollection table
var areaAdded = table.limit(100).map(addArea);
};
So, if you can see, my code add the whole Array [limit] to each property in the FeatureCollection, not a first Value from the Array to the first property and so on...
Could anybody help me? thank you
If you have a smallish number of features, you can convert the feature collection to a list, convert the array to a list, zip() them together, map a function over the lists to set the property. Toy example:
var features = [
ee.Feature(ee.Geometry.Rectangle(30.01, 59.80, 30.59, 60.15), {name: 'Voronoi'}),
ee.Feature(ee.Geometry.Point(-73.96, 40.781), {name: 'Thiessen'}),
ee.Feature(ee.Geometry.Point(6.4806, 50.8012), {name: 'Dirichlet'})
];
var fromList = ee.FeatureCollection(features);
var array = ee.Array([2, 3, 5]);
var lists = fromList.toList(fromList.size()).zip(array.toList());
var features = ee.FeatureCollection(lists.map(function(l) {
return ee.Feature(ee.List(l).get(0)).set('foo', ee.List(l).get(1));
}));
print(features);

getting data from an object's array with vue.js

I am trying to access the following data in Vue.js
{"id":1,"name":"Westbrook","created_at":"2017-06-10T16:03:07.336Z","updated_at":"2017-06-10T16:03:07.336Z","stats":[{"id":1,"player_id":1,"points":2558,"assists":840,"rebounds":864,"created_at":"2017-06-10T16:03:07.373Z","updated_at":"2017-06-10T16:03:07.373Z"}]}
self.player = response.name works. now i need self.point
methods: {
fetchData: function() {
var self = this;
$.get("api/v1/players/1", function(response) {
console.log(response);
self.player = response.name;
self.point = response.stats.points
});
}
}
I have thus far tried response.stats["points"], response.stats[2], response.stats[ { points } ], response.stats[points]
The stats property in your json holds an array in which the first object has a property named points
So use response.stats[0].points
Keep in mind though that the stats is probably an array for a reason. It might hold more than one objects in the future, so always using the first element [0] might not be a valid approach.
I think it can help you
var json = JSON.parse(data);
json.stats[0].points
response = {"id":1,"name":"Westbrook","created_at":"2017-06-10T16:03:07.336Z","updated_at":"2017-06-10T16:03:07.336Z","stats":[{"id":1,"player_id":1,"points":2558,"assists":840,"rebounds":864,"created_at":"2017-06-10T16:03:07.373Z","updated_at":"2017-06-10T16:03:07.373Z"}]}
If you want to access the name
console.log(response.name) // Westbrook
If you want to access the stats data which contain list, simply target
let stats=response.stats[0] //By getting the first index in the list
Get the points in stats
console.log(stats.points) // 2588

KnockoutJS Accessing an array of objects in a separate class

So i have 2 classes, users and health readings. i made a array of user objects with an array of readings inside it.i just want access to the date and weight in the reading array, i have been trying for a long time to figure this out! please help this simple problem is driving me nuts!
// Class to represent a row in the seat reservations grid
function Reading(theDate,theWeight)
{
self.theDate=ko.observable(theDate);
self.theWeight=ko.observable(theWeight);
}
function User(name,weight,date) {
var self = this;
self.name = name;
self.date = date;
self.weight = ko.observable(weight);
self.theReadings = ko.observableArray([
new Reading(12,13)
]);
}
// Editable data
self.users = ko.observableArray([
new User("George",1,2012),
new User("Bindu",2,2012)
]);
/this alerts an object but i dont know how to access the weight/date variable
alert(self.users()[0].theReadings()[0]);
self.readings = ko.observableArray([
new Reading(12,13)
Just missed a few things on this one.
Here ya go.
http://jsfiddle.net/EN7y4/3/
Namely. You had "self.theWeight" in function Reading instead of "this."...
Happy Coding!
alert(self.users()[0].theReadings()[0].theWeight();
I would recommend removing the 'thes'. That's an uncommon style.

Resources