Учитывая объявления
char *s0 = "hello world";
char s1[] = "hello world";
, предположим следующую гипотетическую карту памяти:
0x01 0x02 0x03 0x04 0x00008000: 'h' 'e' 'l' 'l' 0x00008004: 'o' ' ' 'w' 'o' 0x00008008: 'r' 'l' 'd' 0x00 ... s0: 0x00010000: 0x00 0x00 0x80 0x00 s1: 0x00010004: 'h' 'e' 'l' 'l' 0x00010008: 'o' ' ' 'w' 'o' 0x0001000C: 'r' 'l' 'd' 0x00
Строковый литерал "hello world"
представляет собой 12-элементный массив из char
( const char
в C ++) со статической продолжительностью хранения, что означает, что память для него выделяется при запуске программы и остается выделенной до тех пор, пока программа не завершится. Попытка изменить содержимое строкового литерала вызывает неопределенное поведение.
Линия
char *s0 = "hello world";
определяет s0
как указатель на char
с длительностью автоматического хранения (это означает, что переменная s0
существует только для области, в которой она объявлено) и копирует адрес строкового литерала (0x00008000
в этом примере) к нему. Обратите внимание, что поскольку s0
указывает на строковый литерал, он не должен использоваться в качестве аргумента для любой функции, которая попытается ее модифицировать (например, strtok()
, strcat()
, strcpy()
и т. Д.).
Строка
char s1[] = "hello world";
определяет s1
как 12-элементный массив из char
(длина берется из строкового литерала) с длительностью автоматического хранения и копирует содержимого литерала массиву. Как видно из карты памяти, у нас есть две копии строки "hello world"
; разница в том, что вы можете изменить строку, содержащуюся в s1
.
s0
и s1
взаимозаменяемы в большинстве контекстов; вот исключения:
sizeof s0 == sizeof (char*)
sizeof s1 == 12
type of &s0 == char **
type of &s1 == char (*)[12] // pointer to a 12-element array of char
Вы можете переназначить переменную s0
, чтобы указать на другой строковый литерал или на другую переменную. Вы не можете переназначить переменную s1
, чтобы указать на другой массив.
Предполагая, что ваши данные введены в data.frame, называемом dat
, скажем, два фактора приведены в этом примере:
> dat <- data.frame(f1=sample(LETTERS[1:3],20,T),f2=sample(LETTERS[4:5],20,T),id=1:20)
> dat
f1 f2 id
1 C D 1
2 B E 2
3 B E 3
4 A D 4
5 C E 5
6 C E 6
7 C D 7
8 B E 8
9 C D 9
10 A D 10
11 B E 11
12 C E 12
13 B D 13
14 B E 14
15 A D 15
16 C E 16
17 C D 17
18 C D 18
19 B D 19
20 C D 20
> dat$f1
[1] C B B A C C C B C A B C B B A C C C B C
Levels: A B C
> dat$f2
[1] D E E D E E D E D D E E D E D E D D D D
Levels: D E
Вы можете использовать outer
, чтобы получить матрицу как вы показали, для каждого фактора:
> F1 <- with(dat, outer(f1, levels(f1), `==`)*1)
> colnames(F1) <- paste("f1",sep="=",levels(dat$f1))
> F1
f1=A f1=B f1=C
[1,] 0 0 1
[2,] 0 1 0
[3,] 0 1 0
[4,] 1 0 0
[5,] 0 0 1
[6,] 0 0 1
[7,] 0 0 1
[8,] 0 1 0
[9,] 0 0 1
[10,] 1 0 0
[11,] 0 1 0
[12,] 0 0 1
[13,] 0 1 0
[14,] 0 1 0
[15,] 1 0 0
[16,] 0 0 1
[17,] 0 0 1
[18,] 0 0 1
[19,] 0 1 0
[20,] 0 0 1
Теперь сделайте то же самое для второго фактора:
> F2 <- with(dat, outer(f2, levels(f2), `==`)*1)
> colnames(F2) <- paste("f2",sep="=",levels(dat$f2))
И cbind
их, чтобы получить окончательный результат:
> cbind(F1,F2)
model.matrix
- это процесс, который lm
и другие используют в фоновом режиме для преобразования для вас.
dat <- data.frame(f1=sample(LETTERS[1:3],20,T),f2=sample(LETTERS[4:5],20,T),id=1:20)
dat
model.matrix(~dat$f1 + dat$f2)
Он создает переменную INTERCEPT как столбец из 1, но вы можете легко удалить что если вам нужно.
model.matrix(~dat$f1 + dat$f2)[,-1]
Изменить: теперь я вижу, что это по существу то же самое, что и один из других комментариев, но более краткий.
У вас есть несколько вариантов:
Используйте базу и объедините ее самостоятельно:
(iris.dummy<-with(iris,model.matrix(~Species-1)))
(IRIS<-data.frame(iris,iris.dummy))
Или используйте пакет ade4 следующим образом:
dummy <- function(df) {
require(ade4)
ISFACT <- sapply(df, is.factor)
FACTS <- acm.disjonctif(df[, ISFACT, drop = FALSE])
NONFACTS <- df[, !ISFACT,drop = FALSE]
data.frame(NONFACTS, FACTS)
}
dat <-data.frame(eggs = c("foo", "foo", "bar", "bar"),
ham = c("red","blue","green","red"), x=rnorm(4))
dummy(dat)
## x eggs.bar eggs.foo ham.blue ham.green ham.red
## 1 0.3365302 0 1 0 0 1
## 2 1.1341354 0 1 1 0 0
## 3 2.0489741 1 0 0 1 0
## 4 1.1019108 1 0 0 0 1