Как сравнить значение вектора в кадре данных с константой в R?

Предыстория: я использую некоторые образцы микроданных общественного пользования переписи (в частности, исследование американского сообщества) за несколько лет, чтобы изучить поведение людей, получивших разные степени (например, диплом средней школы, степень бакалавра, степень магистра). Переменная с этим файлом общего пользования называется Schooling. Проблема в том, что коды, содержащиеся в переменной Schooling, менялись из года в год. Например, для файлов до 2007 года значение 13 отражает получение степени бакалавра, но начиная с 2008 года значение изменяется на 21, когда кто-то получил степень бакалавра.

Цель: создать новую переменную Degree Competed, которая переводит коды обучения, чтобы отразить полученный уровень с учетом года файла. Логистика: файлы за все годы были объединены, и для целей обзора я должен работать с файлом как есть, а не исправлять его, прежде чем он дойдет до этого момента.

Существующий код: вот что я пробовал.

if      (original.file$year %in% c(2000,2001)) {
    if      (original.file$Schooling <= 08) {original.file$degree.completed <- 0}
    else if (original.file$Schooling <= 10) {original.file$degree.completed <- 1}
    else if (original.file$Schooling <= 12) {original.file$degree.completed <- 2}
    else if (original.file$Schooling == 13) {original.file$degree.completed <- 3}
    else if (original.file$Schooling == 14) {original.file$degree.completed <- 4}
    else if (original.file$Schooling == 15) {original.file$degree.completed <- 5}
    else if (original.file$Schooling == 16) {original.file$degree.completed <- 6}
    }
else if (original.file$year %in% c(2002,2003,2004,2005,2006,2007)) {
    if      (original.file$Schooling <= 08) {original.file$degree.completed <- 0}
    else if (original.file$Schooling <= 11) {original.file$degree.completed <- 1}
    else if (original.file$Schooling == 12) {original.file$degree.completed <- 2}
    else if (original.file$Schooling == 13) {original.file$degree.completed <- 3}
    else if (original.file$Schooling == 14) {original.file$degree.completed <- 4}
    else if (original.file$Schooling == 15) {original.file$degree.completed <- 5}
    else if (original.file$Schooling == 16) {original.file$degree.completed <- 6}
    }
else if (original.file$year %in% c(2008,2009,2010,2011)) {
    if      (original.file$Schooling <= 15) {original.file$degree.completed <- 0}
    else if (original.file$Schooling <= 19) {original.file$degree.completed <- 1}
    else if (original.file$Schooling == 20) {original.file$degree.completed <- 2}
    else if (original.file$Schooling == 21) {original.file$degree.completed <- 3}
    else if (original.file$Schooling == 22) {original.file$degree.completed <- 4}
    else if (original.file$Schooling == 23) {original.file$degree.completed <- 5}
    else if (original.file$Schooling == 24) {original.file$degree.completed <- 6}
    }

Проблема: я получаю следующие предупреждающие сообщения этого типа.

Предупреждающие сообщения:

1: В if (original.file $ year% в% c (2000, 2001)) {: длина условия ›1 и будет использоваться только первый элемент

2: В if (original.file $ Schooling ‹= 8) {: длина условия› 1 и будет использоваться только первый элемент

3: В if (original.file $ Schooling ‹= 10) {: длина условия› 1 и будет использоваться только первый элемент

Вопрос: Я знаю, что здесь есть проблема вектора и скаляра с if, как я видел из других вопросов по StackOverflow, но ответы, похоже, не применимы к этой ситуации. Какое здесь решение?


person Jeff the Demographic Economist    schedule 31.01.2013    source источник
comment
if действует на одно логическое значение. вместо этого вы можете использовать ifelse, который действует на векторы, но не подходит для этого. Вы также можете использовать логические условия и подмножества. Что-то вроде dat$degree[dat$year %in% 2000:2001 & dat$schooling <= 8] <- 0.   -  person Justin    schedule 31.01.2013


Ответы (2)


Во-первых, используйте cut или table вместо всех этих if и else:

CutOffs1 <- c(0,8,10,12,13,14,15,16)
CutOffs2 <- c(0,8,11,12,13,14,15,16)
CutOffs3 <- c(0,15,19,20,21,22,23,24)
CutOffs <- cbind(CutOffs1, CutOffs2, CutOffs3)
MyTable <- apply(CutOffs, 2, function(X) cut(1:24, X, FALSE)-1)

      CutOffs1 CutOffs2 CutOffs3
 [1,]        0        0        0
 [2,]        0        0        0
 [3,]        0        0        0
 [4,]        0        0        0
 [5,]        0        0        0
 [6,]        0        0        0
 [7,]        0        0        0
 [8,]        0        0        0
 [9,]        1        1        0
[10,]        1        1        0
[11,]        2        1        0
[12,]        2        2        0
[13,]        3        3        0
[14,]        4        4        0
[15,]        5        5        0
[16,]        6        6        1
[17,]       NA       NA        1
[18,]       NA       NA        1
[19,]       NA       NA        1
[20,]       NA       NA        2
[21,]       NA       NA        3
[22,]       NA       NA        4
[23,]       NA       NA        5
[24,]       NA       NA        6

Вы также захотите cut годы на факторы.

original.file$Period <- cut(original.file$year, c(2000,2001, 2007, 2011), FALSE,   
                            include.lowest=TRUE) 
## To demonstrate:
    > cbind(2000:2011, cut(2000:2011, c(2000,2001, 2007, 2011), FALSE,   
+     include.lowest=TRUE))
      [,1] [,2]
 [1,] 2000    1
 [2,] 2001    1
 [3,] 2002    2
 [4,] 2003    2
 [5,] 2004    2
 [6,] 2005    2
 [7,] 2006    2
 [8,] 2007    2
 [9,] 2008    3
[10,] 2009    3
[11,] 2010    3
[12,] 2011    3

Тогда вы сможете:

Degrees <- apply(original.file, 1, function(X) MyTable[X['Schooling'], X['Period']])
person Señor O    schedule 31.01.2013
comment
В исходных данных есть некоторые НА. Как бы они были решены в отсечках? - person Jeff the Demographic Economist; 01.02.2013
comment
Они также должны приводить к NA, хотя, если они являются NA, у вас нет возможности узнать, какой уровень в школе кто-то получил, поэтому вам лучше избавиться от них или создать отдельный подмножество ценностей, отличных от NA. - person Señor O; 01.02.2013

Престижность Джастину за решение:

if действует с одним логическим значением. вместо этого вы можете использовать ifelse, который действует с векторами, но не подходит для этого. Вы также можете использовать логические условия и подмножества. Что-то вроде dat $ degree [dat $ year% в% 2000: 2001 & dat $ schooling ‹= 8]‹ - 0. - Джастин

Окончательное решение потребовало одной корректировки: поскольку это не оператор if-then-else и есть несколько операторов, структура типа «‹ = 8 »не будет работать, потому что последующие операторы заменят это. Например, если в следующей строке указано «...‹ = 10] ‹- 1, то все нули будут заменены на единицу после вызова этой строки и т. Д. Вместо этого« ‹= 8» должно быть переведены в оператор% in% c (1: 8), и необходимо позаботиться о том, чтобы все операторы if-like были взаимоисключающими, чтобы избежать переопределения предыдущих присвоений.

person Jeff the Demographic Economist    schedule 31.01.2013