1

I have a meteorite landings dataset.
I nested the data in four keys, by type:

  var dataByType = d3.nest()
    .key(function(d) {
          return d.rectype;
    })
    .entries(dataset); // the original array

This is the resulting structure: data

enter image description here

Now I want to create new arrays, filtering the nested one: I want each filtered array to contain only the objects whose "mass" property is inside a defined range.
So I tried this:

// filter small meteorites
var lightWeight = dataByType.forEach(function(d){
      d.values.filter(function (object) {
            var mass = object.mass;
            return mass <= 100;
      });
  });

But it returns undefined.

Nesting is giving me a lot of trouble! What do I do wrong?
Thanks in advance

5
  • Try to use map instead of forEach and return d. Like var lightWeight = dataByType.map(function(d){ d.values.filter(function (object) { var mass = object.mass; return mass <= 100; }); return d; }); Commented Sep 11, 2017 at 21:43
  • Please post your data as text not an image. Commented Sep 11, 2017 at 22:01
  • Your d.values is an array so....d.values[1].filter? Commented Sep 11, 2017 at 22:05
  • @ben I tried forEach(function(d, i){ d.values[i].filter(...) but it returns an error saying "d.values[i].filter is not a function" Commented Sep 12, 2017 at 16:53
  • @chsdk I'm sorry, I'm a newbie and can't figure out how to do that from the Firefox console Commented Sep 12, 2017 at 16:55

4 Answers 4

3

I think you're overwriting lightWeight on each pass of that forEach. Instead try creating lightWeight as its own object, then adding the keys you want in the loop:

const lightWeight = {};

dataByType.forEach(function(d){
  lightWeight[d.key] = d.values.filter(function (object) {
    var mass = object.mass;
    return mass <= 100;
  });
});

Working pen which (I think?) is doing what you want: https://codepen.io/benjaminwfox/pen/veBjrP?editors=0012

Sign up to request clarification or add additional context in comments.

4 Comments

Many thanks, this does exactly what I need! So my mistake was not assigning the results to keys, inside the loop.. But then, why did I get undefined instead of an array with only the last result? Is it important to declare lightWeight as const instead of var?
const vs var is syntactic difference between two versions of JavaScript (ES6 vs ES5). That's not actually relevant to the solution, it's just the syntax I've been using lately. I'll see if I can get an explanation for why it ended up undefined.
So the reason you were getting undefined is because you were trying to assign the return value of a forEach loop which, be design, returns undefined. See the MDN page: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…, and more info on the SO question: stackoverflow.com/questions/34653612/… Your .filter() function only returned the value of mass inside the scope of the forEach loop.
Thankyou very much for your patience!
0

I couldn't speak for what your dataset looks like, but could it just be that you're not returning lightWeight at the end?

Comments

0

I am unsure what you are trying to filter on exactly, but try to use map instead of forEach and you need to return d in the iterators, anon function.

Like the following:

var lightWeight = dataByType.map(function(d) {
    d.filteredValues = d.values.filter(function (object) {
        return object.mass <= 100;
    });
    return d;
});

4 Comments

Actually filter() method will return a new array and does not change the array in-place, so this code won't be helpful.
What if you stored it in another key within the object, like filteredValues?
This will affect the initial array structure, but any way if you wanted so you could just do d.values = d.values.filter(...).
@StanleyLiu Yes this works, but changes the original array. In the end, though, I only need to group the data by 5 intervals of mass value, and this might do. I just hope it won't make accessing the data more difficult later. I'll try! Thanks
0

Assuming that you got the data in the format you shared, where for each item of data you have a key property and a values array.

If you want to filter the values array by the mass property of each entry, you will need to use a combination of .map() and .filter() methods.

This is how should be your code:

var lightWeight = data.map(function(d){
    var obj = {};
    obj.key = d.key;
    obj.values = d.values.filter(function (object) {
            return object.mass <= 100;
    });
    return obj;
});

This will give you the expected results.

2 Comments

I tried this, but still got an error saying "d.values is undefined"
@Léonie normally this will work perfectly, can you please show us a Demo where you got this error, what data have you used?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.