Поэтому я не уверен, что он удовлетворяет требованию «элегантности», но вот функция общего назначения, которую вы можете использовать для получения сбалансированных данных.
balanced<-function(data, ID, TIME, VARS, required=c("all","shared")) {
if(is.character(ID)) {
ID <- match(ID, names(data))
}
if(is.character(TIME)) {
TIME <- match(TIME, names(data))
}
if(missing(VARS)) {
VARS <- setdiff(1:ncol(data), c(ID,TIME))
} else if (is.character(VARS)) {
VARS <- match(VARS, names(data))
}
required <- match.arg(required)
idf <- do.call(interaction, c(data[, ID, drop=FALSE], drop=TRUE))
timef <- do.call(interaction, c(data[, TIME, drop=FALSE], drop=TRUE))
complete <- complete.cases(data[, VARS])
tbl <- table(idf[complete], timef[complete])
if (required=="all") {
keep <- which(rowSums(tbl==1)==ncol(tbl))
idx <- as.numeric(idf) %in% keep
} else if (required=="shared") {
keep <- which(colSums(tbl==1)==nrow(tbl))
idx <- as.numeric(timef) %in% keep
}
data[idx, ]
}
Вы можете получить желаемый результат с
balanced(unbal, "PERSON","YEAR")
# PERSON YEAR Y X
# 1 Frank 2001 21 1
# 2 Frank 2002 22 2
# 3 Frank 2003 23 3
# 4 Frank 2004 24 4
# 5 Frank 2005 25 5
# 11 Edward 2001 31 11
# 12 Edward 2002 32 12
# 13 Edward 2003 33 13
# 14 Edward 2004 34 14
# 15 Edward 2005 35 15
Первый параметр — это data.frame, который вы хотите подмножить. Второй параметр (ID=
) представляет собой вектор символов имен столбцов, которые идентифицируют каждого «человека» в наборе данных. Тогда параметр TIME=
также является вектором символов, определяющим различные времена наблюдения для каждого идентификатора. Наконец, вы можете дополнительно указать аргумент VARS=
, чтобы указать, какие поля должны быть NA (по умолчанию для всех значений, кроме значений ID или TIME). Наконец, есть последний параметр с именем required
, который указывает, должен ли каждый идентификатор иметь наблюдение для каждого ВРЕМЕНИ (по умолчанию), или если вы установите для него значение «общий», он будет возвращать только ВРЕМЯ, для которых все идентификаторы имеют неотсутствующие значения.
Так например
balanced(unbal, "PERSON","YEAR", "X")
# PERSON YEAR Y X
# 1 Frank 2001 21 1
# 2 Frank 2002 22 2
# 3 Frank 2003 23 3
# 4 Frank 2004 24 4
# 5 Frank 2005 25 5
# 6 Tony 2001 5 6
# 7 Tony 2002 6 7
# 8 Tony 2003 NA 8
# 9 Tony 2004 7 9
# 10 Tony 2005 8 10
# 11 Edward 2001 31 11
# 12 Edward 2002 32 12
# 13 Edward 2003 33 13
# 14 Edward 2004 34 14
# 15 Edward 2005 35 15
требуется только, чтобы «X» был NA для всех ЧЕЛОВЕК/ГОД, и, поскольку это верно для всех записей, дополнительная настройка не выполняется.
Если вы сделаете
balanced(unbal, "PERSON","YEAR", required="shared")
# PERSON YEAR Y X
# 1 Frank 2001 21 1
# 2 Frank 2002 22 2
# 4 Frank 2004 24 4
# 5 Frank 2005 25 5
# 6 Tony 2001 5 6
# 7 Tony 2002 6 7
# 9 Tony 2004 7 9
# 10 Tony 2005 8 10
# 11 Edward 2001 31 11
# 12 Edward 2002 32 12
# 14 Edward 2004 34 14
# 15 Edward 2005 35 15
затем вы получаете данные за 2001, 2002, 2004, 2005 годы для ВСЕХ лиц, поскольку все они имеют данные за эти годы.
Теперь давайте создадим немного другой пример набора данных.
unbal2 <- unbal
unbal2[15, 2] <- 2006
tail(unbal2)
# PERSON YEAR Y X
# 10 Tony 2005 8 10
# 11 Edward 2001 31 11
# 12 Edward 2002 32 12
# 13 Edward 2003 33 13
# 14 Edward 2004 34 14
# 15 Edward 2006 35 15
Обратите внимание, что Эдвард — единственный человек, у которого есть значение на 2006 год. Это означает, что
balanced(unbal2, "PERSON","YEAR")
# [1] PERSON YEAR Y X
# <0 rows> (or 0-length row.names)
теперь не возвращает ничего, кроме
balanced(unbal2, "PERSON","YEAR", required="shared")
# PERSON YEAR Y X
# 1 Frank 2001 21 1
# 2 Frank 2002 22 2
# 4 Frank 2004 24 4
# 6 Tony 2001 5 6
# 7 Tony 2002 6 7
# 9 Tony 2004 7 9
# 11 Edward 2001 31 11
# 12 Edward 2002 32 12
# 14 Edward 2004 34 14
вернет данные за 2001,2002, 2004 годы, т.к. у всех лиц есть данные за эти годы.
person
MrFlick
schedule
04.09.2014