Я работаю над проектом визуализации данных, где я проанализировал каждую статью на главной странице определенного новостного веб-сайта в поисках 10 различных слов. Затем я подсчитал каждое появление этого слова в тот конкретный день.
Я пытаюсь реализовать линейный график для отображения использования каждого слова с течением времени. Что я хочу сделать, так это создать кнопку для каждого слова и при нажатии отображать линейный график, соответствующий набору данных каждого слова.
Моя первая проблема заключается в том, что все эти данные хранятся в большом наборе данных. Нет проблем, я отформатировал данные, чтобы они теперь существовали в одном большом объекте с 10 ключами для каждого слова. Каждый из этих ключей содержит массив в паре значений. Этот массив содержит объекты с ключом (date и word_count) и значениями соответственно.
Однако пример , который я использую для моделирования своего проекта, использует совершенно другой набор данных и имеет доступ к другим данным, поэтому теперь возникают проблемы.
Вот мои недавно отформатированные данные, все существующие в одном объекте. Я обнаружил, что это единственный способ разделить каждое слово на отдельный набор данных. Такие слова, как «Экстремист», «Бог», «Оружие» и т. д., являются ключевыми.
Значения представляют собой массив объектов, содержащих ключ (дата и количество) и пары значений соответственно.
ПРОБЛЕМА
Этот объект существует в переменной с именем «data_count».
То, что мне нужно сделать, аналогично тому, что указано в примере, это доступ ко всем переменным даты и количества с этим синтаксисом: data_count.Obama.date
или data_count.Obama.count
Прямо сейчас, чтобы получить доступ ко всем значениям даты или количества, мне нужно перебрать их и получить доступ к каждому индексу массива «Обама», например так
data_count.Obama[i].date
Проблема в том, что мне нужно вставить эти значения даты и столбца, чтобы они были приняты как координаты «x» и «y», используя функцию d3.line. Так что я не могу пройти через них. Как вы можете видеть в примере, пользователь получает доступ к своим парам ключ-значение через простую точечную нотацию. Но когда я повторяю его процесс, значение отображается как неопределенное.
Извините за стену текста! Надеюсь, кто-то может мне помочь! Спасибо.
Если я правильно понимаю, я считаю, что вы слишком усложняете вопрос: ваши данные очень совместимы с функцией обновления в примере, которым вы поделились. У вас есть массивы данных, как в примере, каждый элемент в массивах представляет точку на линии, свойства которой представляют значения как x, так и y. Функция обновления может передавать ваши данные или данные примеров с небольшими изменениями, чтобы учесть, что ось x является датой, а не числом:
Вам не нужно делать ничего другого, кроме основных модификаций: изменить шкалу, чтобы взять дату, изменить экстент оси x, чтобы min не равнялся 0, изменить свойства, передаваемые каждой шкале, и т. д. После того, как вы сделайте так, чтобы вы могли передать любое свойство current_data
своей функции обновления.
d3.csv("https://raw.githubusercontent.com/nickrinaldi88/BreitBart_DataVis/main/breitbartData.csv").then(function(csv) {
var current_data = {};
var parse = d3.timeParse("%Y-%m-%d")
for(var i=0; i < csv.length; i++) {
var item = csv[i];
if (!current_data[item.Word]) current_data[item.Word] = [];
current_data[item.Word].push({
date:parse(item.Date),
count:item.Count
})
}
d3.select("select")
.selectAll("option")
.data(Object.keys(current_data))
.enter()
.append("option")
.text(function(d) { return d; });
d3.select("select")
.on("change", function() {
update(current_data[this.value])
})
// set the dimensions and margins of the graph
var margin = {top: 10, right: 30, bottom: 30, left: 50},
width = 460 - margin.left - margin.right,
height = 250 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.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 + ")");
// Initialise a X axis:
var x = d3.scaleTime().range([0,width]);
var xAxis = d3.axisBottom().scale(x);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.attr("class","myXaxis")
// Initialize an Y axis
var y = d3.scaleLinear().range([height, 0]);
var yAxis = d3.axisLeft().scale(y);
svg.append("g")
.attr("class","myYaxis")
// Create a function that takes a dataset as input and update the plot:
function update(data) {
// Create the X axis:
x.domain(d3.extent(data, function(d) { return d.date }) );
svg.selectAll(".myXaxis").transition()
.duration(3000)
.call(xAxis);
// create the Y axis
y.domain([0, d3.max(data, function(d) { return +d.count }) ]);
svg.selectAll(".myYaxis")
.transition()
.duration(3000)
.call(yAxis);
// Create a update selection: bind to the new data
var u = svg.selectAll(".lineTest")
.data([data]);
// Updata the line
u
.enter()
.append("path")
.attr("class","lineTest")
.merge(u)
.transition()
.duration(3000)
.attr("d", d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.count); }))
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 2.5)
}
// At the beginning, I run the update function on the first dataset:
update(current_data.Obama)
})
path {
stroke-width: 1px;
stroke: black;
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<select></select>
<div id = "my_dataviz"></div>
Эй, ты не мог бы кое-что объяснить? В функции обновления, когда мы добавляем атрибут «d» и передаем d3.line в качестве второго аргумента, мы возвращаем x(d.date) и y(d.count). Если я попытаюсь выполнить console.info(d.date) или d.count, я получу неопределенное значение. Вот почему я не думал, что мы можем получить доступ к этим столбцам, поэтому я подумал о другом способе. Аргумент «d» представляет наши данные, верно? Итак, если я консолью регистрирую данные, которые являются current_data, передаю слово, выбранное из раскрывающегося списка, current_data["Obama"], затем пытаюсь получить доступ ко всем столбцам даты через current_data["Obama"].date, почему я получаю " неопределенный"?
Вы должны иметь возможность регистрировать d.date везде, где d.date используется во фрагменте выше: .x(function(d) { console.info(d.date); return x(d.date); })
будет регистрировать даты в этой строке. Вы должны сделать это во встроенной функции, потому что здесь d
представляет точку на линии, и функция повторяется для каждой точки. d
передается в качестве параметра встроенной функции автоматически d3 за кулисами и не будет определяться где-либо еще. Но, возможно, я не понимаю.
Кроме того, вы должны получить undefined с помощью current_data["Obama"].date
, поскольку current_data["Obama"]
— это массив без свойства date
, вместо этого вы можете регистрировать current_data["Obama"][0].date
или внутри функции обновления data[0].date
.
Вау, я ценю это. Этот код, похоже, решил все мои проблемы. Я определенно переосмыслил это. Это был мой первый реальный опыт работы с d3, поэтому я собираюсь сравнить этот код с тем, что у меня было раньше, чтобы увидеть, что отличается, и почему он не работает, почему я хотел.