Tengo un csv de 7 millones de registros de biodiversidad donde los niveles de taxonomía son como columnas. Por ejemplo:
RecordID,kingdom,phylum,class,order,family,genus,species
1,Animalia,Chordata,Mammalia,Primates,Hominidae,Homo,Homo sapiens
2,Animalia,Chordata,Mammalia,Carnivora,Canidae,Canis,Canis
3,Plantae,nan,Magnoliopsida,Brassicales,Brassicaceae,Arabidopsis,Arabidopsis thaliana
4,Plantae,nan,Magnoliopsida,Fabales,Fabaceae,Phaseoulus,Phaseolus vulgaris
Quiero crear una visualización en D3, pero el formato de datos debe ser una red, donde cada valor diferente de la columna es un elemento secundario de la columna anterior para un cierto valor. Necesito pasar del csv a algo como esto:
{
name: 'Animalia',
children: [{
name: 'Chordata',
children: [{
name: 'Mammalia',
children: [{
name: 'Primates',
children: 'Hominidae'
}, {
name: 'Carnivora',
children: 'Canidae'
}]
}]
}]
}
No se me ocurrió una idea de cómo hacer esto sin usar mil para bucles. ¿Alguien tiene una sugerencia sobre cómo crear esta red en python o javascript?
javascript
python
d3.js
data-visualization
hierarchical-data
Andres Camilo Zuñiga Gonzalez
fuente
fuente
nan
para el Filo que contiene Magnoliopsida. ¿Qué es esonan
? El Phylum es Anthophyta, o alternativamente Magnolia (es el antiguo Phylum Angiospermae).Respuestas:
Para crear el objeto anidado exacto que desea, usaremos una combinación de JavaScript puro y un método D3 llamado
d3.stratify
. Sin embargo, tenga en cuenta que 7 millones de filas (consulte el post scriptum a continuación) es mucho para calcular.Es muy importante mencionar que, para esta solución propuesta, tendrá que separar los Reinos en diferentes matrices de datos (por ejemplo, usando
Array.prototype.filter
). Esta restricción ocurre porque necesitamos un nodo raíz, y en la taxonomía linneana no hay relación entre reinos (a menos que cree "Dominio" como rango superior, que será la raíz para todos los eucariotas, pero entonces tendrás la misma problema para Archaea y Bacteria).Entonces, supongamos que tiene este CSV (agregué algunas filas más) con solo un Reino:
Basado en ese CSV, crearemos una matriz aquí
tableOfRelationships
que, como su nombre lo indica, tiene las relaciones entre los rangos:Para los datos anteriores, este es el
tableOfRelationships
:Eche un vistazo
null
como padre deAnimalia
: es por eso que le dije que necesita separar su conjunto de datos por Reinos, solo puede haber unnull
valor en toda la tabla.Finalmente, en base a esa tabla, creamos la jerarquía usando
d3.stratify()
:Y aquí está la demo. Abra la consola de su navegador (la del fragmento no es muy buena para esta tarea) e inspeccione los varios niveles (
children
) del objeto:Mostrar fragmento de código
PD : No sé qué tipo de dataviz crearás, pero realmente deberías evitar los rangos taxonómicos. Toda la taxonomía linneana está desactualizada, ya no usamos rangos: dado que la sistemática filogenética se desarrolló a mediados de los años 60, usamos solo taxones, sin ningún rango taxonómico (profesor de biología evolutiva aquí). Además, tengo bastante curiosidad acerca de estos 7 millones de filas, ¡ya que hemos descrito poco más de 1 millón de especies!
fuente
Es fácil hacer exactamente lo que necesita usando Python y la
python-benedict
biblioteca (es de código abierto en Github :Instalación
pip install python-benedict
La primera salida de impresión será:
La segunda salida impresa será:
fuente
fuente
Esto parece sencillo, así que quizás no entiendo tu problema.
La estructura de datos que desea es un conjunto anidado de diccionarios, pares clave / valor. Su diccionario de reino de nivel superior tiene una clave para cada uno de sus reinos, cuyos valores son diccionarios de filo. Un diccionario phylum (para un reino) tiene una clave para cada nombre phylum y cada clave tiene un valor que es un diccionario de clase, y así sucesivamente.
Para simplificar la codificación, los diccionarios de género tendrán una clave para cada especie, pero los valores para la especie serán diccionarios vacíos.
Esto debería ser lo que quieres; No se requieren bibliotecas extrañas.
Para probarlo, usé sus datos y
pprint
de la biblioteca estándar.consiguiendo
Al leer su pregunta nuevamente, es posible que desee una gran tabla de pares ('enlace de un grupo más general', 'enlace a un grupo más específico'). Es decir, 'Animalia' enlaza con 'Animalia: Chordata' y 'Animalia: Chordata' enlaza con 'Animalia: Chordata: Mammalia ", etc. Desafortunadamente, el' nan 'en sus datos significa que necesita nombres completos en cada enlace. Si ( padre, hijo) pares son lo que quieres, camina el árbol de esta manera:
dando:
fuente
name
ychildren
según lo solicitado en la pregunta.En Python, una forma de codificar un árbol es usar a
dict
, donde las claves representan nodos y el valor asociado es el padre del nodo:Una ventaja de esto es que se asegura de que los nodos sean únicos, ya
dicts
que no pueden tener claves duplicadas.Si desea codificar un gráfico dirigido más general (es decir, los nodos pueden tener más de un padre), puede usar listas para los valores y hacer que representen a los hijos (o padres, supongo):
Podría hacer algo similar con Objetos en JS, sustituyendo Arrays por listas, si es necesario.
Aquí está el código de Python que usé para crear el primer dict anterior:
fuente
Probablemente, la forma más sencilla de convertir sus datos en una jerarquía es utilizar el operador de anidamiento incorporado de D3
d3.nest()
:Al registrar las funciones clave a través de
nest.key()
, puede especificar fácilmente la estructura de su jerarquía. Al igual que Gerardo en su respuesta , puede usar la.columns
propiedad expuesta en la matriz de datos después de analizar su CSV para automatizar la generación de estas funciones clave. Todo el código se reduce a las siguientes líneas:Sin embargo, tenga en cuenta que la jerarquía resultante no se parece exactamente a la estructura solicitada en su pregunta, ya que los objetos son en
{ key, values }
lugar de{ name, children }
; Por cierto, esto también es válido para la respuesta de Gerardo. Sin embargo, esto no afecta a ambas respuestas, ya que los resultados pueden congestionarsed3.hierarchy()
especificando una función de acceso para niños :La siguiente demostración reúne todas las partes:
Mostrar fragmento de código
También es posible que desee echar un vistazo a la conversión de clave y valores d3.nest () a nombre e hijos en caso de que sienta la necesidad de tener exactamente su estructura publicada.
fuente
d3.nest
mientras dure: pronto será desaprobado.Un reto divertido. Prueba este código javascript. Utilizo el set de Lodash por simplicidad.
Esto produce el resultado final (similar) a lo que quieres.
fuente
De hecho, @Charles Merriam su solución es muy elegante.
Si desea obtener un resultado igual a la pregunta, intente lo siguiente.
fuente