OneHotEncoder(Estimator)
и VectorIndexer
- совершенно разные звери и не подлежат обмену. OneHotEncoder(Estimator)
используется главным образом, когда последующий процесс использует линейную модель ( он также может быть использован с Наивным Байесом ).
Давайте рассмотрим простое Dataset
val df = Seq(1.0, 2.0, 3.0).toDF
и Pipeline
import org.apache.spark.ml.Pipeline
import org.apache.spark.ml.feature._
val m1 = new Pipeline().setStages(Array(
new OneHotEncoderEstimator()
.setInputCols(Array("value")).setOutputCols(Array("features"))
)).fit(df)
Если такая модель будет применена к нашим данным, она будет в одно касание -кодированный (в зависимости от конфигурации OneHotEncoderEstimator
поддерживает как горячее, так и фиктивное кодирование) - другими словами, каждый уровень, исключая ссылку, будет представлен в виде отдельного двоичного столбца:
m1.transform(df).schema("features").metadata
[113 ]
Обратите внимание, что такое представление неэффективно и нецелесообразно для использования с алгоритмами, которые изначально обрабатывают категориальные функции.
Напротив, VectorIndexer
только анализирует данные и соответственно корректирует метаданные
val m2 = new Pipeline().setStages(Array(
new VectorAssembler().setInputCols(Array("value")).setOutputCol("raw"),
new VectorIndexer().setInputCol("raw").setOutputCol("features")
)).fit(df)
m2.transform(df).schema("features").metadata
org.apache.spark.sql.types.Metadata = {"ml_attr":{"attrs":{"nominal":[{"ord":false,"vals":["1.0","2.0","3.0"],"idx":0,"name":"value"}]},"num_attrs":1}}
Другими словами, это более или менее эквивалентно векторизованному варианту StringIndexer
(вы можете достичь аналогичного результата, с большим контролем над выводом, используя набор StringIndexers
, за которым следует VectorAssembler
).
Такие функции не подходят для линейных моделей , но являются действительными входными данными для деревьев решений и ансамблей деревьев.
Подводя итог - на практике OneHotEncoder(Esitmator)
и VectorIndexer
являются взаимоисключающими, и выбор, какой из них следует использовать, зависит от последующего процесса.
Метод замены может взять функцию в качестве своего второго аргумента. Это получает соответствие (включая подсоответствия) и возвращает замещающую строку. Другие уже упомянули, что круглых скобок нужно оставить.
"Item Name (4)".replace(/\((\d+)\)/, function(fullMatch, n) {
return "(" + (Number(n) + 1) + ")";
});
Я могу, может только думать о способе сделать его на трех шагах: Извлечение, инкремент и замена.
// Tested on rhino
var name = "Item Name (4)";
var re = /\((\d+)\)/;
match = re.exec(name);
number = parseInt(match[1]) + 1;
name = name.replace(re, "(" + number + ")");
Важные части шаблона:
'var name = "Item Name (4)"'.replace(/\(([\d]+)\)/, 1 + $1);
(непротестированный)
В порядке этот шаблон для работы Вас shoud выходят из круглой скобки. Кроме того, \b и $ являются ненужными. Таким образом
var s = "Item Name (4)";
var match = /\((\d+)\)/.exec( s );
var n = Number(match[1])+1;
alert( s.replace( /\(\d+\)/, '('+n+')' ) );
Решение david.clarke (протестировано)
"Item Name (4)".replace(/\(([0-9]+)\)/, '('+(1+RegExp.$1) + ')');
Но я думаю, что это слишком кратко
UPD: оказалось, что 1$ RegExp. не может использоваться в качестве части параметра замены, потому что это работает только в Opera