Преобразование data.frame в список списков списков списков - PullRequest
0 голосов
/ 09 мая 2018

Я работаю с разными моделями, которые имеют разные параметры.Мне удобно хранить их в базе данных.Когда я их тяну, они приходят в виде кадра данных , который я называю df.

В df есть несколько столбцов, которые помогают дифференцировать каждый параметр друг от друга, так что каждая (вся) строка в конечном итоге уникальна.

Например,

col_1 <- c("model_1", "model_1", "model_1", "model_1", "model_2", "model_2", "model_2", "model_2")
col_2 <- c("category_1", "category_1", "category_2", "category_2", "category_1", "category_1", "category_2", "category_2")
col_3 <- c("type_1", "type_2", "type_1", "type_2", "type_1", "type_2", "type_1", "type_2")
col_4 <- c("name_1", "name_2", "name_3", "name_4", "name_5", "name_6", "name_7", "name_8")
col_5 <- c("value_1", "value_2", "value_3", "value_4", "value_5", "value_6", "value_7", "value_8")
mat <- matrix(c(col_1, col_2, col_3, col_4, col_5), ncol = 5)
df <- data.frame(mat)
names(df) <- c("model", "category", "type", "name", "value")

Мне было бы интересно преобразовать df в список списка списка ... - назовите его deep_list - так, чтобы каждый параметрзначение может быть доступно как

parameter <- deep_list$model_1$category_2$type_2$name_4

, и оно должно дать мне value_4.

Я читал эту тему Преобразование data.frame в списоксписков и пытался наилучшим образом использовать функцию dlply() из {plyr} как

not_deep_list <- dlply(df,1,c)

или также

not_list <- df %>% group_by(model)

Я считаю, что это очень похожая проблема (отсюда и похожий заголовок).

Однако отличается тем, что требует обработки большего количества "слоев" (то есть столбцов) информации, следовательноимя и заголовок deep_list ...

Приветствуются любые предложения (рекурсии, циклы, векторизованные решения, функции из пакетов, которые я никогда не слышал, ...)

Спасибо!

1 Ответ

0 голосов
/ 09 мая 2018

Во-первых, я указал stringsAsFactors=FALSE в вашем data.frame - это важно, поскольку я использую split(...), который распознает уровни факторов , а не значения факторов. Чтобы увидеть, что я имею в виду, запустите

vec <- factor(c("apple"), levels=c("apple","banana"))
split(vec, vec)

# $apple
# [1] apple
# Levels: apple banana
# $banana
# factor(0)
# Levels: apple banana

Хорошо, поэтому указание строк в качестве нефакторов

df <- data.frame(mat, stringsAsFactors=FALSE)

Попробуйте эту пользовательскую функцию - она ​​рекурсивна и вызывает себя, если length(split(..., ...)) > 1) - то есть, если split(...) столбца data.frame приводит к> 1 группе, функция будет вызывать себя, используя в качестве нового аргумента i[,-1].

recursive_split <- function(L) {
    L1 <- split(L, L[,1])
    if (length(L1) == 1) {
        L2 <- lapply(L1, function(i) i[,-1])
        return(L2)
    } else {
        lapply(L1, function(i) recursive_split(i[,-1])) 
    }
}

deep_list <- recursive_split(df)

# $model_1
# $model_1$category_1
# $model_1$category_1$type_1
# $model_1$category_1$type_1$name_1
# [1] "value_1"

# $model_1$category_1$type_2
# $model_1$category_1$type_2$name_2
# [1] "value_2"

# $model_1$category_2
# $model_1$category_2$type_1
# $model_1$category_2$type_1$name_3
# [1] "value_3"
# etc

deep_list$model_1$category_2$type_2$name_4
# [1] "value_4"
...