Это потому, что если бы у вас было c("X.Intercept.", "x1A", "x1B", "x2")
, то у вас была бы идеальная мультиколлинеарность: x1A + x1B
был бы столбцом единиц, точно так же как столбец X.Intercept.
. Если для интерпретации вы предпочитаете иметь x1A
вместо перехвата, мы можем использовать
formula_test <- as.formula("Y ~ -1 + x1 + x2")
, давая
names(result_test)
# [1] "x1A" "x1B" "x2"
и
all(rowSums(result_test[, c("x1A", "x1B")]) == 1)
# [1] TRUE
[1114 ] Что касается того, почему опускается x1A
, а не x1B
, то, как представляется, правило заключается в том, что уровни первого фактора исчезают. Если вместо этого мы используем
levels(data_test$x1) <- c("B", "A")
, то это дает
names(result_test)
# [1] "X.Intercept." "x1A" "x2"
va_end
используется, чтобы сделать очистку. Вы не хотите разбивать стек, не так ли?
От man va_start
:
va_end ()
Каждый вызов va_start () должен быть подобран соответствующим вызовом va_end () в той же функции. После вызова va_end (AP) переменное AP не определено. Несколько обходов списка, каждый заключенный в скобки va_start () и va_end () возможен. va_end () может быть макросом или функцией.
Примечание присутствие Word должно .
стек мог стать поврежденным, потому что Вы не знаете то, что va_start()
делает . va_*
макросы предназначены, чтобы рассматриваться как черные квадраты. Каждый компилятор на каждой платформе может сделать то, что это хочет там. Это ничего не может сделать, или это может сделать много.
Некоторые ABIs передают первые несколько args в регистрах и остаток на стеке. va_arg()
там может быть более сложным. Можно искать, как данная реализация делает varargs, который может быть интересным, но в записи портативного кода необходимо рассматривать их как непрозрачные операции.
В общих "параметрах передал стек" реализация, я полагаю, что va_end () обычно nothing/empty/null. Однако на платформах, которые имеют менее традиционные схемы, это становится необходимым. Это - "хорошая практика" для включения его, чтобы остаться независимым от платформы.