Christopher Worley
Christopher Worley

Reputation: 77

Calculate max from array with some non-numeric values

I would like to calculate the maximum value for 15-minute data I'm importing from a .csv file. Each row in the file contains the 15-min data from a different source ("ID") from a different day ("Date"), but there are additional columns that are not needed ("Class", "Sample", "Channel") for my analysis.

I looked at using d3.group, but it doesn't seem like having five key values (one for each of the non-numeric values) is the right way to go about it.

Importing the data looks like this:

[
  {
    "ID": "10D1012B",
    "Class": "R",
    "Sample": "135_OLD",
    "Channel": "1",
    "Date": "1/1/2019",
    "00:15": "0.48",
    "00:30": "0.6",
    "00:45": "0.896",
    "01:00": "0.712",
    "01:15": "1.12",
          ...
    "23:00": "0.48",
    "23:15": "0.6",
    "23:30": "0.624",
    "23:45": "0.552",
    "00:00": "0.704"
  },
  {
    "ID": "10D1040B",
    "Class": "R",
    "Sample": "135_OLD",
    "Channel": "1",
    "Date": "1/2/2019",
    "00:15": "1.016",
         ...
    "23:30": "0.632",
    "23:45": "0.72",
    "00:00": "0.776"
  }
]

I would like to calculate the maximum value for each row of data (ID,Date pair) so I can use that to create the chart scale. It's not clear to me how to exclude the non-numeric columns when calculating the maximum.

Upvotes: 4

Views: 441

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102198

You have two problems: first, d3.max traverse different objects in the same array... however, you need to traverse different values in the same object. Second, you have some numerical values, like for the "Channel" property, that you also don't want to include. So, the thing is not as simple as just finding all the numerical values in the properties.

That being said, here's my suggestion: set a list of property names, or keys, that you don't want to check...

const nonNeededKeys = ["ID", "Class", "Sample", "Channel", "Date"];

... and then use d3.max for all other keys in each object inside the array:

data.forEach(function(row) {
  const keys = d3.keys(row).filter(function(d) {
    return nonNeededKeys.indexOf(d) === -1;
  });
  row.maxValue = d3.max(keys.map(function(d) {
    return +row[d]
  }))
});

Here, as you can see, for each object, I'm creating a new property named maxValue.

Here is the demo:

const data = [{
    "ID": "10D1012B",
    "Class": "R",
    "Sample": "135_OLD",
    "Channel": "1",
    "Date": "1/1/2019",
    "00:15": "0.48",
    "00:30": "0.6",
    "00:45": "0.896",
    "01:00": "0.712",
    "01:15": "1.12",
    "23:00": "0.48",
    "23:15": "0.6",
    "23:30": "0.624",
    "23:45": "0.552",
    "00:00": "0.704"
  },
  {
    "ID": "10D1040B",
    "Class": "R",
    "Sample": "135_OLD",
    "Channel": "1",
    "Date": "1/2/2019",
    "00:15": "1.016",
    "23:30": "0.632",
    "23:45": "0.72",
    "00:00": "0.776"
  }
];

const nonNeededKeys = ["ID", "Class", "Sample", "Channel", "Date"];

data.forEach(function(row) {
  const keys = d3.keys(row).filter(function(d) {
    return nonNeededKeys.indexOf(d) === -1;
  });
  row.maxValue = d3.max(keys.map(function(d) {
    return +row[d]
  }))
});

console.log(data)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

After that, calculating the maximum value for all objects is very easy:

const maxValue = d3.max(data, function(d) {
    return d.maxValue;
});

And the running snippet:

const data = [{
    "ID": "10D1012B",
    "Class": "R",
    "Sample": "135_OLD",
    "Channel": "1",
    "Date": "1/1/2019",
    "00:15": "0.48",
    "00:30": "0.6",
    "00:45": "0.896",
    "01:00": "0.712",
    "01:15": "1.12",
    "23:00": "0.48",
    "23:15": "0.6",
    "23:30": "0.624",
    "23:45": "0.552",
    "00:00": "0.704"
  },
  {
    "ID": "10D1040B",
    "Class": "R",
    "Sample": "135_OLD",
    "Channel": "1",
    "Date": "1/2/2019",
    "00:15": "1.016",
    "23:30": "0.632",
    "23:45": "0.72",
    "00:00": "0.776"
  }
];

const nonNeededKeys = ["ID", "Class", "Sample", "Channel", "Date"];

data.forEach(function(row) {
  const keys = d3.keys(row).filter(function(d) {
    return nonNeededKeys.indexOf(d) === -1;
  });
  row.maxValue = d3.max(keys.map(function(d) {
    return +row[d]
  }))
});

const maxValue = d3.max(data, function(d) {
  return d.maxValue
})
console.log(maxValue)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

Upvotes: 1

Related Questions