Read csv to object of object for d3 [datamaps] - csv

I'm using datamaps and would like to be able to read the data from a csv file.
The data format that datamaps is expecting is the following:
var loadeddata = {
"JPN":{Rate:17.5,fillKey:"firstCat"},
"DNK":{Rate:16.6,fillKey:"secondCat"}
};
I would like to read a csv file of the following structure and transform it into the format that datamaps is expecting:
ISO, Rate, fillKey
JPN, 17.5, firstCat
DNK, 16.6, secondCat
My 'best attempt' was using the following code:
var csvloadeddata;
d3.csv("simpledata.csv", function (error, csv) {
if (error) return console.log("there was an error loading the csv: " + error);
console.log("there are " + csv.length + " elements in my csv set");
var nestFunction = d3.nest().key(function(d){return d.ISO;});
csvloadeddata = nestFunction.entries(
csv.map(function(d){
d.Rate = +d.Rate;
d.fillKey = d.fillKey;
return d;
})
);
console.log("there are " + csvloadeddata.length + " elements in my data");
});
But this code generates a variable 'csvloadeddata' that looks like this:
var csvloadeddata = [
{"key": "JPN", "values": { 0: {Rate:17.5, fillKey:"firstCat"}} },
{"key": "DNK", values : { 1: {Rate:16.6,fillKey:"secondCat"}} }
];
What am I doing wrong?

Found the answer myself. If somebody is interested – this is what I ended up using:
<script>
d3.csv("simpledata.csv", function(error, csvdata1) {
globalcsvdata1 = csvdata1;
for (var i=0;i<csvdata1.length;i++)
{
globalcsvdata1[ globalcsvdata1[i].ISO] = globalcsvdata1[i] ;
//console.log(globalcsvdata1[i]);
delete globalcsvdata1[i].ISO;
delete globalcsvdata1[i] ;
}
myMap.updateChoropleth(globalcsvdata1);
}
);
var myMap = new Datamap({
element: document.getElementById('map'),
scope: 'world',
geographyConfig: {
popupOnHover: true,
highlightOnHover: false
},
fills: {
'AA': '#1f77b4',
'BB': '#9467bd',
defaultFill: 'grey'
}
});
</script>
</body>
The csv has the following structure:
ISO,fillKey
RUS,AA
USA,BB
Here is a working example: http://www.explainingprogress.com/wp-content/uploads/datamaps/uploaded_gdpPerCapita2011_PWTrgdpe/gdpPerCapita2011_PWTrgdpe.html

Related

Accessing json returning undefined react js

I am trying to grab some json data to display in Ui but when I iterate over it using the map method I keep getting undefined.Any help will be really appreciated.Here is a link on code sandbox https://codesandbox.io/s/late-wood-kx8w2?file=/src/App.js
This line
const [items, setItem] = useState(Object.keys(trees));
is passing the tree keys to the View function and not the actual data. I believe that you meant to pass the data. Your code passes 'name' and 'children' as {items} that then gets displayed by View.js.
The following code shows you how you can parse the tree and get the names and the values. It's incomplete, but it should give you a start on how to do the traversal.
import React, { useState } from "react";
export default function Start(){
const trees = {
name: "root",
children: [
{
name: "child1",
children: [
{ name: "child1-child1", data: "c1-c1 Hello" },
{ name: "child1-child2", data: "c1-c2 JS" }
]
},
{ name: "child2", data: "c2 World" }
]
};
const treesCopy = trees;
function Traverse(tree){
var treesCopy = tree;
var str = [];
for (var prop in treesCopy) {
console.log(prop);
if (prop=="children"){
str = str + "name: "+ prop + ",";
treesCopy = treesCopy[prop][0];
// console.log('New tree: ',treesCopy);
return str + Traverse(treesCopy);
}
str = str + "name: "+ prop +" value: " + treesCopy[prop]+",";
}
return str;
};
const str = Traverse(treesCopy);
return(
<>
{
str ? str.split(",").map(place => <p> {place} </p>)
: ""
}
</>
)
}

How to append JSON data to existing JSON file node.js

