Генератор formula
Используйте, когда колонка не разыгрывается, а вычисляется — из других колонок той же строки. Вес, который следует за ростом. ИМТ из обоих. Цена, умноженная на количество. Остаток, который нужно напечатать, а не проверить.
<gen type="formula" expr="0.75 * Height - 58 + 6 * Z" decimals="1"/>
expr= — это тот же язык, что и if=: те же операторы, те
же функции, те же имена для тех же колонок. Разница одна — куда девается ответ: if=
съедает его как «да/нет», а формула оставляет значением своей колонки.
| Атрибут | Что задаёт |
|---|---|
expr | Обязательный. Арифметика, которой эта колонка является |
decimals | Знаков после точки, 0..10. Без него значение печатается целиком |
Колонка, которая следует за другой
Настоящие данные — не набор независимых колонок: вес идёт за ростом, доход за образованием, площадь за ценой. Формула — способ это сказать:
<sequence name="Height"><gen type="number" distribution="normal" mean="170" sd="10" decimals="1"/></sequence>
<sequence name="Z"> <gen type="number" distribution="normal" mean="0" sd="1" decimals="4"/></sequence>
<sequence name="Weight"><gen type="formula" expr="0.75 * Height - 58 + 6 * Z" decimals="1"/></sequence>
<sequence name="BMI"> <gen type="formula" expr="Weight / pow(Height / 100, 2)" decimals="1"/></sequence>
<sequence name="Label"> <gen type="formula" expr="BMI > 25 ? over : normal"/></sequence>
152.3,62.1,26.8,over 187.3,73.4,20.9,normal 172.9,69.6,23.3,normal 164.9,59.8,22.0,normal 159.3,60.9,24.0,normal 157.4,63.9,25.8,over
Height разыгран, Z — шум, из-за которого связь не превращается в прямую линию,
остальные три вычислены. Z печатать не обязательно: не упоминайте колонку в
<block>, и она останется в расчёте, не попав в файл. В конфиге для data science таких
обычно несколько.
Последняя строка стоит отдельного внимания: тернарник заставляет формулу выдавать метку, а не только число — так у обучающего набора появляется целевая колонка.
Деление и остаток, который можно напечатать
Деление здесь настоящее и было таким всегда — это единственный оператор, который не может остаться целым, потому что целые числа делением не замыкаются:
<sequence name="N"> <gen type="number" value="1..20"/></sequence>
<sequence name="Half"><gen type="formula" expr="N / 2"/></sequence>
<sequence name="Rem"> <gen type="formula" expr="N % 3"/></sequence>
<sequence name="Row"> <gen type="formula" expr="_count"/></sequence>
n=15 half=7.5 rem=0 row=1 n=9 half=4.5 rem=0 row=2 n=9 half=4.5 rem=0 row=3 n=5 half=2.5 rem=2 row=4
_count и любая другая встроенная величина читаются, так что
тренд руками — это expr="100 + 0.05 * _count".
true / false, а не 1 / 0expr="BMI > 25" даёт слово true — так же, как _last, _first и любая колонка
anomaly_flag: одно написание для флага во всём движке.
Обучающему набору обычно нужна другая форма, и тернарник рядом:
<gen type="formula" expr="BMI > 25 ? 1 : 0"/>
Целые остаются целыми
Операнд, который ЯВЛЯЕТСЯ целым числом, так и несётся целым и становится дробным, только
когда об этом попросят. Поэтому формула точна везде, где точны её входы — 1000000 * 1000000 даёт верный ответ, а не округлённый, — и становится приблизительной только тогда,
когда конфиг попросил чего-то неточного. Правила те же, что и во всём языке выражений, и
выписаны в Выражениях.
0.1 + 0.2 == 0.3 — ложь, здесь и в любом другом языке, потому что у 0.1 нет точной
двоичной формы. Это честная арифметика IEEE, а не причуда движка, — но означает, что ветка,
написанная как if="A + B == 0.3", может не сработать никогда. Сравнивайте через < и >
либо сначала округляйте обе стороны.
Пустой источник даёт пустой ответ
Ячейка, которую опустошил parent= или
missing=, — это не ноль, и формула, читающая её,
выдаёт пустоту, а не выдуманное число:
<sequence name="H" parent="G.M"><gen type="number" value="170..190"/></sequence>
<sequence name="W"><gen type="formula" expr="H * 2"/></sequence>
F,, F,, M,170,340 M,172,344
Строки, где у H значения нет, оставляют пустым и W. Это то же правило, которому
следуют накопление и статистика, пропуская опустошённую
ячейку, — только с другой стороны. Оно же делает формулу безопасной поверх колонки с
missing=: пропуски остаются пропусками, а не превращаются в арифметику.
Обёртки, которых формула не берёт
mask=, case=, missing=, missing_as=, repeat=, anomaly= и
anomaly_factor= получают отказ TDC015, а не принимаются
и игнорируются. Формула разрешается до того, как заработает слой форматирования, — то
же место, что у running и stat.
Ответ существует шагом позже и он лучше, потому что работает там, где значение ПЕЧАТАЕТСЯ:
<data>${{Weight|mask:x}}</data>
Какой слой: formula или <compute>
Оба вычисляют значение, и разделение тут не дело вкуса:
formula | математика — дроби, деление, функции, любая производная величина |
<compute> | контрольные цифры и работа с текстом — мод-11, Луна, дополнение, вырезание |
<compute> намеренно работает только с целыми, потому что контрольной цифре нужно именно
это. Написать формулу в его дереве тегов можно, и это мучительно: (x - lo) / (hi - lo)
там — полэкрана вложенности, а здесь тринадцать символов.
Что отказывает check
Всё, что нужно формуле, известно из конфига, поэтому ничего не ждёт прогона:
- нет
expr=—TDC294. Формула И ЕСТЬ своё выражение. expr=, который не разбирается —TDC294, с указанием на место.- имя, не являющееся колонкой, объявленной выше —
TDC240, тот же код, что уrunningиstatна то же правило, с подсказкойdid you mean, если имя похоже на настоящее. Это самое важное: опечатка вif=— просто слово, и ветка тихо перестаёт срабатывать, а опечатка в формуле доходит до арифметики.
Ещё два отказа выдаёт прогон, потому что они зависят от значений, а не от конфига:
арифметика над текстовой колонкой (откуда иначе взялся бы NaN, а файл, полный NaN,
о котором никого не предупредили, хуже остановленного прогона) и деление на ноль.
Подробности
-
Читает свою строку. Строка i вычисляется из строки i и ничего больше, поэтому формула не тратит случайность — добавление её оставляет все остальные колонки на месте.
-
Порядок объявления. Формула строится из колонок, которые уже есть, поэтому каждое имя в
expr=должно принадлежать последовательности, объявленной выше. -
Она потоковая. Чтение только своей строки — ровно то, на чём построен потоковый движок, поэтому формула работает там как любая разыгранная колонка, и память не растёт вместе с числом строк. Измерено на одном конфиге: 1 млн строк — 2.1 с, 5 млн — 3.9 с, 20 млн — 9.5 с и файл на 291 МБ, при этом пик памяти вырос в 1.3 раза, пока число строк выросло в 20. Движок в памяти на тех же 5 млн занял 12.5 с и больше памяти, а до 20 млн не дотягивает вовсе.
Этим формула и отличается от накопления и статистики: тем двум нужны чужие строки — все предыдущие и вообще все, — поэтому они остаются в памяти по своему смыслу, а не по недоделке.
Смотрите также
- Выражения — операторы, функции и правила целых чисел.
- Накопление — когда ответу нужны строки до этой.
- Статистика — когда нужен весь прогон.
- Number — разыгранные колонки, которые формула читает.