I am new to D3 and need to design a heatmap using D3. I had the data for 20 years and required to show the max and min for every month. The question is different month has different days and for February there is 28 days or 29 days. Can anybody help me?
Sorry for my unclear description.This is the part of the data.enter image description here I need to use the max and min value of each month to draw a heatmap. The data is from 1997-01-01 to 2007-12-31.
You can sort this out using underscorejs and d3.extent.
For Example your list is like,
data = [{
month: 1,
value: 10
}, {
month: 1,
value: 20
}, {
month: 2,
value: 30
}, {
month: 2,
value: 40
}];
You underscore groupBy method like,
result = _.groupBy(data, 'month');
Your result will be,
result = {
1: [{
month: 1,
value: 10
}, {
month: 1,
value: 20
}],
2: [{
month: 2,
value: 30
}, {
month: 2,
value: 40
}]
};
Then you can plot max and min values using d3.extent.
Related
I have a dataset with date format as
var dataset = [{
"monthDate": "2018-05",
"count": 83
},
{
"monthDate": "2018-06",
"count": 23
},.....]
I wish to change this to 'May-18', 'June-18' and so on and pass this data to Highchart Categories. How do I do that?
You could parse the date into a Date object, and then format it with toLocaleDateString. One adjustment is needed at the end, to get the hyphen in the output:
var dataset = [{ "monthDate": "2018-05", "count": 83 }, { "monthDate": "2018-06", "count": 23 }];
var result = dataset.map(o => ({
monthDate: new Date(parseInt(o.monthDate), o.monthDate.slice(-2) - 1)
.toLocaleDateString("en", {month: "long", year: "2-digit"})
.replace(" ", "-"),
count: o.count
}));
console.log(result);
I'm trying to render a chart from a big amount of data (about 1200 entries). The chart takes in an array of objects with text and value properties like the one shown in FIG1. The data that I have coming in though is an object with key value pairs of string and number like the one shown if FIG2.
How could I transform the data from FIG2 format to FIG1 format so that I can use it in the Chart? Any help is much appreciated.
//FIG1
let words = [
{
text: "told",
value: 64,
},
{
text: "great",
value: 11,
},
{
text: "thought",
value: 16,
},
{
text: "clean",
value: 17,
},
];
//FIG2
const data = {
"give it a try!": 97,
"go for 6 months and get 1 month free": 8,
"go for 12 months and get 2 month free": 2,
"go for 12 months and get 2 months free": 6,
"go to url": 1,
};
...
return (
<div>
<h1>Chart</h1>
<ReactWordcloud words={words} />
</div>
);
Easy-Peasy
const transformed = Object.entries(data).map(( [key, value] )=>{
return { text:key , value: value }
})
I receive an array of posts through an API and want to merge the ones with the same "month" and "year" (day is not important), into one object. I looked up for answers but there are just too many foo-bar examples that confuses more than helping. I want to know the cleanest, most elegant way of handling such problems, without getting into call-back hell and nested blocks...
Here is the API response:
0:
{
date: {day: 27, month: 1, year: 2020}
id: 3
}
1:
{
date: {day: 28, month: 1, year: 2020}
id: 4
}
2:
{
date: {day: 31, month: 1, year: 2020}
id: 5
}
3:
{
date: {day: 1, month: 2, year: 2020}
id: 6
}
4:
{
date: {day: 2, month: 2, year: 2020}
id: 7
}
The expected outcome:
0:
result: {month: 1, year: 2020, id:[3,4,5]}
1:
result: {month: 2, year: 2020, id:[6,7]}
One approach would be to use the Array#reduce() method to transform the input array into a dictionary, where each value contains the accumulation of id's for that month and year. Once this dictionary has been built, you could then extract the values of that dictionary to an array via Object#values() to obtain the required output:
let input=[{date:{day:27,month:1,year:2020},id:3},{date:{day:28,month:1,year:2020},id:4},{date:{day:31,month:1,year:2020},id:5},{date:{day:1,month:2,year:2020},id:6},{date:{day:2,month:2,year:2020},id:7}];
/* Convert the dictionary that will be created by reduce to a value array */
var output = Object.values(input.reduce((dict, item) => {
const { date, id } = item;
/* The distinct key for this item based on month/year of date field */
const key = `${date.month}-${date.year}`;
/* Check if dictionary already has an object value for key. This short hand
will only insert a new object value for key, if one does not already exist
in the dictionary */
const value = dict[key] || { month : date.month, year : date.year, id : [] };
/* Add the item id to the dictionary entries id array */
value.id.push(id);
/* Update value object for key */
return { ...dict, [key] : value };
}, {}))
console.log(output);
The idea here is that the dictionary is built using Compound Keys, where the keys are derived from the month and year of the current array item.
When no value exists for the current key, a new value object is inserted to the dictionary for that key:
{ month : date.month, year : date.year, id : [] }
The id of the current array item is then added (accumulated) to the id sub array of the object for that key:
dict[key].id.push(id);
Hope that helps
Here is an alternate approach, if you are not a big fan of Array.reduce and Array.values and also, if you like to consider performance when running the response for a larger data set.
This approach avoids cloning object (or rather non-mutating object) with spread operator i.e {...<anyObject>} while iterating. which should be fine for minimal set of data but but definitely not when you deal with huge volume.
const response = [{
date: { day: 27, month: 1, year: 2020 },
id: 3
}, {
date: { day: 28, month: 1, year: 2020 },
id: 4
}, {
date: { day: 31, month: 1, year: 2020 },
id: 5
},{
date: { day: 1, month: 2, year: 2020 },
id: 6
},{
date: { day: 2, month: 2, year: 2020 },
id: 7
}];
function groupByMonthYear(response) {
// output
const groupedData = []
// Using map for lookup to avoid iterating again on the grouped data
const referenceMap = new Map();
// destructing month, year and id from the response
for (const { date: { month, year }, id } of response) {
const groupKey = `${month}${year}`
// check if the month and year reference is already seen using the groupKey MMYYYY
if (referenceMap.has(groupKey)) {
referenceMap.get(groupKey).id.push(id);
// early return
continue;
}
// simply add a new entry if it doesn't exist
const data = {
month,
year,
id: [id]
};
groupedData.push(data);
referenceMap.set(groupKey, data)
}
return groupedData;
}
// Invoke and Print the result
console.log(groupByMonthYear(response));
I have an array with a date. When I parse it, the month increases by 1. How can I fix it?
var data = [{
name: 'Arun',
date: [2019, 4, 9, 14, 55, 28, 897778]
}, {
name: 'Manohar',
date: [2019, 4, 3, 22, 43, 54, 894553]
}]
data.forEach((item) => {
item.date.pop()
item.date = new Date(...item.date).toLocaleString('en-US')
});
console.log(data)
I want the month as April and not May. Please advice.
As per the documentation suggests, the monthIndex would start at 0, rather than 1. So you need to manually subtract 1.
data.forEach((item) => {
item.date.pop()
item.date[1]--
item.date = new Date(...item.date).toLocaleString('en-US')
});
The month is represented by a value from 0 to 11, 4 is the fifth month, it corresponds to May, you just need to decrease it by 1.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
In JS, given an array of objects, like:
[{
date: 1525655429184,
value: 20.00
},{
date: 1525655429184,
value: 3.99
},{
date: 1526001029184,
value: 19.00
},{
date: 1526001025184,
value: 4.30
}]
Where the 'date' property is a date in milliseconds, and the 'value' property is a monetary represented by a float, and each object of this array can be one day of the month with his associated value.
I want to get the sum of value for each week day, to show in a chart of total values x day.
So the output should be like this example:
[
{ day: 'Sun', sum: 23.99 },
{ day: 'Mon', sum: 0 },
{ day: 'Tue', sum: 22.2 },
{ day: 'Wed', sum: 22.3 },
{ day: 'Thu', sum: 2.2 },
{ day: 'Fri', sum: 32.2 },
{ day: 'Sat', sum: 22.43 },
]
First, you need to convert the date (which i believe in milliseconds) into date and get the day by using getDay(). Create an array of days, loop thru the days, and if the converted date is the same as the day sum the values. Take a look at the snippet below.
var data = [{
date: 1525655429184,
value: 20.00
}, {
date: 1525655429184,
value: 3.99
}, {
date: 1526001029184,
value: 19.00
}, {
date: 1526001025184,
value: 4.30
}]
var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
var sumVals = [];
var daysSum = [];
var sumVal = days.forEach(function(day) {
var total = 0;
data.forEach(function(items) {
var d = new Date(items.date);
var formattedD = days[d.getDay()];
if (day === formattedD) {
total += parseFloat(items.value);
}
})
sumVals.push(total)
daysSum.push([day, total])
})
console.log(days)
console.log(sumVals)
console.log(daysSum)//just to show if it matches
Milliseconds in a day:
var millsperday = 1000*60*60*24;
Current millisecond/day offset:
var d = new Date();
var m = d.getTime();
d.setHours(0,0,0,0);
var o = d.getTime()-m;
So, to divide a list of (unixtime) milliseconds:
for (i=0;i<list.length;i++) {
numberofday = Math.floor((list[i]-o)/millsperday) ;
}