javascript d3.js scatter-plot nvd3.js

javascript - Gráfico de dispersión d3.v3 con todos los círculos del mismo radio



d3.js scatter-plot (2)

El radio se mide en píxeles. Si lo configura en un valor inferior a uno, sí, tendrá un círculo muy pequeño. La mayoría de los ejemplos que usan números aleatorios también usan un factor de escala.

Si desea que todos los círculos tengan un radio constante, no necesita establecer el valor en los datos, simplemente configúrelo cuando agregue el atributo de radio.

No estoy seguro de qué tutoriales estaba viendo, pero comience aquí: https://github.com/mbostock/d3/wiki/Tutorials

El ejemplo "Tres pequeños círculos" hace un buen paso a paso de las diferentes cosas que puedes hacer con los círculos: http://mbostock.github.io/d3/tutorial/circle.html

Cada ejemplo que he encontrado muestra que todos los puntos de la gráfica de dispersión son de radios aleatorios. ¿Es posible tenerlos todos del mismo tamaño? Si trato de establecer estáticamente el radio, todos los círculos serán muy pequeños (estoy asumiendo el radio predeterminado). Sin embargo, si uso Math.random () como en la mayoría de los ejemplos, hay círculos grandes y pequeños. Quiero que todos los círculos sean grandes. ¿Hay una manera de hacer eso? Aquí está el fragmento de código que forma los datos del gráfico usando Math.random () (esto funciona bien por alguna razón):

function scatterData(xData, yData) { var data = []; for (var i = 0; i < seismoNames.length; i++) { data.push({ key: seismoNames[i], values: [] }); var xVals=""+xData[i]; xVals=xVals.split(","); var yVals=""+yData[i]; yVals=yVals.split(","); for (var j = 0; j < xVals.length; j++) { data[i].values.push({ x: xVals[j], y: yVals[j], size: Math.random() }); } } return data; }

Math.random () escupe valores entre 0 y 1 como 0.164259538891095 y 0.9842195005008699. He intentado poner estos como valores estáticos en el atributo ''tamaño'', pero no importa que los círculos sean siempre muy pequeños. ¿Se me escapa algo?


Actualización: La API de NVD3 ha cambiado, y ahora usa pointSize , pointSizeDomain , etc. en lugar de solo size . El resto de la lógica para explorar la API actual sin documentación completa aún se aplica.

Para los gráficos NVD3, la idea es que todos los ajustes que realice se puedan realizar llamando a métodos en la función del gráfico en sí (o sus componentes públicos) antes de llamar a esa función para dibujar el gráfico en un elemento contenedor específico.

Por ejemplo, en el ejemplo que también vinculó, la función del gráfico se inicializó así:

var chart = nv.models.scatterChart() .showDistX(true) .showDistY(true) .color(d3.scale.category10().range()); chart.xAxis.tickFormat(d3.format(''.02f'')); chart.yAxis.tickFormat(d3.format(''.02f''));

Los .showDistX() y .showDistY() activan la distribución de marcas en los ejes; .color() establece la serie de colores que desea usar para las diferentes categorías. Las siguientes líneas también acceden a los objetos de eje predeterminados dentro del gráfico y configuran el formato numérico para que sea un decimal de dos dígitos. Puede jugar con estas opciones haciendo clic en la opción de diagrama de dispersión de la página "Código en vivo" .

Lamentablemente, los creadores de los gráficos NVD3 no tienen una documentación completa disponible que describa todas las demás opciones que puede configurar para cada gráfico. Sin embargo, puede usar el javascript para saber qué métodos están disponibles.

Inspeccionar un objeto de gráfico NVD3.js para determinar las opciones

Abra una página web que cargue la biblioteca d3 y nvd3. La página de códigos en vivo en su sitio web funciona bien. A continuación, abra la línea de comandos de la consola del desarrollador (esto dependerá de su navegador, busque en sus páginas de ayuda si aún no sabe cómo). Ahora, cree una nueva función de gráfico de dispersión nvd3 en la memoria:

var testChart = nv.models.scatterChart();

En mi consola (Chrome), la consola imprimirá todo el contenido de la función que acaba de crear. Es interesante, pero muy largo y difícil de interpretar de un vistazo. Y la mayor parte del código está encapsulado, por lo que no puede cambiarlo fácilmente. Desea saber qué propiedades puede cambiar. Por lo tanto, ejecute este código en la siguiente línea de su consola:

for (keyname in testChart){console.log(keyname + " (" + typeof(testChart[keyname]) + ")");}

