У меня есть следующий фрейм данных.
Data_Frame <- data.frame(Factor_1 = rep(LETTERS[1:4], each = 12, length.out = 48), Factor_2 = rep(letters[1:3], each = 4, length.out = 48), Factor_3 = rep(1:2, each = 2, length.out = 48), Response = rnorm(48, 25, 1))
Я хочу создать вложенный список, в котором я последовательно разделю фрейм данных по каждому из факторов исследования. Я начну с вектора, содержащего имена столбцов, которые содержат факторы, по которым я хочу разделить фрейм данных (этот вектор будет содержать факторы в том порядке, в котором я хочу, чтобы результирующий список был вложен).
Factors_to_Split_by <- c("Factor_1", "Factor_2", "Factor_3")
Результирующий список должен выглядеть как следующий объект Output
.
Output <- lapply(lapply(split(Data_Frame, Data_Frame[, which(colnames(Data_Frame) == Factors_to_Split_by[1])]), function (x) {
split(x, x[, which(colnames(x) == Factors_to_Split_by[2])])
}), function (x) {
lapply(x, function (y) {
split(y, y[, which(colnames(y) == Factors_to_Split_by[3])])
})
})
Как я могу написать рекурсивную функцию, используя Factors_to_Split_by
в качестве входных данных и возвращая желаемый список Output
в качестве выходных данных? У меня может быть более трех факторов для разделения данных, и мне нужно что-то модульное, эффективное и программируемое.
Спасибо!
@IfeaNYIdiaye — код, генерирующий желаемый объект Output
, уже включен автором.
Вот один из возможных подходов с использованием Reduce
и пользовательской функции:
split_df <- function(x, split) {
if (is.data.frame(x)) {
split(x, x[split])
} else {
lapply(x, split_df, split = split)
}
}
Output2 <- Reduce(split_df, Factors_to_Split_by, init = Data_Frame)
identical(Output, Output2)
#> [1] TRUE
Красивый код с Reduce
, ура!
Вы можете определить рекурсивную функцию следующим образом
f <- function(data, fct) {
if (length(fct) == 1) split(data, data[fct])
lapply(split(data, data[fct[1]]), f, fct = fct[-1])
}
такой, что
> f(Data_Frame, Factors_to_Split_by)
$A
$A$a
$A$a$`1`
Factor_1 Factor_2 Factor_3 Response
1 A a 1 25.91996
2 A a 1 25.12079
$A$a$`2`
Factor_1 Factor_2 Factor_3 Response
3 A a 2 24.88218
4 A a 2 24.77660
$A$b
$A$b$`1`
Factor_1 Factor_2 Factor_3 Response
5 A b 1 25.63426
6 A b 1 24.64074
$A$b$`2`
Factor_1 Factor_2 Factor_3 Response
7 A b 2 26.60224
8 A b 2 25.17982
$A$c
$A$c$`1`
Factor_1 Factor_2 Factor_3 Response
9 A c 1 24.90249
10 A c 1 26.12602
$A$c$`2`
Factor_1 Factor_2 Factor_3 Response
11 A c 2 25.87801
12 A c 2 24.82886
$B
$B$a
$B$a$`1`
Factor_1 Factor_2 Factor_3 Response
13 B a 1 25.29955
14 B a 1 24.74579
$B$a$`2`
Factor_1 Factor_2 Factor_3 Response
15 B a 2 25.06018
16 B a 2 27.33450
$B$b
$B$b$`1`
Factor_1 Factor_2 Factor_3 Response
17 B b 1 25.78050
18 B b 1 24.96464
$B$b$`2`
Factor_1 Factor_2 Factor_3 Response
19 B b 2 24.04945
20 B b 2 23.52038
$B$c
$B$c$`1`
Factor_1 Factor_2 Factor_3 Response
21 B c 1 25.68414
22 B c 1 25.25209
$B$c$`2`
Factor_1 Factor_2 Factor_3 Response
23 B c 2 24.32218
24 B c 2 25.81953
$C
$C$a
$C$a$`1`
Factor_1 Factor_2 Factor_3 Response
25 C a 1 23.61297
26 C a 1 25.52444
$C$a$`2`
Factor_1 Factor_2 Factor_3 Response
27 C a 2 27.80018
28 C a 2 24.85324
$C$b
$C$b$`1`
Factor_1 Factor_2 Factor_3 Response
29 C b 1 24.63975
30 C b 1 23.95888
$C$b$`2`
Factor_1 Factor_2 Factor_3 Response
31 C b 2 24.93261
32 C b 2 23.85798
$C$c
$C$c$`1`
Factor_1 Factor_2 Factor_3 Response
33 C c 1 25.29823
34 C c 1 25.16727
$C$c$`2`
Factor_1 Factor_2 Factor_3 Response
35 C c 2 25.36553
36 C c 2 24.99169
$D
$D$a
$D$a$`1`
Factor_1 Factor_2 Factor_3 Response
37 D a 1 24.53971
38 D a 1 24.72733
$D$a$`2`
Factor_1 Factor_2 Factor_3 Response
39 D a 2 25.74960
40 D a 2 24.56601
$D$b
$D$b$`1`
Factor_1 Factor_2 Factor_3 Response
41 D b 1 22.72847
42 D b 1 24.29836
$D$b$`2`
Factor_1 Factor_2 Factor_3 Response
43 D b 2 24.69552
44 D b 2 23.77094
$D$c
$D$c$`1`
Factor_1 Factor_2 Factor_3 Response
45 D c 1 24.07517
46 D c 1 26.21868
$D$c$`2`
Factor_1 Factor_2 Factor_3 Response
47 D c 2 26.46018
48 D c 2 24.44250
Как должен выглядеть вложенный список? Можете ли вы включить желаемый результат в свой вопрос?