Сгенерировать фиктивную переменную

У меня возникают проблемы с созданием следующих фиктивных переменных в R:

Я анализирую годовые данные временных рядов (период 1948-2009). У меня есть два вопроса:

  1. Как создать фиктивную переменную для наблюдения № 10, то есть за 1957 год (значение = 1 в 1957 году и ноль в противном случае)?

  2. Как создать фиктивную переменную, которая равна нулю до 1957 года и принимает значение 1 с 1957 года и далее до 2009 года?

Другой вариант, который может работать лучше, если у вас много переменных, это factor и model.matrix .

 > year.f = factor(year) > dummies = model.matrix(~year.f) 

Это будет включать столбец перехвата (все) и один столбец за каждый из лет в вашем наборе данных, кроме одного, который будет значением «по умолчанию» или перехватом.

Вы можете изменить способ выбора «по умолчанию», model.matrix с contrasts.arg в model.matrix .

Кроме того, если вы хотите опустить перехват, вы можете просто удалить первый столбец или добавить +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) .

Использование манекенов :: 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

То, что я обычно делаю для работы с такими фиктивными переменными, является:

(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 :

 summary ( lm ( y ~ t, data = data ) ) 

Надеюсь это поможет!

Другие ответы здесь предлагают прямые маршруты для выполнения этой задачи – так, что многие модели (например, lm ) будут делать для вас внутренне в любом случае. Тем не менее, вот способы сделать фиктивные переменные с популярными пакетами и recipes Макса Куна. В то время как несколько более подробные, они оба легко масштабируются в более сложных ситуациях и аккуратно вписываются в их соответствующие frameworks.


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.cy #> 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 #>    #> 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 #>    #> 1 1 0 0 #> 2 2 0 0 #> 3 3 1 0 #> 4 4 1 0 #> 5 5 0 1 #> 6 6 0 1 

Я прочитал это на форуме 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) } 

Если вы хотите получить K фиктивных переменных вместо K-1, попробуйте:

 dummies = table(1:length(year),as.factor(year)) 

Лучший,

Для usecase, представленного в вопросе, вы также можете просто умножить логическое условие на 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) 

который дает:

 > df1 yr is.1957 after.1957 1 1951 0 0 2 1952 0 0 3 1953 0 0 4 1954 0 0 5 1955 0 0 6 1956 0 0 7 1957 1 1 8 1958 0 1 9 1959 0 1 10 1960 0 1 

Для usecases, как представлено, например, в ответах @ 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')) 

который дает:

  id year y1991 y1992 y1993 y1994 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 5 5 1992 0 1 0 0 

2) используйте dcast из таблицы data.table или reshape2

  dcast(df2, id + year ~ year, fun.aggregate = length) 

который дает:

  id year 1991 1992 1993 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 5 5 1992 0 1 0 0 

Однако это не будет работать, если в столбце, в котором должны быть созданы макеты, есть повторяющиеся значения. В случае, когда для dcast требуется конкретная функция 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 столбцом):

  var ABC 1 A 1 0 0 2 B 0 1 0 3 B 0 1 0 4 C 0 0 1 5 C 0 0 1 

3) использовать spread функцию от tidyr (с мутатом от dplyr )

 library(dplyr) library(tidyr) df2 %>% mutate(v = 1, yr = year) %>% spread(yr, v, fill = 0) 

который дает:

  id year 1991 1992 1993 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 5 5 1992 0 1 0 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 , т. 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) 

который дает,

  ABC 1 0 0 1 2 1 0 0 3 0 0 1 4 0 1 0 5 0 1 0 

Я использую такую ​​функцию (для 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") 

Преобразуйте свои данные в таблицу data.table и используйте set by reference и row filtering

 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] 

Привет, я написал эту общую функцию для создания фиктивной переменной, которая по существу реплицирует функцию замены в 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 } 

другим способом, которым вы можете это сделать, является использование

 ifelse(year < 1965 , 1, 0) 
  • dplyr - mutate: использовать имена динамических переменных
  • Создайте пустой файл data.frame
  • Перестановка множества наборов измерительных столбцов (широкий формат) в отдельные столбцы (длинный формат)
  • Раунд вверх от .5
  • Почему операторы R if ifsese не возвращают векторы?
  • Вставить несколько столбцов вместе
  • Уровни фактора падения в подмножестве данных
  • Удаление столбцов фрейма данных по имени
  • Ошибка в : цель присвоения расширяется до неязыкового объекта
  • Условное слияние / замена в R
  • Почему объекты R не печатаются в функции или в цикле «для»?
  • Давайте будем гением компьютера.