ИМХО, эффективность скорости должна быть последней ваших проблем при написании кода, особенно если вы новичок. Вместо этого вы должны сосредоточиться на простоте, удобочитаемости и модульности. Не поймите меня неправильно, эффективность - это отличная вещь, и вы найдете много способов сделать ваш код быстрее, когда это необходимо, но это не должно быть приоритетом само по себе.
Так что я буду давать советы о стиле в основном. Чтобы проиллюстрировать это, вот как будет выглядеть моя версия вашего кода. Пожалуйста, имейте в виду, что я не знаю, что вычисляет ваш код, поэтому я приложил все усилия, чтобы сломать его, используя значимые имена переменных.
IVCV <- function(stack) {
## This function computes [...] IVCV stands for [...]
## Inputs:
## - stack: a matrix where each column [...]
## Output: a matrix [...]
n <- nrow(stack) # stack size
stack.ratios <- stack[-n, ] / stack[-1, ]
log.ratios <- log(stack.ratios)
ivcv <- solve(var(log.ratios))
return(ivcv)
}
ExcessReturn <- function(stack) {
## This function computes [...] IVCV stands for [...]
## Inputs:
## - stack: a matrix where each column [...]
## Output: a matrix [...]
n <- nrow(stack) # stack size
total.ratio <- stack[1, ] / stack[n, ]
excess.return <- (1 + log(total.ratio)) ^ (1 / n) - 1
return(excess.return)
}
ExcessReturnTimesIVCV <- function(stack) {
## This function computes [...] IVCV stands for [...]
## Inputs:
## - stack: a matrix where each column [...]
## Output: a vector [...]
return(IVCV(stack) %*% ExcessReturn(stack))
}
1) да, разбейте ваш код на маленькие функции. Это лучше для удобочитаемости, гибкости и обслуживания. Это также облегчает модульное тестирование, где вы можете создавать тесты для каждого элементарного фрагмента кода.
2) задокументировать функцию, включив комментарии о ее описании / входах / выходах внутри тела функции. Таким образом, после создания функции пользователь может видеть ее описание как часть распечатки функции (например, просто наберите ExcessReturnTimesIVCV
в GUI).
3) разбить сложность на несколько утверждений. Прямо сейчас, все ваши три предложения трудно понять, так как в каждой строке происходит слишком много вещей. Заявление должно делать простую вещь, чтобы его можно было легко прочитать. Создание большего количества объектов вряд ли замедлит ваш процесс, и это значительно упростит отладку.
4) имена ваших объектов - это ключ к ясности вашего кода. Выберите их хорошо и используйте последовательный синтаксис. Я использую UpperCamelCase для имен своих собственных функций и строчные слова, разделенные точками для большинства других объектов.
5) размещать комментарии, особенно там, где 3) и 4) недостаточно, чтобы сделать код понятным. В моем примере я решил использовать переменную n
. Я пошел против рекомендации, что имена переменных должны быть описательными, но это должно было сделать код немного легче и придать выражениям типа stack[-n, ] / stack[-1, ]
некоторую приятную симметрию. Поскольку n
- это плохое имя, я добавил комментарий, объясняющий его значение. Я мог бы также добавить больше комментариев в код, если бы знал, что на самом деле делают функции.
6) Используйте согласованные правила синтаксиса, в основном для улучшения читабельности. Вы услышите разные мнения о том, что следует использовать здесь. В общем, нет одного лучшего подхода. Самое главное, чтобы сделать выбор и придерживаться его. Итак, вот мои предложения:
a) одно утверждение в строке, без точек с запятой.
б) постоянный интервал и отступ (без вкладок). Я ставлю пробелы после запятых, вокруг бинарных операторов. Я также использую дополнительный интервал, чтобы выровнять вещи, если это помогает читаемости.
в) последовательная привязка: будьте осторожны с тем, как вы используете фигурные скобки для определения блоков, в противном случае у вас могут возникнуть проблемы в режиме сценария. См. Раздел 8.1.43 R Inferno (отличный справочник.)
Удачи!