Предварительные данные: этот вопрос в основном имеет образовательное значение, фактическая задача выполнена, даже если подход не является полностью оптимальным. Мой вопрос: нижеприведенный код может быть оптимизирован для скорости и/или реализован более элегантно. Возможно использование дополнительных пакетов, таких как plyr или reshape. Выполнение фактических данных занимает около 140 секунд, что намного выше, чем моделируемые данные, так как некоторые из исходных строк содержат ничего, кроме NA, и необходимо выполнить дополнительные проверки. Для сравнения, смоделированные данные обрабатываются примерно через 30 секунд.Оптимизация: разделение данных в списке данных, преобразование данных в строку
Условия: набор данных содержит 360 переменных, в 30 раз набор 12. Давайте назовем их V1_1, V1_2 ... (первый набор), V2_1, V2_2 ... (второй набор) и так далее. Каждый набор из 12 переменных содержит дихотомические ответы (да/нет), на практике соответствующие статусу карьеры. Например: работа (да/нет), исследование (да/нет) и т. Д., Всего 12 статусов, повторяющихся 30 раз.
Задача: задача состоит в том, чтобы перекодировать каждый набор из 12 дихотомических переменных в одну переменную с 12 категориями ответа (например, работа, исследование ...). В конечном итоге мы должны получить 30 переменных, каждый из которых имеет 12 категорий ответов.
данных: Я не могу отправить фактический набор данных, но здесь хорошо моделируемой приближение:
randomRow <- function() {
# make a row with a single 1 and some NA's
sample(x=c(rep(0,9),1,NA,NA),size=12,replace=F)
}
# create a data frame with 12 variables and 1500 cases
makeDf <- function() {
data <- matrix(NA,ncol=12,nrow=1500)
for (i in 1:1500) {
data[i,] <- randomRow()
}
return(data)
}
mydata <- NULL
# combine 30 of these dataframes horizontally
for (i in 1:30) {
mydata <- cbind(mydata,makeDf())
}
mydata <- as.data.frame(mydata) # example data ready
Мое решение:
# Divide the dataset into a list with 30 dataframes, each with 12 variables
S1 <- lapply(1:30,function(i) {
Z <- rep(1:30,each=12) # define selection vector
mydata[Z==i] # use selection vector to get groups of variables (x12)
})
recodeDf <- function(df) {
result <- as.numeric(apply(df,1,function(x) {
if (any(!is.na(df))) which(x == 1) else NA # return the position of "1" per row
})) # the if/else check is for the real data
return(result)
}
# Combine individual position vectors into a dataframe
final.df <- as.data.frame(do.call(cbind,lapply(S1,recodeDf)))
В общем, есть двойная * применить функцию, одну по списку, другую по строкам данных. Это делает его немного медленным. Какие-либо предложения? Заранее спасибо.
(+1) Очень красиво оформленный вопрос. – Arun