In d3.js. I can read in a user-uploaded CSV file in my web app like this:
d3.csv("upload.csv", function(data) {
console.log(data[0]);
});
This results in everything being read in as a string. However, I need to be able to treat numeric data types as numbers.
If I knew the property names ahead of time, I could do something like this:
d3.csv("upload.csv", function(data) {
data.forEach(function(d) {
d.population = +d.population;
d["land area"] = +d["land area"];
});
console.log(data[0]);
});
However, as this is user-provided data, there's no way to know the property names ahead of time. Is there a way to detect that the fields only contain numbers, then change the data type accordingly? Perhaps some sort of conditional statement with a regex test or something?
The examples were adapted from this tutorial.
New Answer:
D3 v5.8 introduced the very handy method d3.autotype
, which makes this task quite easy:
var data = d3.csvParse(d3.select("#csv").text(), d3.autoType);
console.log(data);
pre {
display: none;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<pre id="csv">header1,header2,header3
foo,foo2,1212
bar,bar2,2345
baz,baz2,7623</pre>
(Original Answer)
As discussed in the comments, you can use a regex to check if the string contains only digits. Then, if it does, you coerce it to a number.
In the following demo I'm using a <pre>
to store the data, since I cannot use the actual d3.csv
function in the Stack snippet.
In the simulated CSV there are three columns. One of them, header3
, has numbers. We know that, but the code doesn't: it just check all values using the regex and coerce the strings containing only digits to numbers.
var data = d3.csvParse(d3.select("#csv").text());
data.forEach(function(d) {
for (var key in d) {
if (/^\d+$/.test(d[key])) {
d[key] = +d[key]
}
}
});
console.log(data);
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<pre id="csv">header1,header2,header3
foo,foo2,1212
bar,bar2,2345
baz,baz2,7623</pre>
This addresses your question, which is "detect if a string contains only digits". However, if you want to deal with negative numbers, scientific notation and floats as well, you can drop the regex and use something way more elegant:
In JavaScript, NaN
is not equal to anything, not even to itself. Since using the unary operator with something that is not a number returns NaN
, you can simply do:
if (+d[key]===+d[key]) {
d[key] = +d[key]
}
Here is another demo, with negatives, floats and scientific notation:
var data = d3.csvParse(d3.select("#csv").text());
data.forEach(function(d) {
for (var key in d) {
if (+d[key]===+d[key]) {
d[key] = +d[key]
}
}
});
console.log(data);
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<pre id="csv">header1,header2,header3
foo,foo2,12.12
bar,bar2,-2345
baz,baz2,2.4e6</pre>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With