I'm trying to get all users for the last 12 months from database and show some statistics using chart.For that purpose I'm using chartJS.
$registeredUsersData = $connection->fetchAll(
'SELECT
COUNT(id) AS registered_users,
CONCAT(MONTHNAME(created_on), " ", YEAR(created_on)) AS created_on
FROM users
WHERE created_on
BETWEEN CURDATE() - INTERVAL 12 MONTH AND CURDATE()
GROUP BY YEAR(created_on), MONTH(created_on)
ORDER BY YEAR(created_on) DESC, MONTH(created_on) DESC;
');
We pass it by symfony controller and render html template.
$registeredUsersCount = array_column($registeredUsersData, 'registered_users');
$registeredUserMonths = array_column($registeredUsersData, 'created_on');
return $this->render('dashboard/admin/index.html.twig', [
'registered_users_count' => $registeredUsersCount,
'registered_users_months' => $registeredUserMonths
]);
In the template I'm trying to display using a bar diagram that data where year and month should be combined and display on the abscissa(X-axis) and the count respectively on the ordinate(Y-axis).
<div class="chart-container">
<canvas id="canvas"></canvas>
</div>
let months = {{ registered_users_months|json_encode|raw }};
let users = {{ registered_users_count|json_encode|raw }};
const ctx = document.getElementById('canvas').getContext('2d');
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: months,
datasets: [{
label: 'Registered Users Monthly',
data: users,
backgroundColor: 'rgba(90, 80, 191, 0.2)',
borderColor: 'rgba(90, 80, 191, 1)',
borderWidth: 1
}]
},
options: {
maintainAspectRatio: false,
responsive: true,
scales: {
yAxes: [{
ticks: {
beginAtZero: true
},
}]
}
}
});
Data is properly displayed but not all "previous" 12 months are displayed.If a month does not have registered users it must be displayed as well but with count of zero. Unfortunately, the given query does not support that function currently, how could I modify it?
You need to make changes in your query like below:
$start = new DateTime(date('Y-m-d'));
$end = new DateTime(date('Y-m-d'));
$end->modify('+12 month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
$registeredUsersData[$dt->format('Y-m')] = 0;
}
$registeredUsersData = $connection->fetchAll(
'SELECT
COUNT(id) AS registered_users,
DATE_FORMAT(created_on,'%Y-%m') AS created_on
FROM users
WHERE created_on BETWEEN CURDATE() - INTERVAL 12 MONTH AND CURDATE()
GROUP BY DATE_FORMAT(created_on,'%Y-%m')
ORDER BY DATE_FORMAT(created_on,'%Y-%m') DESC;
');
foreach($registeredUsersData as $registeredUser) {
$registeredUsersData[$registeredUser['created_on']] = $registeredUser['registered_users'];
}
return $this->render('dashboard/admin/index.html.twig', [
'registered_users_count' => array_values($registeredUsersData),
'registered_users_months' => array_keys($registeredUsersData)
]);
I also updated your PHP have all dates for 12 months
I am more of a caveman coder than eloquent, but I believe this gets the result set you are looking for without changing your query... add this after your query to send the new data set to your controller.
for ($i = 1; $i < 12; $i++) {
$monthToCheck[$i]['registered_users'] = 0;
$monthToCheck[$i]['month_of_creation'] = date("F", strtotime( date( 'Y-m-01' )." -$i months"));
$monthToCheck[$i]['year_of_creation'] = date("Y", strtotime( date( 'Y-m-01' )." -$i months"));
}
return (array_merge($registeredUsersData,$monthToCheck));
Related
I'm not able to fill a Chart with my Array.
This is the Json: https://pastebin.com/KLUWqDFS
I'm trying to create a "Area" chart and fill it. Each element in the Json is half an hour.
let series = []
for(let i = 0; i < props.rrd.length; i++) {
series.push({
data: [
{
x: props.rrd[i].cpu * 100,
y: moment(props.rrd[i].time).format('hh:mm')
}
]
})
}
const chartOptions = {
yaxis: {
show: true
},
xaxis: {
show: true
}
}
This is what I'm using. Somehow all I get is this:
My Result
Eventhough it should show me the last 24 hours in the chart.
I am fetching json data from a API and I have to display some of the numbers as %. The json data displays them as 0.00. I tried this method, but it didn't work. I want to use a url to fetch my data, and then use Numeral.js to make the filtered data I got in %. What am I doing wrong? I create a template for my graph. I then make a fetch request to get my data and filter it, so I get the values I need. Then I take that value and try to format it. The new value I want to put on the graph.
const data = {
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
datasets: [
{
label: "ADOPTION",
data: [18, 12, 6, 9, 12, 3, 9],
backgroundColor: "rgba(73, 117, 197, 1)",
borderColor: "rgba(73, 117, 197, 1)"
},
{
label: "Target",
data: [0.654, 0.654, 0.751],
backgroundColor: "rgba(236, 123, 46, 1)",
borderColor: "rgba(236, 123, 46, 1)"
}
]
};
// config for graph
const config = {
type: "line",
data: data,
options: {
plugins: {
title: {
display: true,
text: 'data'
},
},
scales: {
y: {
beginAtZero: true
}
}
}
};
// render init block
const myChart = new Chart(
document.getElementById("data"),
config
);
// Fethc block for the graph
async function fetchJSON() {
const url="link";
const response = await fetch(url);
//* loads waiting to complete the request
const datapoints = await response.json();
return datapoints;
}
fetchJSON().then((datapoints) => {
const month = datapoints.map(function (index) {
return index.PERIOD_NAME; //*reffers to jSon word from file
});
console.log(month);
myChart.config.data.labels = month;
myChart.update();
});
fetchJSON().then((datapoints) => {
const total = datapoints.map(function (index) {
return index.ADOPTION //*reffers to jSon word from file
});
var string = numeral(datapoints).format('0.000%');
console.log(string);
myChart.config.data.datasets[0].data = total;
myChart.update();
});
<div class="col-sm-12 col-md-4 col-lg-4">
<canvas id="data"></canvas>
</div>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/chart.js"></script>
I'm guessing datapoints is an array. Numeral takes numbers or strings that it trys to convert into a number. You can use datapoints.map(val => numeral(val).format('0.00%')) to format the datapoints elements.
So I'm making this mobile app using Cordova, which allows me to use HTML, CSS and JavaScript. I'm currently using SQLite as a database (works almost same as mySQL) but that isn't that important. All I do is get my data from that database. I get both the date (of when the data was added to the Database) and the weight of a person.
I'm using a linegraph which show the weight on the Y-axis and the data on the X-axis.
What I want to do is only show the months as labels on the x-axis but still make it so that it show data for each day seperate. So for example if I add data on the 1st of January, the 2nd of January and the 3rd of January. I want to be able to see all 3 days as dots on my graph but on the X-axis it should only say 'January'.
I've been looking into the 'time' option of Chart.JS but can't really make any sense of how I'm supposed to do it.
HTML:
<canvas id="myChart" style="margin-top: 20px;"></canvas>
JavaScript:
//these are the arrays that I will fill dynamically. Labels will be my months and data will be the weight
var labels = [];
var data = [];
var ctx = document.getElementById('myChart').getContext('2d');
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'line',
// The data for our dataset
data: {
labels: labels,
datasets: [{
backgroundColor: 'rgba(255, 119, 0, 0.5)',
borderColor: 'rgba(255, 119, 0, 1)',
data: data
}]
},
// Configuration options go here
options: {
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
Use the time-type in your x-axis. With time: { unit: 'month' } (always months) or minUnit (months and years if necessary) you can get the month labels.
As label for your data you need to pass a Date or moment
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'month'
}
}],
}
Here is a complete example.
Check the moment docs for dates, especially the creation and parsing of dates. Chart.js works with moment dates so it's quite important (and quite easy btw).
I'm making a chart using Highcharts.js
The API I'm using has a different output than what Highchart uses.
Highchart reads JSON data as [timestamp, data]
which looks something like this: [1512000000000,171.85],
furthermore, the rest of the data is parsed within the same call.
Now MY Api outputs data by a single call for each timestamp (via url &ts=1511929853 for example
outputs {"ENJ":{"USD":0.02154}} (the price for that point in time)
Now here's where things get complicated. I would need to parse the price from a certain date, till now.
I've already made a ++ variable for the timestamp, but how would I include the timestamp and the price for that timestamp within the array for the data output.
It's a bit confusing, as the calls would have to be repeated so many times to draw a historical graph of the price. Some help would be appreciated. If you need more clarification, I'm right here.
Data is parsed via data function
full code here
var startDate = 1511929853;
var endDate = Math.floor((new Date).getTime()/1000);
function count() {
if (startDate != endDate) {
startDate++
}
else {
return false;
}
};
count();
$.getJSON('https://min-api.cryptocompare.com/data/pricehistorical?fsym=ENJ&tsyms=USD&ts=' + startDate, function (data) {
// Create the chart
var enjPrice = `${data.ENJ.USD}`;
console.log(enjPrice);
Highcharts.stockChart('container', {
xAxis: {
gapGridLineWidth: 0
},
rangeSelector: {
buttons: [{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'day',
count: 1,
text: '1D'
}, {
type: 'all',
count: 1,
text: 'All'
}],
selected: 1,
inputEnabled: false
},
series: [{
name: 'AAPL',
type: 'area',
data: JSON.parse("[" + enjPrice + "]"),
gapSize: 5,
tooltip: {
valueDecimals: 2
}
}]
});
});
You can use spread operator, like this,
let var = [new Date().getTime(), { ...data }.ENJ.USD]
This will result [1512000000000, 171.85] as you expected.
You need to make different functions for getting the data and generating the chart. Below is an example of how would you do it.
var startDate = 1511929853;
var endDate = Math.floor((new Date).getTime() / 1000);
var data = [];
function count() {
if (startDate != endDate) {
data.push(getPrice(startDate));
startDate++;
} else {
generateChart();
}
};
count();
function getPrice(timestamp) {
$.getJSON('https://min-api.cryptocompare.com/data/pricehistorical?fsym=ENJ&tsyms=USD&ts=' + startDate, function(data) {
return [timestamp, data.ENJ.USD];
});
}
function generateChart() {
Highcharts.stockChart('container', {
xAxis: {
gapGridLineWidth: 0
},
rangeSelector: {
buttons: [{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'day',
count: 1,
text: '1D'
}, {
type: 'all',
count: 1,
text: 'All'
}],
selected: 1,
inputEnabled: false
},
series: [{
name: 'AAPL',
type: 'area',
data,
gapSize: 5,
tooltip: {
valueDecimals: 2
}
}]
});
}
Though this is not the best way how you would do it but you get an idea.
I managed to solve the problem, by using a different API, which indexes data for past 30 days. I iterated into each index, 31, of them and grabbed the time and high(price) values and parsed them into a number since I was getting a "string" and then looped them into an array and put them into the final data [array]. just what I needed for the chart to work. If anyone needs any help just ask away. :) PS: Excuse the console.logs as I was using them to debug and test which helped me tremendously, you can remove them, as shall I
$.getJSON('https://min-api.cryptocompare.com/data/histoday?fsym=ENJ&tsym=USD', function(data) {
var x = `${data.Data[0].time}`;
var y = `${data.Data[0].high}`;
console.log(x);
console.log(y);
var tempData = [];
console.log(tempData);
for (var i = 0; i < 31; i++ ) {
var a = `${data.Data[i].time}`;
var b = `${data.Data[i].high}`;
function numberfy(val){
parseFloat(val);
}
a = parseFloat(a);
a = a * 1000;
b = parseFloat(b);
x = [a , b];
tempData.push(x);
};
data = tempData;
console.log(data.length);
Highcharts.stockChart('container', {
i work with jQuery chart.js for show view counter by month using PHP and MySql. I insert/Put each views page to MySql like this :
| id | ip | page | date(timestamp) |
| 1 | 138.86.20.20 | test.php | 1375710823 |
| 2 | 100.86.123.10 | test.php | 1380206563 |
for chart.js :
var data = {
labels: ["january","February", "March", "April", "May", "June", "July"],
datasets: [{
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,1)",
data: [150,59, 90, 81, 56, 55, 40]
}, {
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,1)",
data: [20,48, 40, 59, 500, 127, 100]
}]
}
var options = {animation :true};
//Get the context of the canvas element we want to select
var c = $('#daily-chart');
var ct = c.get(0).getContext('2d');
var ctx = document.getElementById("daily-chart").getContext("2d");
//Run function when window resizes
$(window).resize(respondCanvas);
function respondCanvas() {
c.attr('width', jQuery("#daily").width());
c.attr('height', jQuery("#daily").height());
//Call a function to redraw other content (texts, images etc)
myNewChart = new Chart(ct).Bar(data, options);
}
//Initial call
respondCanvas();
Now, I need to count views by/per month for chart.js data ouput using json format.
[150,59, 90, 81, 56, 55, 40,12,54,65,365,2] for 12 month strat #january.
How to crate this?!
NOTE: charts datasets have two color : 1- unique user 2- all user
You could use a query to group the visits by month:
SELECT COUNT(*), MONTH(date(timestamp)), YEAR(date(timestamp))
FROM table
GROUP BY MONTH(FROM_UNIXTIME(date(timestamp)), YEAR(FROM_UNIXTIME(date(timestamp))
Which will return the number of visits, with the year and month they correspond to.
\EDIT\
To loop through and print each month's value, use a mysqli_query and WHILE in PHP:
$query = mysqli_query($con, "THE QUERY ABOVE ^^");
while($row = mysqli_fetch_array($query {
echo $row['date(timestamp)'].",";
}