R scripts - lanit-tercom-school/analyzeme GitHub Wiki
- Общие сведения
- Хочу написать анализатор на R:
- Я написал скрипт, используя R-консоль. Что дальше?
- Скрипты пользователя
Использование языка R - один из наиболее популярных способов производить статистические исследования. В рамках нашего проекта работа с ним проходит в двух вариантах:
- заранее заготовленный в общем виде скрипт, используемый в качестве одного из анализаторов-"чёрных ящиков" (см., например, Общая схема вычисляемых функций)
- скрипты, написанные пользователем непосредственно для имеющихся в проекте данных
Здесь представлена краткая справка о том, каким условиям должен удовлетворять R скрипт, чтобы выполняться в нашем проекте, и что делать, когда он готов.
Для разработки анализатора, использующего язык R, почти не нужно знаний, специфических для нашего проекта. Необходимо только понимать, в каком виде представлены исходные данные - и что написать в последней строчке.
В данный момент данные, получаемые анализатором - набор именованых векторов-"колонок" одинаковой длины: Map<String, List<Double>>
. При преобразовании в R каждый из них переходит в отдельный вектор со стандартным именем: внутри скрипта используйте его.
Пример:
Пусть данные в Java перед вызовом анализатора были сформированы примерно так (анализатор получит на вход объект data
):
Map<String, List<Double>> data = new HashMap<String, List<Double>>();
List<Double> x = new ArrayList<Double>();
x.add(1.);
x.add(2.);
data.put("x", x);
List<Double> y = new ArrayList<Double>();
y.add(1.);
y.add(2.);
data.put("y", y);
Это равносильно тому, что перед вызовом написанного на R скрипта будут выполнены следующие команды:
col_0 <- c(1.0, 2.0)
col_1 <- c(1.0, 2.0)
Где col_0
соответствует x
, а col_1
- y
. Обращать внимание на преобразования названий внутри R скрипта не нужно: считайте, что на вход всегда приходит набор векторов с названиями вида col_0...col_n
. В случае, если в вашем скрипте всегда используется заданное число векторов, либо если он не будет работать меньше/больше чем с каким-то числом векторов, укажите это в комментарии в его начале.
Возможно, но не реализовано, представление входных данных в другом виде: например, data.frame или matrix с именованными колонками. Если для вашего скрипта оно принципиально важно, обратитесь в раздел, описывающий происходящее на стороне Java (см. Wiki) и создайте новые методы классов в package R.call, либо заведите issue, описывающий вашу потребность.
В процессе написания скрипта можно использовать практически любые package и команды R (неопределённое поведение может вызвать работа с графикой, избегайте её). Важно, чтобы результат его работы удовлетворял одному из приведённых ниже форматов.
В данный момент корректно будет обработан только double-результат, в ближайшее время предполагается добавить какой-то формат для работы со временем. Таким образом, сейчас вы можете написать скрипт, который вернёт:
- Скаляр (SCALAR_DOUBLE)
- Безымянный вектор (VECTOR_DOUBLE)
- Набор именованных векторов (VECTORS_DOUBLE)
- Неопределённый результат (NOT_PARSED_JSON_STRING)
Для того, чтобы вернуть результат работы R скрипта на сторону Java, достаточно прописать нужную переменную или команду на последней строчке.
В начале скрипта укажите #Output: SCALAR_DOUBLE.
Последней указанной переменной/результатом работы последней команды в скрипте должен быть double-вектор длины 1.
Примеры скриптов:
#minN = 2
#Output: SCALAR_DOUBLE
a <- col_0[5];
b <- mean(col_1);
result <- a + b
#minN = 1
#Output: SCALAR_DOUBLE
mean(col_0)
В начале скрипта укажите #Output: VECTOR_DOUBLE
Последней указанной переменной/результатом работы последней команды в скрипте должен быть double-вектор любой длины. Используйте такой вид результата в случае, если название вектора могло бы совпадать с названием вашего анализатора, но не с именем одной из "колонок".
Примеры скриптов:
#minN = 2
#Output: VECTOR_DOUBLE
a <- col_0[5];
b <- mean(col_1);
r <- c(a, b)
#minN = 2
#Output: VECTOR_DOUBLE
c(mean(col_0), col_1)
В начале скрипта укажите #Output: VECTORS_DOUBLE
Используйте этот вид результата в случае, если хотите вернуть несколько векторов (именованных или нет), или тогда, когда имя вектора имеет значение. Возможных типов значения в конце скрипта сейчас два.
Во-первых, data.frame. При желании имена векторов, использованных при его создании, можно менять и вручную, главное упомянуть нужную переменную/выполнить нужную команду на последней строке.
Пример скрипта:
#minN = 2
#Output: VECTORS_DOUBLE
z<-data.frame(col_0, col_1+3);
names(z) <- c("new col_0 name", "new col_1 name");
z
Во-вторых, можно использовать обычную матрицу.
Примеры:
#minN = 2
#Output: VECTORS_DOUBLE
m <- cbind(col_1, col_0);
colnames(m) <- c("new col_1 name", "new col_0 name");
m
#minN = 2
#Output: VECTORS_DOUBLE
m <- cbind(col_0, col_1);
m
#minN = 0
#Output: VECTORS_DOUBLE
m <- matrix(c(1, 2, 3, 4), nrow = 2, byrow=TRUE);
m
В последнем случае имена колонок результата будут сформированы автоматически в виде col0...coln
В случае, если в начале скрипта вы указали #Output: NOT_PARSED_JSON_STRING, результатом его выполнения можно делать что угодно (кроме графики). Это возможный, но не рекомендуемый вариант, т.к. его корректная обработка для представления результата пользователю сомнительна. Используйте только для экзотических статистик или в рамках отладки.
Для использования скриптов, соответствующих стандартной схеме:
//необязательно
#Name: some text here
//обязательна одна из двух следующих строк
#minN = number
#n = number
//необязательно
#Input: word
//обязательно
#Output: word
your script
Достаточно добавить их в папку r репозитория и запустить скрипт before_commit.bat (для других операционных систем - добавьте в файл rscripts_info.txt названия файлов с новыми скриптами).
Сейчас реализована поддержка файлов с данными в формате .json, .csv и .xls/.xlsx, примеры см. Home. Имя файла должно удовлетворять регулярному выражению [A-Za-z0-9,_.]+
.
Для обращения к данным из файлов в проекте, пользователь в своём скрипте должен использовать переменные специального вида. Название переменной должно удовлетворять регулярному выражению ([A-Za-z]+)_from__([A-Za-z]+)__([A-Za-z0-9,_.]+)__
и состоять из:
- название "колонки" данных (для точек это
x
илиy
) - специальное выражение
_from__
- указание на источник данных (сейчас поддерживается только
repo
для загруженных вFileRepository
файлов) - referenceName источника, окружённое символами
__
- например,__0_10.json__
Итого, примеры названий переменных:
x_from__repo__0_5.json__
z_from__repo__0_5_with_z.json__
time_from__repo__example.csv
//in the future
y_from__webRepo__webToken__
Реальная инициализация этих переменных будет происходить на стороне сервера перед запуском скрипта. Использовать же их в скрипте нужно как R-вектора соответствующего типа (сейчас поддерживается только double).
Остальное, за исключением названий переменных, аналогично разделу выше