У меня есть CSV 7 миллионов записей биоразнообразия, где уровни таксономии в виде столбцов. Например:
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
Я хочу создать визуализацию в D3, но формат данных должен быть сетевым, где каждое другое значение столбца является дочерним по отношению к предыдущему столбцу для определенного значения. Мне нужно перейти от CSV к чему-то вроде этого:
{
name: 'Animalia',
children: [{
name: 'Chordata',
children: [{
name: 'Mammalia',
children: [{
name: 'Primates',
children: 'Hominidae'
}, {
name: 'Carnivora',
children: 'Canidae'
}]
}]
}]
}
Я не придумал, как это сделать, не используя тысячу циклов for. У кого-нибудь есть предложения о том, как создать эту сеть на python или javascript?
javascript
python
d3.js
data-visualization
hierarchical-data
Андрес Камило Суньига Гонсалес
источник
источник
nan
для Типа, содержащего Магнолиопсиду. Что этоnan
? Типом является Антофита, или, в качестве альтернативы, Магнолия (это старый Phylum Angiospermae).Ответы:
Для создания нужного вложенного объекта мы будем использовать смесь чистого JavaScript и метода D3 с именем
d3.stratify
. Тем не менее, имейте в виду, что 7 миллионов строк (см. Постскриптум ниже) - это много для вычисления.Очень важно отметить, что для этого предлагаемого решения вам придется разделить Королевства в разных массивах данных (например, используя
Array.prototype.filter
). Это ограничение возникает из-за того, что нам нужен корневой узел, и в таксономии Линнея нет никакой связи между королевствами (если вы не создадите «Домен» в качестве высшего ранга, который будет корнем для всех эукариот, но тогда у вас будет то же самое проблема для архей и бактерий).Итак, предположим, у вас есть этот CSV (я добавил еще несколько строк) только с одним Королевством:
На основе этого CSV мы создадим массив с именем,
tableOfRelationships
который, как следует из названия, имеет отношения между рангами:Для приведенных выше данных это
tableOfRelationships
:Взгляните
null
как на родителяAnimalia
: именно поэтому я сказал вам, что вам нужно разделить ваш набор данных по Kingdoms,null
во всей таблице может быть только одно значение.Наконец, на основе этой таблицы мы создаем иерархию, используя
d3.stratify()
:И вот демо. Откройте консоль браузера (фрагмент кода не подходит для этой задачи) и проверьте несколько уровней (
children
) объекта:Показать фрагмент кода
PS : я не знаю, какой тип данных вы создадите, но вам действительно следует избегать таксономических рангов. Вся таксономия Линнея устарела, мы больше не используем ранги: поскольку филогенетическая систематика была разработана в середине 60-х годов, мы используем только таксоны без какого-либо таксономического ранга (здесь учитель эволюционной биологии). Кроме того, мне довольно любопытно эти 7 миллионов строк, так как мы описали чуть более 1 миллиона видов!
источник
С Python и
python-benedict
библиотекой легко сделать именно то, что вам нужно (это открытый исходный код на Github :Установка
pip install python-benedict
Первый вывод на печать будет:
Второй печатный вывод будет:
источник
источник
Это кажется простым, так что, возможно, я не понимаю вашу проблему.
Желаемая структура данных - это вложенный набор словарей, пар ключ / значение. В вашем словаре королевства верхнего уровня есть ключ для каждого из ваших королевств, значения которого - словари филюмов. Типовой словарь (для одного королевства) имеет ключ для каждого имени типа, а каждый ключ имеет значение, являющееся словарем классов и т. Д.
Чтобы упростить кодирование, в ваших словарях рода будет ключ для каждого вида, но значения для вида будут пустыми словарями.
Это должно быть то, что вы хотите; никаких странных библиотек не требуется.
Чтобы проверить это, я использовал ваши данные и
pprint
из стандартной библиотеки.получение
При повторном чтении вашего вопроса вам может понадобиться большая таблица пар («ссылка из более общей группы», «ссылка на более конкретную группу»). То есть ссылки «Animalia» на «Animalia: Chordata» и «Animalia: Chordata» ссылаются на «Animalia: Chordata: Mammalia» и т. Д. К сожалению, «nan» в ваших данных означает, что вам нужны полные имена для каждой ссылки. Если ( пары родительские, дочерние) - это то, что вы хотите, пройдитесь по дереву следующим образом:
давая:
источник
name
и,children
как того требует вопрос.В Python одним из способов кодирования дерева является использование a
dict
, где ключи представляют узлы, а соответствующее значение является родительским узлом:Преимущество этого заключается в том, что вы гарантируете, что узлы уникальны, поскольку
dicts
не могут иметь дублирующиеся ключи.Если вы хотите закодировать более общий ориентированный граф (т. Е. Узлы могут иметь более одного родителя), вы можете использовать списки для значений и иметь представляющих детей (или, я полагаю, родителей):
Вы можете сделать нечто подобное с объектами в JS, заменив списки массивами, если это необходимо.
Вот код Python, который я использовал для создания первого dict выше:
источник
Вероятно, самый простой способ превратить ваши данные в иерархию - это использовать встроенный оператор вложенности D3
d3.nest()
:Регистрируя ключевые функции через,
nest.key()
вы можете легко определить структуру вашей иерархии. Подобно тому, как Герардо изложил в своем ответе, вы можете использовать.columns
свойство, представленное в массиве данных после анализа CSV, для автоматизации генерации этих ключевых функций. Весь код сводится к следующим строкам:Обратите внимание, однако, что получающаяся иерархия не совсем напоминает структуру, запрошенную в вашем вопросе, поскольку объекты
{ key, values }
вместо{ name, children }
; кстати, это верно и для ответа Герардо. Это не помешает обоим ответам, поскольку результаты могут быть перегруженыd3.hierarchy()
указанием дочерней функции доступа :Следующая демонстрация объединяет все части:
Показать фрагмент кода
Возможно, вы также захотите взглянуть на преобразование ключа и значений d3.nest () в имя и дочерние элементы, если вам необходимо иметь точно опубликованную структуру.
источник
d3.nest
пока это длится: это скоро устареет.Веселый вызов. Попробуйте этот код JavaScript. Я использую набор Лодаша для простоты.
Это дает конечный результат (аналог), что вы хотите.
источник
На самом деле, @Charles Merriam его решение очень элегантно.
Если вы хотите, чтобы результат был таким же, как вопрос, попробуйте следующее.
источник