Как добавить дополнительное поле в набор данных в Vega-Lite

Мой набор данных представляет собой массив следующей формы:

[
  { "DATE" : "2020-01-02", "COUNTRY" : "Spain", "COUNT" : 110 },
  { ... },
  { ... }
]

Есть несколько стран и несколько дней. В датах нет пробелов.

Я хочу ввести поле DAYS_PASSED (и впоследствии использовать его для оси X), используя следующий алгоритм:

  1. Проверьте значение DAYS_PASSED за предыдущий день для той же страны и присвойте его переменной TEMP. (Если предыдущий день не существует, предположим, что 0);
  2. Вычислите DAYS_PASSED по следующей формуле:
   if TEMP > 0, then DAYS_PASSED = TEMP + 1
   else-if COUNT > 100 then DAYS_PASSED = 1
   else DAYS_PASSED = 0

До сих пор я делал это на этапе предварительной обработки (за пределами Vega-Lite), но мне было интересно, можно ли перенести расчет в Vega-Lite, возможно, подключив функцию JavaScript каким-либо образом?

Я также хотел бы иметь возможность выставить 100 (из условия COUNT > 100) на графике, чтобы пользователь мог настроить его, скажем, на 200.


person az5112    schedule 08.04.2020    source источник


Ответы (1)


Вы можете сделать это с помощью серии преобразований; Например:


  "transform": [
    {"calculate": "toDate(datum.DATE)", "as": "date"},
    {"calculate": "datum.COUNT < 100", "as": "pre100"},
    {
      "joinaggregate": [{"op": "sum", "field": "pre100", "as": "offset"}],
      "groupby": ["COUNTRY"]
    },
    {
      "window": [{"op": "count", "as": "daysPassed"}],
      "groupby": ["COUNTRY"],
      "sort": [{"field": "date"}]
    },
    {"calculate": "max(0, datum.daysPassed - datum.offset)", "as": "daysPassed"}
  ],

Вот более полный пример, показывающий это для небольшого набора данных (вега редактор):

{
  "data": {
    "values": [
      {"DATE": "2020-02-02", "COUNTRY": "Spain", "COUNT": 50},
      {"DATE": "2020-02-03", "COUNTRY": "Spain", "COUNT": 70},
      {"DATE": "2020-02-04", "COUNTRY": "Spain", "COUNT": 110},
      {"DATE": "2020-02-05", "COUNTRY": "Spain", "COUNT": 150},
      {"DATE": "2020-02-06", "COUNTRY": "Spain", "COUNT": 200},
      {"DATE": "2020-02-02", "COUNTRY": "Italy", "COUNT": 90},
      {"DATE": "2020-02-03", "COUNTRY": "Italy", "COUNT": 100},
      {"DATE": "2020-02-04", "COUNTRY": "Italy", "COUNT": 140},
      {"DATE": "2020-02-05", "COUNTRY": "Italy", "COUNT": 190},
      {"DATE": "2020-02-06", "COUNTRY": "Italy", "COUNT": 250}
    ]
  },
  "transform": [
    {"calculate": "toDate(datum.DATE)", "as": "date"},
    {"calculate": "datum.COUNT < 100", "as": "pre100"},
    {
      "joinaggregate": [{"op": "sum", "field": "pre100", "as": "offset"}],
      "groupby": ["COUNTRY"]
    },
    {
      "window": [{"op": "count", "as": "daysPassed"}],
      "groupby": ["COUNTRY"],
      "sort": [{"field": "date"}]
    },
    {"calculate": "max(0, datum.daysPassed - datum.offset)", "as": "daysPassed"}
  ],
  "concat": [
    {
      "mark": "line",
      "encoding": {
        "x": {"field": "DATE", "type": "temporal"},
        "y": {"field": "COUNT", "type": "quantitative"},
        "color": {"field": "COUNTRY", "type": "nominal"}
      }
    },
    {
      "mark": "line",
      "transform": [{"filter": "datum.daysPassed > 0"}],
      "encoding": {
        "x": {"field": "daysPassed", "type": "quantitative"},
        "y": {"field": "COUNT", "type": "quantitative"},
        "color": {"field": "COUNTRY", "type": "nominal"}
      }
    }
  ]
}

введите здесь описание изображения

person jakevdp    schedule 09.04.2020
comment
Спасибо - я действительно впечатлен. Я не осознавал, насколько сильны эти преобразования! Но .. я не уверен, что пример в редакторе делает именно то, что я хотел. Когда я изменяю последнюю точку данных для Испании и уменьшаю COUNT с 200 до 20, линия на втором графике становится короче, как если бы для Испании было только два daysPassed. Я задумал немного иначе. Вы переходите по датам, как только вы найдете точку данных для данной страны, которая соответствует условию (например, value > 100), тогда счетчик daysPassed начинает увеличиваться для данной страны (и никогда не останавливается). - person az5112; 09.04.2020
comment
Договорились - мой раствор предполагает момотоническое усиление. Какие идеи у вас есть для расширения решения? - person jakevdp; 09.04.2020
comment
Я принял ответ; в то время как он делает что-то немного другое, он дал достаточно намеков, чтобы я смог достичь того, чего хотел. Ключевым моментом было вычисление поля в виде флага в каждой точке данных, а затем выяснение того, как работают оконные функции. Я играл с Vega два вечера и поражен ее мощью. - person az5112; 10.04.2020
comment
Идеи для улучшения (взяв ваш график в качестве отправной точки): 1) при условии, что стран намного больше - показать список и разрешить выбор стран, которые будут отображаться на графике 2) выноски при наведении курсора мыши на отображение дополнительных данных для точки данных 3) после наведения указателя мыши на страну, покажите дневную гистограмму для этой страны на отдельном графике (теперь мой график показывает количество на миллион; столбчатая диаграмма будет отображать абсолютные числа) - person az5112; 10.04.2020
comment
Думаю, теперь мне нужно выяснить, как работают выделения. Иногда легко заблудиться, несмотря на отличную документацию. В качестве примера - после прочтения спецификации datetime (vega.github.io/vega- lite / docs / datetime.html) Я создал эти объекты на этапе предварительной обработки данных (вне Vega-lite). Я не предоставлял функцию Vega-lite toDate(), пока не проверил ваш пример. - person az5112; 10.04.2020