У меня проблемы с созданием следующих фиктивных переменных в R:
Я анализирую данные годовых временных рядов (период 1948-2009 гг.). У меня два вопроса:
Как мне создать фиктивную переменную для наблюдения № 10, то есть для 1957 года (значение = 1 в 1957 году и ноль в противном случае)?
Как создать фиктивную переменную, которая была равна нулю до 1957 года и принимала значение 1 с 1957 года и далее до 2009 года?
+ 0
или- 1
. Такmodel.matrix(~ year.f + 0)
будут даны фиктивные переменные без эталонного уровня.Самый простой способ создать эти фиктивные переменные - это примерно так:
> print(year) [1] 1956 1957 1957 1958 1958 1959 > dummy <- as.numeric(year == 1957) > print(dummy) [1] 0 1 1 0 0 0 > dummy2 <- as.numeric(year >= 1957) > print(dummy2) [1] 0 1 1 1 1 1
В более общем плане вы можете использовать
ifelse
для выбора одного из двух значений в зависимости от условия. Так что, если вместо фиктивной переменной 0-1 по какой-то причине вы хотите использовать, скажем, 4 и 7, вы можете использоватьifelse(year == 1957, 4, 7)
.источник
Использование dummies :: dummy () :
library(dummies) # example data df1 <- data.frame(id = 1:4, year = 1991:1994) df1 <- cbind(df1, dummy(df1$year, sep = "_")) df1 # id year df1_1991 df1_1992 df1_1993 df1_1994 # 1 1 1991 1 0 0 0 # 2 2 1992 0 1 0 0 # 3 3 1993 0 0 1 0 # 4 4 1994 0 0 0 1
источник
Пакет для этого
mlr
включаетcreateDummyFeatures
:library(mlr) df <- data.frame(var = sample(c("A", "B", "C"), 10, replace = TRUE)) df # var # 1 B # 2 A # 3 C # 4 B # 5 C # 6 A # 7 C # 8 A # 9 B # 10 C createDummyFeatures(df, cols = "var") # var.A var.B var.C # 1 0 1 0 # 2 1 0 0 # 3 0 0 1 # 4 0 1 0 # 5 0 0 1 # 6 1 0 0 # 7 0 0 1 # 8 1 0 0 # 9 0 1 0 # 10 0 0 1
createDummyFeatures
удаляет исходную переменную.https://www.rdocumentation.org/packages/mlr/versions/2.9/topics/createDummyFeatures
.....
источник
Другие ответы здесь предлагают прямые маршруты для выполнения этой задачи, которые многие модели (например
lm
) в любом случае сделают для вас внутри. Тем не менее, вот способы сделать фиктивные переменные популярнымиcaret
с помощьюrecipes
пакетов Max Kuhn и . Хотя они несколько более подробны, они оба легко масштабируются для более сложных ситуаций и аккуратно вписываются в соответствующие рамки.caret::dummyVars
С
caret
, соответствующая функцияdummyVars
, которая имеетpredict
метод , чтобы применить его на кадр данных:df <- data.frame(letter = rep(c('a', 'b', 'c'), each = 2), y = 1:6) library(caret) dummy <- dummyVars(~ ., data = df, fullRank = TRUE) dummy #> Dummy Variable Object #> #> Formula: ~. #> 2 variables, 1 factors #> Variables and levels will be separated by '.' #> A full rank encoding is used predict(dummy, df) #> letter.b letter.c y #> 1 0 0 1 #> 2 0 0 2 #> 3 1 0 3 #> 4 1 0 4 #> 5 0 1 5 #> 6 0 1 6
recipes::step_dummy
С
recipes
, соответствующая функцияstep_dummy
:library(recipes) dummy_recipe <- recipe(y ~ letter, df) %>% step_dummy(letter) dummy_recipe #> Data Recipe #> #> Inputs: #> #> role #variables #> outcome 1 #> predictor 1 #> #> Steps: #> #> Dummy variables from letter
В зависимости от контекста извлеките данные с помощью
prep
и либо,bake
либоjuice
:# Prep and bake on new data... dummy_recipe %>% prep() %>% bake(df) #> # A tibble: 6 x 3 #> y letter_b letter_c #> <int> <dbl> <dbl> #> 1 1 0 0 #> 2 2 0 0 #> 3 3 1 0 #> 4 4 1 0 #> 5 5 0 1 #> 6 6 0 1 # ...or use `retain = TRUE` and `juice` to extract training data dummy_recipe %>% prep(retain = TRUE) %>% juice() #> # A tibble: 6 x 3 #> y letter_b letter_c #> <int> <dbl> <dbl> #> 1 1 0 0 #> 2 2 0 0 #> 3 3 1 0 #> 4 4 1 0 #> 5 5 0 1 #> 6 6 0 1
источник
Для варианта использования, представленного в вопросе, вы также можете просто умножить логическое условие на
1
(или, может быть, даже лучше, на1L
):# example data df1 <- data.frame(yr = 1951:1960) # create the dummies df1$is.1957 <- 1L * (df1$yr == 1957) df1$after.1957 <- 1L * (df1$yr >= 1957)
который дает:
Для вариантов использования, представленных, например, в ответах @ zx8754 и @Sotos, есть еще некоторые другие варианты, которые еще не были рассмотрены imo.
1) Сделайте свою собственную
make_dummies
функцию# example data df2 <- data.frame(id = 1:5, year = c(1991:1994,1992)) # create a function make_dummies <- function(v, prefix = '') { s <- sort(unique(v)) d <- outer(v, s, function(v, s) 1L * (v == s)) colnames(d) <- paste0(prefix, s) d } # bind the dummies to the original dataframe cbind(df2, make_dummies(df2$year, prefix = 'y'))
который дает:
2) используйте
dcast
-функцию из любогоТаблица данных или reshape2который дает:
Однако это не сработает, если в столбце есть повторяющиеся значения, для которых необходимо создать фиктивные переменные. В случае, если требуется конкретная функция агрегирования,
dcast
а результатdcast
нужно объединить с исходным:# example data df3 <- data.frame(var = c("B", "C", "A", "B", "C")) # aggregation function to get dummy values f <- function(x) as.integer(length(x) > 0) # reshape to wide with the cumstom aggregation function and merge back to the original merge(df3, dcast(df3, var ~ var, fun.aggregate = f), by = 'var', all.x = TRUE)
что дает (обратите внимание, что результат упорядочен в соответствии с
by
столбцом):3) используйте
spread
-функцию изтидир(сmutate
отdplyr)library(dplyr) library(tidyr) df2 %>% mutate(v = 1, yr = year) %>% spread(yr, v, fill = 0)
который дает:
источник
Что я обычно делаю для работы с такими фиктивными переменными:
(1) как мне создать фиктивную переменную для наблюдения № 10, то есть для 1957 года (значение = 1 в 1957 году и ноль в противном случае)
data$factor_year_1 <- factor ( with ( data, ifelse ( ( year == 1957 ), 1 , 0 ) ) )
(2) как мне создать фиктивную переменную, которая была равна нулю до 1957 года и принимала значение 1 с 1957 года и далее до 2009 года?
data$factor_year_2 <- factor ( with ( data, ifelse ( ( year < 1957 ), 0 , 1 ) ) )
Затем я могу ввести этот фактор в качестве фиктивной переменной в свои модели. Например, чтобы увидеть, есть ли долгосрочный тренд в переменной
y
:Надеюсь это поможет!
источник
Если вы хотите получить K фиктивных переменных вместо K-1, попробуйте:
dummies = table(1:length(year),as.factor(year))
Лучший,
источник
as.data.frame.matrix(dummies)
чтобы перевести это в одинЯ прочитал это на форуме kaggle:
#Generate example dataframe with character column example <- as.data.frame(c("A", "A", "B", "F", "C", "G", "C", "D", "E", "F")) names(example) <- "strcol" #For every unique value in the string column, create a new 1/0 column #This is what Factors do "under-the-hood" automatically when passed to function requiring numeric data for(level in unique(example$strcol)){ example[paste("dummy", level, sep = "_")] <- ifelse(example$strcol == level, 1, 0) }
источник
ifelse
Функция лучше всего подходит для простой логики , как это.> x <- seq(1950, 1960, 1) ifelse(x == 1957, 1, 0) ifelse(x <= 1957, 1, 0) > [1] 0 0 0 0 0 0 0 1 0 0 0 > [1] 1 1 1 1 1 1 1 1 0 0 0
Кроме того, если вы хотите, чтобы он возвращал символьные данные, вы можете это сделать.
> x <- seq(1950, 1960, 1) ifelse(x == 1957, "foo", "bar") ifelse(x <= 1957, "foo", "bar") > [1] "bar" "bar" "bar" "bar" "bar" "bar" "bar" "foo" "bar" "bar" "bar" > [1] "foo" "foo" "foo" "foo" "foo" "foo" "foo" "foo" "bar" "bar" "bar"
Категориальные переменные с вложенностью ...
> x <- seq(1950, 1960, 1) ifelse(x == 1957, "foo", ifelse(x == 1958, "bar","baz")) > [1] "baz" "baz" "baz" "baz" "baz" "baz" "baz" "foo" "bar" "baz" "baz"
Это самый простой вариант.
источник
Другой способ - использовать
mtabulate
изqdapTools
пакета, т.е.df <- data.frame(var = sample(c("A", "B", "C"), 5, replace = TRUE)) var #1 C #2 A #3 C #4 B #5 B library(qdapTools) mtabulate(df$var)
который дает,
источник
Преобразуйте свои данные в таблицу data.table и используйте набор по ссылке и фильтрацию строк
library(data.table) dt <- as.data.table(your.dataframe.or.whatever) dt[, is.1957 := 0] dt[year == 1957, is.1957 := 1]
Пример экспериментальной игрушки:
library(data.table) dt <- as.data.table(cbind(c(1, 1, 1), c(2, 2, 3))) dt[, is.3 := 0] dt[V2 == 3, is.3 := 1]
источник
Этот лайнер в базе R
model.matrix( ~ iris$Species - 1)
дает
iris$Speciessetosa iris$Speciesversicolor iris$Speciesvirginica 1 1 0 0 2 1 0 0 3 1 0 0 4 1 0 0 5 1 0 0 6 1 0 0 7 1 0 0 8 1 0 0 9 1 0 0 10 1 0 0 11 1 0 0 12 1 0 0 13 1 0 0 14 1 0 0 15 1 0 0 16 1 0 0 17 1 0 0 18 1 0 0 19 1 0 0 20 1 0 0 21 1 0 0 22 1 0 0 23 1 0 0 24 1 0 0 25 1 0 0 26 1 0 0 27 1 0 0 28 1 0 0 29 1 0 0 30 1 0 0 31 1 0 0 32 1 0 0 33 1 0 0 34 1 0 0 35 1 0 0 36 1 0 0 37 1 0 0 38 1 0 0 39 1 0 0 40 1 0 0 41 1 0 0 42 1 0 0 43 1 0 0 44 1 0 0 45 1 0 0 46 1 0 0 47 1 0 0 48 1 0 0 49 1 0 0 50 1 0 0 51 0 1 0 52 0 1 0 53 0 1 0 54 0 1 0 55 0 1 0 56 0 1 0 57 0 1 0 58 0 1 0 59 0 1 0 60 0 1 0 61 0 1 0 62 0 1 0 63 0 1 0 64 0 1 0 65 0 1 0 66 0 1 0 67 0 1 0 68 0 1 0 69 0 1 0 70 0 1 0 71 0 1 0 72 0 1 0 73 0 1 0 74 0 1 0 75 0 1 0 76 0 1 0 77 0 1 0 78 0 1 0 79 0 1 0 80 0 1 0 81 0 1 0 82 0 1 0 83 0 1 0 84 0 1 0 85 0 1 0 86 0 1 0 87 0 1 0 88 0 1 0 89 0 1 0 90 0 1 0 91 0 1 0 92 0 1 0 93 0 1 0 94 0 1 0 95 0 1 0 96 0 1 0 97 0 1 0 98 0 1 0 99 0 1 0 100 0 1 0 101 0 0 1 102 0 0 1 103 0 0 1 104 0 0 1 105 0 0 1 106 0 0 1 107 0 0 1 108 0 0 1 109 0 0 1 110 0 0 1 111 0 0 1 112 0 0 1 113 0 0 1 114 0 0 1 115 0 0 1 116 0 0 1 117 0 0 1 118 0 0 1 119 0 0 1 120 0 0 1 121 0 0 1 122 0 0 1 123 0 0 1 124 0 0 1 125 0 0 1 126 0 0 1 127 0 0 1 128 0 0 1 129 0 0 1 130 0 0 1 131 0 0 1 132 0 0 1 133 0 0 1 134 0 0 1 135 0 0 1 136 0 0 1 137 0 0 1 138 0 0 1 139 0 0 1 140 0 0 1 141 0 0 1 142 0 0 1 143 0 0 1 144 0 0 1 145 0 0 1 146 0 0 1 147 0 0 1 148 0 0 1 149 0 0 1 150 0 0 1
источник
Я использую такую функцию (для data.table):
# Ta funkcja dla obiektu data.table i zmiennej var.name typu factor tworzy dummy variables o nazwach "var.name: (level1)" factorToDummy <- function(dtable, var.name){ stopifnot(is.data.table(dtable)) stopifnot(var.name %in% names(dtable)) stopifnot(is.factor(dtable[, get(var.name)])) dtable[, paste0(var.name,": ",levels(get(var.name)))] -> new.names dtable[, (new.names) := transpose(lapply(get(var.name), FUN = function(x){x == levels(get(var.name))})) ] cat(paste("\nDodano zmienne dummy: ", paste0(new.names, collapse = ", "))) }
Применение:
data <- data.table(data) data[, x:= droplevels(x)] factorToDummy(data, "x")
источник
Другой способ сделать это - использовать
ifelse(year < 1965 , 1, 0)
источник
Привет, я написал эту общую функцию для создания фиктивной переменной, которая по сути копирует функцию замены в Stata.
Если x - это фрейм данных, это x, и я хочу, чтобы вызывалась фиктивная переменная,
a
которая будет принимать значение,1
когдаx$b
принимает значениеc
introducedummy<-function(x,a,b,c){ g<-c(a,b,c) n<-nrow(x) newcol<-g[1] p<-colnames(x) p2<-c(p,newcol) new1<-numeric(n) state<-x[,g[2]] interest<-g[3] for(i in 1:n){ if(state[i]==interest){ new1[i]=1 } else{ new1[i]=0 } } x$added<-new1 colnames(x)<-p2 x }
источник
Мы также можем использовать
cSplit_e
fromsplitstackshape
. Использование данных @ zx8754df1 <- data.frame(id = 1:4, year = 1991:1994) splitstackshape::cSplit_e(df1, "year", fill = 0) # id year year_1 year_2 year_3 year_4 #1 1 1991 1 0 0 0 #2 2 1992 0 1 0 0 #3 3 1993 0 0 1 0 #4 4 1994 0 0 0 1
Для того, чтобы заставить его работать на других , чем числовом нам нужно указать данные
type
в"character"
явном видеdf1 <- data.frame(id = 1:4, let = LETTERS[1:4]) splitstackshape::cSplit_e(df1, "let", fill = 0, type = "character") # id let let_A let_B let_C let_D #1 1 A 1 0 0 0 #2 2 B 0 1 0 0 #3 3 C 0 0 1 0 #4 4 D 0 0 0 1
источник