CSV to JSON using D3.JS - javascript

I have a csv file in the following format
type,1,2,3,4,5,6,7,8,.... // Upto 48
type1,54.69801915,84.4717406,81.87766667,66.48516667,...
type2,51.57399106,84.23170179,82.13950136,67.37540461,...
......
I wanna draw a line chart using this csv data with d3. Once I nest them using below code
d3.nest().key(function(d) {
return d.type;
}).entries(data);
My json looks as follow
{ key: "type1", values: […] }
and inside values it is just a single element array and the value of that is { 1: 54.69801915, 2: 84.4717406, 3: 81.87766667, … }
But my expectation is that that would be a array something similar to
{ { 1: 54.69801915}, {2: 84.4717406}, {3: 81.87766667}, … }
Can someone tell me what I am doing wrong here? Or how should I get my expected format?

Well, that's the expected behaviour of d3.nest().
If you want that structure you shared in your question, with values as an array of objects, I suggest you write your own nesting function.
Here is an example of code that does what you want, using map and for...in. It's neither elegant nor beautiful, it's purposely verbose to be easily understood (I'm using only a few columns and rows in your data):
var csv = `type,1,2,3,4
type1,54.69801915,84.4717406,81.87766667,66.48516667
type2,51.57399106,84.23170179,82.13950136,67.37540461`;
var data = d3.csvParse(csv);
var nested = data.map(function(d) {
var obj = {
key: d.type,
values: []
};
for (var prop in d) {
if (prop !== "type") {
obj.values.push({
[prop]: d[prop]
})
}
}
return obj;
});
console.log(nested)
<script src="https://d3js.org/d3.v5.min.js"></script>
Some additional comments:
What yo have in your question is not a JSON, that's just a simple JavaScript object.
What you call an array at the end of your question is neither an array nor an object, that's actually invalid.
Finally, don't use numbers for your property names.

Related

How to handle a nested json array to show in a table?

I have this JSON array. I am displaying data in a table. So, How should I put 'transactionData' inside the main object? i.e. I want the object as
{
completeTime: "value",
createTime: "value2",
assigneeName:"value3",
assigneeMap:"value4"
}
Since this is a JSON Array, so I need a way to iterate the array and make each of the objects as required.
I can't use the original JSON array since the object transactionData is not fixed and its keys might change. So, I don't want to hardcode any value like assigneeMap or assigneeName as it might change.
Hence, I want whatever the values in transactionData object are there, I want to insert it into my main object.
use the array.map(), something like this
results.map(x=>{
{
completeTime: x.completeTime,
createTime: x.createTime,
assigneeName: x.assigneeName || x.assigneename,
assigneeMap:x.assigneeMap || x.assigneeMap || x.yourChangedKey,
}
})
Use Array.prototype.map()
const result = arr.map(item => {
const { completeTime, createTime, data: { transactionData } } = item;
const { assigneeName, assigneeMap } = transactionData;
return {
completeTime,
createTime,
assigneeName,
assigneeMap
}
});

array.sort not working on array of objects

I got the following object array:
var arr = [{
2: {
1: { name: "test" },
2: { name: "apple" }
},
3: {
1: { name: "banana" },
2: { name: "pear" }
}
}];
Just some sample data. Now, I got 3 textareas:
<textarea id="first"></textarea>
<textarea id="second"></textarea>
<textarea id="third"></textarea>
And I have the following custom-made function:
function sort(alt)
{
arr.sort(function (a,b)
{
console.log(a);
if (a[2].name < a[2].name)
return (alt) ? 1 : -1;
if (a[2].name > a[2].name)
return (alt) ? -1 : 1;
return 0;
});
}
It should sort the array of objects by name, ascending or descending according to parameter. Now, I got 2 problems. This way I append all the values to the textareas:
for (var key in arr[0])
{
var obj = arr[0][key];
$(ID).append(obj[2].name + '\n');
}
The first time, that code will be executed without running sort. The second time, sort will be executed with false as parameter, than that code will be executed. The third time sort will be executed with true as parameter, than that code will be executed. However, the output of all textboxes is exactly the same.
This is a link to the jsfiddle:
http://jsfiddle.net/JoshB1997/gow4vzsc/
Also, the console.log(a) doesn't get printed in the console.
So variable arr is an array but as far as I can see it contains only one object.
You're trying to sort directly onto the array, since it only has one object it will simply never sort because there is nothing to sort.
You'll want to access arr[0] which is the object containing the actual objects you want to sort however the Object prototype doesn't contain any of the array functions so you cannot call sort on it even tho technically an Array is an Object an Array inherits from Object and not the other way around so the methods from Object are available to Array but not the other way around.
Also, you're trying to compare the same a[2].name with itself so it'll always be false since it's equal, not > or <.
In your case I extract all the name properties from every nested object you have like this (considering the usage of the original arr):
var compare = [];
var alt = false;
for (k in arr[0]) {
if (arr[0].hasOwnProperty(k)) {
for (l in arr[0][k])
if (arr[0][k].hasOwnProperty(l))
compare.push(arr[0][k][l].name);
compare.sort(function(a, b) {
if (a == b)
return 0;
else if (a < b)
return alt ? 1 : -1
else
return alt ? -1 : 1
});
Now you can use the compare array to output the sorted names correctly.
Also - your construction seems overly complex? It has objects and within them are nested objects but you're only sorting and displaying names, is there any reason this structure has to be maintained?
If not I would highly recommend you simplify this to just be an array of names, the loop I made above is far from beautiful and I'd rather have you not use it since it assumes that the outmost object is an object filled with other objects that all have the name property. This code could still break without an extra arr[0][k][l].hasOwnProperty('name').
Either way, the compare array simply contains all the names and it easily sortable with the default sort if you don't make things to complex for yourself.
I suggest you to use http://underscorejs.org/ that contains quite really useful function to transform from object to arrays.
For example in this case you can use something like http://underscorejs.org/#values
let values = _.values(arr[0]);
Now values is an array that contains your two object (2,3) in the form
values = [
{
1: {
name: "test"
},
2: {
name: "apple"
}
},
{
1: {
name: "banana"
},
2: {
name: "pear"
}
}
]
and here you can call your sort function
There is my demo on your code with underscore.js http://jsfiddle.net/gow4vzsc/3/
EDIT: If you cant/wont to include an entire library you can write your code for get the values:
values = [];
for(key in arr[0]){
values.push(arr[0][key]);
}
Here a demo without underscore.js http://jsfiddle.net/3L7ttu2r/1/

Split one JSON return into several objects

So, I've been looking at this for a couple hours and am out of ideas. My app is returning a single JSON object, and I need to parse the 4 data sets out of it and make 3 charts and a table. For the life of me I can't figure out how to "extract" each part. The JSON looks like:
{
"allele":{
"12426597":{
"??":4,
"CC":3,
"TT":4,
"CT":12
},
"878198":{
"??":4,
"AA":1,
"AC":15,
"CC":3
},
"6447271":{
"??":4,
"GG":14,
"AG":5
}
},
"haplo":{
"CT,AG,AC":3,
"TT,GG,AC":1,
"CC,GG,CC":1,
"TT,AG,CC":1,
"TT,GG,CC":1
},
"exercise":"p1"
}
I need to grab the data just for the three key's/IDs (12426597,878198, 6447271) and make one bar chart for each of those (requiring a data transformation <== see). Then I need to plug it into Highcharts...their API calling for an ordered arrays for the keys and values.
I thought about first making an array of the IDs:
var snpsObj = data.allele_frequency; // data returned from $.getJSON
var snpList = [];
for (prop in snpsObj) {
if (!snpsObj.hasOwnProperty(prop)) {
continue;
}
snpList.push(prop);
}
Which does get me the wanted array. And then accessing the "sub" keys like:
snpsObj.snpList[0];
...to return hopefully, something like:
{
"CC" : 23,
"CT" : 36,
"TT" : 12,
}
But that doesn't work at all. The most I could get was a return of something like:
allele_frequency : [object Object ]
I know there's something basic I'm just forgetting in my head-cold-fogged mind... Any suggestions?
Highcharts needs the keys and labels formatted in arrays, like:
categories: ['C', 'T']
data: [ 3, 9] // C=3, T=9
I think you want to access
snpsObj[ snpList[0] ]
by using bracket notation, snpsObj.snpList[0] would try to get the "snpList" property of your snpsObj object.
Btw, instead of your for-in-loop to create the array with property names, you might want to use Object.keys (even if you need to shim it to support old browsers).

Trouble Sorting JSON

I have a JSON object like the following:
{"Data": {
"290": {
...
}
"300": {
...
}
"281": {
...
}
}
}
How would I sort this JSON based on the top container keys (i.e. "290", "300", "281")?
Edit: So I used
$.getJSON('current/csf.txt', function(data) { arr = data["Data"]; }
And it sorted them based on the key. Why did this happen?
You've tagged this "JavaScript" so I assume you mean "A JavaScript object generated from this JSON".
In which case:
Loop over the property names (with a for in loop).
Use them to populate an array.
Sort the array.
Use the array as a map.
(You can't store ordered data in an object).
If you want to store the results in JSON, then you will need to change your data structure (and use an array (of objects)). Objects are explicitly unordered.
Your structure is wrong, it should be something like:
{
"Data": [
{
"id": "290"
},
{
"id": "300"
},
{
"id": "282"
}
]
}
Objects are for unordered data. Use arrays for ordered data. And the array is really easy to sort here:
obj.Data.sort(function(a,b){
return a.id - b.id;
});
You can convert to this structure like so:
function copyProps(dest, src) {
for (var key in src) {
dest[key] = src[key];
}
return dest;
}
var newData = [];
for (var key in obj.Data) {
newData.push(copyProps({
id: key
}, obj.Data[key]));
}
I agree with Amberlamps comment, you shouldn't be trying to sort the keys of an object, but if you wanted to for some reason you might take a look at underscore.js's sortBy method
Even if you COULD sort object attributes, there's no guarantee that you could read them back in sorted order. In Javascript, object attributes are not stored in a specific order; an object simply has attributes.
You cannot use array index notation to access object attributes, so the notion of sorting object attributes by key is moot.

Simplest way to convert a JSON object to a newly structured JSON object?

I've got a JSON object that is structured like this:
{
"xaxis": [
"foo",
"bar",
"baz"
],
"yaxis": [
333,
992,
1365
]
}
From it I'd like to create another JSON object stuctured like this:
{
"piegraph": [
["foo",333],
["bar",992],
["baz",1365]
]
}
Doing this conversion in client-side JavaScript would save me additional development and another server round-trip to fetch what is essentially the same data.
I can employ the jQuery library if that would help.
You could use Functional JavaScript:
second = { piegraph: Functional.zip([first.xaxis, first.yaxis]) };
Assuming that your first JSON string is already parsed to an object, you just have to iterate over the elements of any of the two arrays, to build the result:
var result = { piegraph: [] }; // initialize piegraph as an empty array
var l = obj.xaxis.length;
while(l--) {
result.piegraph[l] = [ obj.xaxis[l], obj.yaxis[l] ];
}
// result will look like this:
// {"piegraph":[["foo",333],["bar",992],["baz",1365]]}
No libraries needed, just a plain sequential loop. ;)
Why can't you just use a for loop something like?
for(var i = 0; xaxis.length; i++){
piegraph.push({xaxis[i], yaxis[i]);
}
This isn't hard to do manually, but the underscore.js functional library has a bunch of very handy functions, including .zip():
var piegraph = _.zip( obj.xaxis, obj.yaxis );
Looks like you want to do pair-wise matching (aka "zipping") of two arrays.
Assume array1 and array2 for x and y axes and resultArray i.e. "piegraph"
jQuery.map(array1, function(item, i){
resultArray.push(new Array(array[item, array2[i]));
}
});

Categories

Resources