How to append an existing JSON file with comma "," as separator
anchors = [ { "title":" 2.0 Wireless " } ]
fs.appendFileSync('testOutput.json', JSON.stringify(anchors));
This current code's output is like this
[
{
"title":" 2.0 Wireless "
}
]
[
{
"title":" Marshall Major II "
}
]
How to I get this in the correct format with comma "," as separator
I want to get something like this
[
{
"title":" 2.0 Wireless "
},
{
"title":" Marshall Major II "
}
]
Try this. Don't forget to define anchors array.
var data = fs.readFileSync('testOutput.json');
var json = JSON.parse(data);
json.push(...anchors);
fs.writeFile("testOutput.json", JSON.stringify(json))
I created two small functions to handle the data to append.
the first function will: read data and convert JSON-string to JSON-array
then we add the new data to the JSON-array
we convert JSON-array to JSON-string and write it to the file
example: you want to add data { "title":" 2.0 Wireless " } to file my_data.json on the same folder root. just call append_data (file_path , data ) ,
it will append data in the JSON file, if the file existed . or it will create the file and add the data to it.
data = { "title":" 2.0 Wireless " }
file_path = './my_data.json'
append_data (file_path , data )
the full code is here :
const fs = require('fs');
data = { "title":" 2.0 Wireless " }
file_path = './my_data.json'
append_data (file_path , data )
async function append_data (filename , data ) {
if (fs.existsSync(filename)) {
read_data = await readFile(filename)
if (read_data == false) {
console.log('not able to read file')
}
else {
read_data.push(data)
dataWrittenStatus = await writeFile(filename, read_data)
if dataWrittenStatus == true {
console.log('data added successfully')
}
else{
console.log('data adding failed')
}
}
else{
dataWrittenStatus = await writeFile(filename, [data])
if dataWrittenStatus == true {
console.log('data added successfully')
}
else{
console.log('data adding failed')
}
}
}
async function readFile (filePath) {
try {
const data = await fs.promises.readFile(filePath, 'utf8')
return JSON.parse(data)
}
catch(err) {
return false;
}
}
async function writeFile (filename ,writedata) {
try {
await fs.promises.writeFile(filename, JSON.stringify(writedata,null, 4), 'utf8');
return true
}
catch(err) {
return false
}
}

How to i display file from JSON object which contains an array?

Below is my json object which is returned. As you can see i have an array called "DocumentVersions" with a blob address of the file that i want to display. On the success function i want to display the image under a div. I tried looping through but i don't know how to display the image. I could have multiple files returned.
{
"FileUploadID":"27",
"DocumentVersions":[
{
"Active":true,
"DocumentVersionID":"5",
"FileName":"Logo0112.png",
"ContentLength":18846,
"ContentType":"image/png", "
"RevisionNumber":0,
"RevisionDate":"2017-08-01T12:24:04.7748026+01:00",
"Blob":"https://address/documents/75755df4af5f.png",
"BlobFileName":75755df4af5f.png"
}
],
"success":true,
"id":"27",
"message":"The Files have been uploaded"
}
Here is my success function. Where i get a 'Cannot read property 'Blob' of undefined'
myDiv.on("complete", function (data) {
res = JSON.parse(data.xhr.responseText);
console.log(res);
if (res.success == true) {
for (var key in res) {
var optionhtml = '<p="' + res[key].FileUploadID +
'">' + res[key].DocumentVersions.Blob + '</p>';
$(".test").append(optionhtml);
}
}
else {
alert(res.message);
}
});
As you can see, the DocumentVersions is not a object, it's a array with objects (only one object in this case).
{
"FileUploadID":"27",
"DocumentVersions":[
{
"Active":true,
"DocumentVersionID":"5",
"FileName":"Logo0112.png",
"ContentLength":18846,
"ContentType":"image/png", "
"RevisionNumber":0,
"RevisionDate":"2017-08-01T12:24:04.7748026+01:00",
"Blob":"https://address/documents/75755df4af5f.png",
"BlobFileName":75755df4af5f.png"
}
],
"success":true,
"id":"27",
"message":"The Files have been uploaded"
}
You need to specify the inner object in the array that you want to get data:
res[key].DocumentVersions[0].Blob
Thanks for your help, I solved my problem by using the following code this lets me get the image files and display.
res.DocumentVersions.forEach(function (obj) {
var img = new Image();
img.src = obj.Blob;
img.name = obj.FileName;
img.setAttribute("class", "fileLoad");
$("#fileupload").append(img);
});

Parsing doubly nested JSON object to MongoDB

Schema for my MongoDB model:
var resultsSchema = new mongoose.Schema({
start_date: String,
end_date: String,
matches:[{
id:Number,
match_date:String,
status:String,
timer:Number,
time:String,
hometeam_id:Number,
hometeam_name:String,
hometeam_score:Number,
awayteam_id:Number,
awayteam_name:String,
awayteam_score:Number,
ht_score:String,
ft_score:String,
et_score:String,
match_events:[{
id:Number,
type:String,
minute:Number,
team:String,
player_name:String,
player_id:Number,
result:String
}]
}]
});
Example of JSON data coming from the server:
"matches":
[
{
"match_id":"1234"
"match_date":"Aug 30"
...
...
"match_events":
[
{
"event_id":"234",
"event_minute":"38",
...,
...
},
{
"event_id":"2334",
"event_minute":"40",
...,
...
}
],
{
"match_id":"454222"
"match_date":"Aug 3"
...
...
"match_events":
[
{
"event_id":"234",
"event_minute":"38",
...,
...
},
....
My current implementation works for parsing just the matches (i.e the first array). But I can't seem to access the inner array properly.
async.waterfall([
function(callback) {
request.get('http://football-api.com/api/?Action=fixtures&APIKey=' + apiKey + '&comp_id=' + compId +
'&&from_date=' + lastWeek_string + '&&to_date=' + today_string, function(error, response, body) {
if (error) return next(error);
var parsedJSON = JSON.parse(body);
var matches = parsedJSON.matches;
var events = parsedJSON.matches.match_events;
var results = new Results({
start_date: lastWeek_string,
end_date: today_string,
matches:[]
});
_.each(matches, function(match) {
results.matches.push({
id: match.match_id,
match_date: match.match_formatted_date,
status:match.match_status,
timer:match.match_timer,
hometeam_id:match.match_localteam_id,
hometeam_name:match.match_localteam_name,
hometeam_score:match.match_localteam_score,
awayteam_id:match.match_visitorteam_id,
awayteam_name:match.match_visitorteam_name,
awayteam_score:match.match_visitorteam_score,
ht_score:match.match_ht_score,
ft_score:match.match_ft_score,
et_score:match.match_et_score,
match_events:[]
});
});
_.each(events, function(event) {
results.matches.match_events.push({
id:event.event_id,
type:event.event_type,
minute:event.event_minute,
team:event.event_team,
player_name:event.event_player,
player_id:event.event_player_id,
result:event.event_result
});
});
I understand that the second _.each loop should be iterating for every match, since very match has it's own events subarray. I'm just not sure how to structure this and have been struggling with it for a while.
I tried nesting that loop inside the _.each(matches, function(match) { loop but that didn't work.
Thank you.
Edit: How could I get this to work?
var results = new Results({
start_date: lastWeek_string,
end_date: today_string,
matches:[
match_events: []
]
});
Because then as #zangw says I could construct the match_events array first, append it to matches, and so on.

d3 - reading JSON data instead of CSV file

I'm trying to read data into my calendar visualisation using JSON. At
the moment it works great using a CSV file:
d3.csv("RSAtest.csv", function(csv) {
var data = d3.nest()
.key(function(d) { return d.date; })
.rollup(function(d) { return d[0].total; })
.map(csv);
rect.filter(function(d) { return d in data; })
.attr("class", function(d) { return "day q" + color(data[d]) +
"-9"; })
.select("title")
.text(function(d) { return d + ": " + data[d]; });
});
It reads the following CSV data:
date,total
2000-01-01,11
2000-01-02,13
.
.
.etc
Any pointers on how I can read the following JSON data instead:
{"2000-01-01":19,"2000-01-02":11......etc}
I tried the following but it not working for me (datareadCal.php spits
out the JSON for me):
d3.json("datareadCal.php", function(json) {
var data = d3.nest()
.key(function(d) { return d.Key; })
.rollup(function(d) { return d[0].Value; })
.map(json);
thanks
You can use d3.entries() to turn an object literal into an array of key/value pairs:
var countsByDate = {'2000-01-01': 10, ...};
var dateCounts = d3.entries(countsByDate);
console.log(JSON.stringify(dateCounts[0])); // {"key": "2000-01-01", "value": 10}
One thing you'll notice, though, is that the resulting array isn't properly sorted. You can sort them by key ascending like so:
dateCounts = dateCounts.sort(function(a, b) {
return d3.ascending(a.key, b.key);
});
Turn your .json file into a .js file that is included in your html file. Inside your .js file have:
var countsByDate = {'2000-01-01':10,...};
Then you can reference countsByDate....no need to read from a file per se.
And you can read it with:
var data = d3.nest()
.key(function(d) { return d.Key; })
.entries(json);
As an aside....d3.js says it's better to set your json up as:
var countsByDate = [
{Date: '2000-01-01', Total: '10'},
{Date: '2000-01-02', Total: '11'},
];