La consola ahora debería imprimir prolijamente los nombres de todos los métodos y objetos a los que puede acceder desde esa función de gráfico. Algunos de estos tendrán sus propios métodos y objetos a los que puede acceder; descubra lo que son ejecutando la misma rutina, pero reemplazando el testChart con testChart.propertyName , así:

for (keyname in testChart.xAxis){console.log(keyname + " (" + typeof(testChart.xAxis[keyname]) + ")");}

De vuelta a tu problema La pequeña rutina que sugerí arriba no ordena los nombres de las propiedades en ningún orden, pero al hojear la lista, debería ver tres opciones relacionadas con el tamaño (que era la variable de datos que los ejemplos usaban para establecer el radio)

  • tamaño (función)
  • sizeDomain (función)
  • sizeRange (función)

Dominio y rango son términos utilizados por las escalas D3 , por lo que me da una pista sobre lo que hacen. Como no desea escalar los puntos, comencemos por mirar solo la propiedad de tamaño. Si escribe lo siguiente en la consola:

testChart.size

Debería imprimir el código de esa función. No es terriblemente informativo para lo que nos interesa, pero me muestra que NVD3 sigue el formato getter / setter de D3: si llama a .property(value) establece la propiedad a ese valor, pero si llama a .property() sin ningún parámetro, devolverá el valor actual de esa propiedad.

Entonces, para averiguar cuál es la propiedad del tamaño por defecto, llame al método size() sin parámetros:

testChart.size()

Debe imprimir la function (d) { return d.size || 1} function (d) { return d.size || 1} , que nos dice que el valor predeterminado es una función que busca una propiedad de tamaño en los datos, y si no existe, devuelve la constante 1. En términos más generales, nos dice que el valor establecido por el método de tamaño determina cómo el gráfico obtiene el valor de tamaño de los datos. El valor predeterminado debe dar un tamaño constante si sus datos no d.size propiedad d.size , pero para una buena medida, debe llamar a chart.size(1); en su código de inicialización para decirle a la función de gráfico que no se moleste en intentar determinar el tamaño a partir de los datos y simplemente use un valor constante.

Volviendo al diagrama de dispersión en vivo, podemos probarlo. Edite el código para agregar en la llamada de tamaño, como este:

var chart = nv.models.scatterChart() .showDistX(true) .showDistY(true) .color(d3.scale.category10().range()) .size(1); chart.xAxis.tickFormat(d3.format(''.02f'')); chart.yAxis.tickFormat(d3.format(''.02f''));

Agregar esa llamada adicional establece con éxito todos los puntos al mismo tamaño, pero ese tamaño definitivamente no es de 1 píxel, por lo que está claro que se está produciendo una escala.

La primera conjetura para obtener puntos más grandes sería cambiar chart.size(1) a chart.size(100) . Nada cambia, sin embargo. La escala predeterminada es claramente calcular su dominio basado en los datos y luego generar una gama estándar de tamaños. Esta es la razón por la cual no se pueden obtener círculos grandes al establecer el valor de tamaño de cada elemento de datos en 0,99, incluso si eso crearía un círculo grande cuando algunos de los datos fueran 0.01 y algunos fueran 0.99. Claramente, si desea cambiar el tamaño de salida, también tendrá que establecer la propiedad .sizeRange() en el gráfico.

Llamar a testChart.sizeRange() en la consola para averiguar el valor predeterminado no es muy informativo: el valor predeterminado es nulo (inexistente). Así que solo hice una conjetura de que, al igual que la función de escala lineal D3 .range() , la entrada esperada es una matriz de dos elementos que consta de los valores máximo y mínimo. Como queremos una constante, el máximo y el mínimo serán los mismos. Entonces en el código en vivo cambio:

.size(1);

a

.size(1).sizeRange([50,50]);

¡Ahora algo está sucediendo! Pero los puntos siguen siendo bastante pequeños: definitivamente no tiene 50 píxeles de radio, se ve más cerca de 50 píxeles cuadrados en el área. Tener un tamaño calculado en función del área tiene sentido cuando se dimensiona a partir de los datos, pero eso significa que para establecer un tamaño constante tendrá que calcular el área aproximada que desea: valores de hasta 200 se ven bien en el ejemplo, pero el valor Eliges dependerá del tamaño de tu gráfico y de lo cerca que estén tus puntos de datos.

- ABR

PD: agregué la etiqueta NVD3.js a su pregunta; asegúrese de usarlo como su etiqueta principal en el futuro cuando haga preguntas sobre las funciones del gráfico NVD3.