0

When you use a counter in an sql query in a php script connecting a database to d3, how do you call that counter to use the values stored in it from d3? For instance I have the query

SELECT `ID_to`, count(*) as counter from `citations` group by `ID_to` ORDER BY counter desc

Now I want to call counter from d3 and use its values to scale my y axis on my scatterplot. It doesnt seem to work when I just use it as if it were a column in the table ie:

var yValue = function(d) { return d.counter;}, // data -> value
yScale = d3.scale.linear().range([height, 0]), // value -> display
yMap = function(d) { return yScale(yValue(d));}, // data -> display
yAxis = d3.svg.axis().scale(yScale).orient("left");

d3.json("connection2.php", function(error, data){
data.forEach(function(d) {
    d['ID_from'] =+d['ID_from']; 
    d['counter'] = +d['counter'];

     console.log(d);
    })      

How do I access these counter values and use them in d3?? Any help is much appreciated I am getting very frustrated with myself going around in circles. The error I'm getting is :

Error: Invalid value for <circle> attribute cy="NaN"

EDIT:: Here is my php script:

<?php
$username = "xxx"; 
$password = "xxx";   
$host = "xxx";
$database="xxx";

$server = mysql_connect($host, $username, $password);
$connection = mysql_select_db($database, $server);

$myquery = "SELECT `ID_to`, count(*) as `counter` from `citations` group by `ID_to`";

$query = mysql_query($myquery);

if ( ! $query ) {
    echo mysql_error();
    die;
}

$data = array();

for ($x = 0; $x < mysql_num_rows($query); $x++) {
    $data[] = mysql_fetch_assoc($query);
}

echo json_encode($data);     

mysql_close($server);
?>

I have ran it in my browser and it returns correct results.

4 Answers 4

1

The reason for your cy="NaN" is that you've not assigned a domain to your scale. While the range is the pixel space of your chart, the domain is the value space (the range of values) in your data. You can use d3.extent, to get the min/max of your dataset:

yScale = d3.scale
  .linear()
  .range([height, 0])
  .domain(
    d3.extent(data, function(d){ return d.counter; })
  );

I suggest you take the time to create a small reproducible example of your problem. I attempted to do that below, but everything works fine.

Also, In this statement d3.json("connection2.php", function(error, data){, you don't handle the error, are you sure your JSON's returning correctly:

d3.json("connection2.php", function(error, data){
   if (error) throw error;

   console.log(data);

What does that output?


<!DOCTYPE html>
<meta charset="utf-8">
<style>
  body {
    font: 10px sans-serif;
  }
  
  .axis path,
  .axis line {
    fill: none;
    stroke: #000;
    shape-rendering: crispEdges;
  }
  
  .dot {
    stroke: #000;
  }
</style>

<body>
  <script src="//d3js.org/d3.v3.min.js"></script>
  <script>
  
    var margin = {
        top: 20,
        right: 20,
        bottom: 30,
        left: 40
      },
      width = 960 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

    var yValue = function(d) {
        return d.counter;
      }, // data -> value
      yScale = d3.scale.linear().range([height, 0]), // value -> display
      yMap = function(d) {
        return yScale(yValue(d));
      }, // data -> display
      yAxis = d3.svg.axis().scale(yScale).orient("left");
      
    var xValue = function(d){
      return d.ID_from;
    },
    xScale = d3.scale.linear().range([0, width]), // value -> display
    xMap = function(d) {
        return xScale(xValue(d));
      }, // data -> display
    xAxis = d3.svg.axis().scale(xScale).orient("bottom");

    var svg = d3.select("body").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


    var data = [{
      'ID_from': 1,
      'counter': parseInt(Math.random() * 100)
    }, {
      'ID_from': 2,
      'counter': parseInt(Math.random() * 100)
    }, {
      'ID_from': 3,
      'counter': parseInt(Math.random() * 100)
    }, {
      'ID_from': 4,
      'counter': parseInt(Math.random() * 100)
    }, {
      'ID_from': 5,
      'counter': parseInt(Math.random() * 100)
    }, {
      'ID_from': 6,
      'counter': parseInt(Math.random() * 100)
    }, {
      'ID_from': 7,
      'counter': parseInt(Math.random() * 100)
    }, {
      'ID_from': 8,
      'counter': parseInt(Math.random() * 100)
    }];

    data.forEach(function(d) {
      d.ID_from = +d.ID_from;
      d.counter = +d.counter;
    });

    xScale.domain([d3.min(data, xValue) - 1, d3.max(data, xValue) + 1]);
    yScale.domain([d3.min(data, yValue) - 1, d3.max(data, yValue) + 1]);

    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

    svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
      .append("text");

    svg.selectAll(".dot")
      .data(data)
      .enter().append("circle")
      .attr("class", "dot")
      .attr("r", 3.5)
      .attr("cx", xMap)
      .attr("cy", yMap);

  </script>

Sign up to request clarification or add additional context in comments.

1 Comment

i am using this further on as my domain xScale.domain([d3.min(data, xValue)-1, d3.max(data, xValue)+1]); yScale.domain([d3.min(data, yValue)-1, d3.max(data, yValue)+1]);
0

Actually you are not assigning variable d to any global-scope variabile neither to a member of d3 object. In other words d is deallocated just after your console.log statements at every (forEach) loop iteration and its value get lost.

Comments

0

you should first check your service "connection2.php", we have no idea here, do you make some serialization and what's happen there - maybe you have a problem here. Just debug your service or execute it with "php connec....php" or use echo "<pre>";MY PHP STUFF HERE; echo"</pre>"; in your script and call your URL, to see your output in a browser, are you get any results.

Now you can try to use again your json-client-code, if every think is ok, then try "console.log(d)" before you try to use some keys of hashes. After that you can use console.log(d['SOME_KEY_WORD']) and "typeof" to see you get the write type, before make some math-operation, but at least, without your php-service you can not get a precise answer, just some debug steps and speculations. Cheers.

1 Comment

I've edited the above post to include my php script hopefully my question will be more clear
0

provide some more information. how do you assign the variable from the database query? if the sql query is called in the connection2.php and its result is assigned to some variable, let's call it $some_array, (like $some_array=$some_db_handler->someQuery(..your query..)); then you should write it to the output.

writing output with just echo in php will not help, since i assume the D3.json() that you are calling will expect a json. so do it like echo(json_encode($some_array));

then console.log(data) to verify the data that you have received

1 Comment

I have edited the above post to include my php script could you point out where in the script I should make the change? Thanks for response!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.