I have a string like this:
"[\'2021_04_27__21_52_09\', \'2021_04_27__21_52_13\', \'2021_04_27__21_52_16\']",
and I separate out the date values and put them in an array like this:
["2021_04_27__21_52_09", "2021_04_27__21_52_13", "2021_04_27__21_52_16"].
I want to draw a line plot with these values on the x axis so I do
`var x_data = ["2021_04_27__21_52_09", "2021_04_27__21_52_13", "2021_04_27__21_52_16"]
var timeParser = d3.timeParse("%Y_%m_%d__%H_%M_%S");`
timeParser(x_data) returns null and I'm not sure why. How do I convert the x_data array into a format so that I can easily create d3 graph using the array as the x axis?
First test:
timeParser("2021_04_27__21_52_09")
If that works, you need to map the function across your array:
let x = x_data.map(timeParser)
Format your data strings correctly and convert to valid JS dates:
const data = ["2021_04_27__21_52_09", "2021_04_27__21_52_13", "2021_04_27__21_52_16"];
const converted = data.map(d => {
const date = d.substr(0, 10).replaceAll('_', "/");
const time = d.substr(12).replaceAll('_', ':');
return new Date(`${date} ${time}`);
});
Related
In My streamBuilder I have Array list contains dates having format(dd-MM-yyyy).
I want to arrange the list in ascending order.
The code I used in StreamBuilder after getting Datasnapshot
Map<dynamic, dynamic> data = snap.data.snapshot.value;
List item = [];
data.forEach(
(index, data) => item.add(
{"key": index, ...data}
)
);
item..sort((a,b)=>a['key'].compareTo(b['key']));
I am expecting result as
16-06-2020
17-06-2020
18-06-2020
19-06-2020
22-06-2020
04-07-2020
The result I am getting is
04-07-2020
16-06-2020
17-06-2020
18-06-2020
19-06-2020
22-06-2020
You'll need to parse your Strings to DateTimes. Since DateTime parse() method won't accept Strings in the format you provided, you can do something like this:
List<String> strings = ['04-07-2020', '17-06-2020', '16-06-2020', '19-06-2020', '18-06-2020', '22-06-2020'];
List<DateTime> dateTimes = [];
strings.forEach((string) {
var splitted = string.split('-');
var day = splitted[0];
var month = splitted[1];
var year = splitted[2];
var formatted = '$year-$month-$day';
dateTimes.add(DateTime.parse(formatted));
});
dateTimes.sort((a, b) => a.compareTo(b));
Just adapt it for your structure!
Storing the data as Timestamps in Firebase would make it much simpler, then you can sort it by this Timestamp.
If you need the dates formatted as a String (dd-MM-yyyy) you can just parse it to Datetime and use the Intl-Package to convert it to a formatted String.
I'm trying to create a generic composite chart that would take any csv file, read the columns and create a composite line chart with one line per column.
In this use case, the first column is always TimeStamp in all csv's and this will not be changed, while the rest of the columns may vary.
To get the column names from any csv, I am using the following line of code.
var mappedArray = d3.entries(data[0]);
Say, my mappedArray is like this :
["Date", "c1", "c2", "c3"]
I have created the Dimension for timestamp as follows:
var DateDim = ndx.dimension(function(d){return timeFmt(d[mappedArray[0].key]); });
For a single valued group, i would use something like this:
var testGrp = DateDim.group().reduceSum(function(d){return +d[mappedArray[1].key]; });
For a multi valued group, I tried something like this:
var testGrp1 = testDim.group().reduce(
function(p,v){
++p.count;
p.col1 = +v[mappedArray[1].key];
p.col2 = +v[mappedArray[2].key];
...
p.coln = +v[mappedArray[n].key];
return p;
},...
But, I cannot hard code like this, as the 'n' in mappedArray[n] may keep changing.
How can I recreate this group by using mappedArray.length?
You recreate by using the index field operator []. Use a for loop to create as many p.colX fields as needed.
var testGrp1 = testDim.group().reduce(
function(p,v){
++p.count;
for (let i = 1; i < mappedArray.length; i++) {
p["col" + i] = +v[mappedArray[i].key];
}
return p;
},...
Edit
The answer to your question in the comment about the chart.compose.
A possible way of doing is to create a function that constructs the array needed.
function makeComposeArray() {
var composeArr = [];
for(let i=1; i<=mappedArray.length; i++) {
composeArr.push(
dc.lineChart(chart)
.group(testGrp1, function(d){return d['col'+i]})
.valueAccessor(function(d){return d.value["col" + i]})
);
}
return composeArr;
}
chart.compose(makeComposeArray());
I am creating a JSL script for some of my datatables and need my function to act on a column.
I can get the function to act on the column during a plotting event, but not with standard operations.
Here's an example that works. This acts on the current datatable and plots up the Distribution for :Column1, which happens to be Nominal Character with 4 unique items in it.
a = Function(
{col}, // Function parameters
{Default Local}, // Local variables
Distribution(
Nominal Distribution(
Column( col ),
Horizontal Layout( 1 ),
Vertical( 0 )
);
);
);
dt = Current Data Table();
a(Expr(:Column1));
Note the Expr() around :Column1. Without this, the Distribution function does not work.
What I'm trying to do is the following, but it doesn't work. What it should do is show the number of unique items in :Column1.
a = Function(
{col}, // Function parameters
{Default Local}, // Local variables
retval = associative array(col);
Show(nitems(retval));
);
dt = Current Data Table();
a(Expr(:Column1));
Returns in Log Window:
N Items(retval) = 0; // Should be 4
If I run the script without trying to wrap it in a function, then it works just fine:
retval = associative array(:Column1);
Show(nitems(retval));
Returns in Log Window:
N Items(retval) = 4; // My column happens to have 4 unique entries in it.
I'm fairly certain that my issue has something to do with namespace inside the function, but I can't seem to figure it out. Does anyone have any suggestions?
It is (from what I've seen) just an issue with the scoping operator : in :Column1.
Try using
a = Function(
{col}, // Function parameters
{Default Local}, // Local variables
retval = associative array(col<<Get Values)<<Get Keys;
Show(nitems(retval));
);
dt = Current Data Table();
a(column(dt, "Column1"));
it returned
N Items(retval) = 9;
Thanks already to Serge insas for his insight both here and here, which have been a godsend for me already. But...I'm having trouble tying everything together with date validation.
To clarify, I have a GAS intended to verify that the date in Column A is (a) more than seven days old and (b) not null. If both pass, the script determines the first empty row in Column G, and then pauses before completing various functions. The beginning of the script looks like...
function getStats() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var sheet = doc.getSheetByName("Main");
var TITLE_ROW = 1;
var DATE_COL = 1;
var URL_COL = 4;
var sevendaysBefore = new Date(new Date().getTime()-7*24*60*60*1000);
if (DATE_COL != ''||(DATE_COL != null || DATE_COL< sevendaysBefore)) {
var end = sheet.getLastRow();
for( var i = 1; i < end; i++) {
var Gvals = sheet.getRange("G1:G").getValues();
var Glast = Gvals.filter(String).length;
var rowNum = TITLE_ROW+Glast;
var itemurl = sheet.getRange(rowNum,URL_COL).getValues();
Utilities.sleep(500);
...
I've clearly implemented something wrong, though, because the date validation doesn't workâthe script appears to function as though the data in Column A doesn't matter. I'm sure I've done something incredibly idiotic, but I'm too ignorant to spot it on my own. So...anyone know what I've overlooked?
While the other answer is probably working (didn't test), its approach is very different from yours.
Below is code that follows the same logic as yours but works at the array level (to follow recommendations in Best practices).
I added a few comments to show the differences, hoping it will help you to understand how it works.
function getStats() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var sheet = doc.getSheetByName("Main");
var Glast; // define the variable for later use
var vals = sheet.getDataRange().getValues();// get all data in an array (do that before loop)
var TITLE_ROW = 0;// use array index instead of real row numbers
var DATE_COL = 0;// use array index instead of real column numbers
var URL_COL = 3;// use array index instead of real column numbers
var sevendaysBefore = new Date(new Date().getTime()-7*24*60*60*1000).getTime();// get native value in milliseconds to make comparison easier below
for( var i = 1; i < vals.length; i++) { // start loop from Row 2 (=array index 1)
if(vals[i][0]!='' && vals[i][0]!=null&&vals[i][0].getTime()<sevendaysBefore){continue};// use && instead of ||, we want ALL conditions to be true ( see !='' and !=null)
Glast = i; break ;// first occurrence of data meeting above condition (non null and date < 7 days before)
}
var itemurl = vals[Glast][URL_COL];// get the value from the array
Utilities.sleep(500);
//...
Mistake : You are hard coding DATE_COL = 1 and you are using this in if statement. It doesn't get the value of the cell. Also I am not getting your statement "date in Column A is (a) more than seven days old". Is that date is from a cell or you are iterating through all the cells in column A ?.
Below code will satisfy your need and I tested. Here as example I am checking date validation for cell R1C1(A1).
1)Get the date from cell. You can change it or Iterate the cells in column for date.
2) We have date.valueOf() method which returns the number of milliseconds since midnight 1970-01-01.
3) Validation : check the cell data is date and greater than 7 days
function compDate()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = sheet.getRange("A1"); //point1
var date01 = new Date();
var date02 = cell.getValue(); //point2
var dateDiff = (date01.valueOf()-date02.valueOf())/(24*60*60*1000);
if((isValidDate(date02)) == true && dateDiff > 7) //point3
Logger.log("success");
}
//below function will return true if the arg is valid date and false if not.
function isValidDate(d) {
if ( Object.prototype.toString.call(d) !== "[object Date]" )
return false;
return !isNaN(d.getTime());
}
I have a 2 column matrix I've saved out of R that looks like :
,y
4.93707840,-2.17356434
4.41122212,-1.96256698
4.21076739,-1.75156962
4.06441510,-1.54057226
The code I'm using is :
var data = d3.text("2013.csv", function(unparsedData)
{
var dataset = d3.csv.parseRows(unparsedData);
// Code here
})
Only the second column is imported. There is a header row which contains ,y which I really need to skip or replace.
Any ideas?
I tried this :
var dataset
d3.csv("2013.csv", function (error, dataset) {
console.log(dataset)
But still only the 2nd column is imported.