R: Какая структура табличных данных наиболее удобна для того, чтобы построить регрессионную модель [особый случай]?
Есть следующие сырые данные, на основании которых необходимо построить регрессионные модели. В качестве независимых переменных выступают элементы столбца ind_name.
Очевидно, что таблицу нужно сделать "широкой", это получается сделать с помощью pivot_wider. Однако после приведения таблицы в широкий формат, где столбцами являются элементы ind_name, данные становятся вложенными (nested). То есть в ячейке не один элемент, а вектор элементов.
sample <- readxl::read_xlsx("original.xlsx")
s <- sample[1:1000,]
s <- s %>%
pivot_wider(id_cols = seance_id,
names_from = ind_name,
values_from = criteria_answ) %>%
print(head(10))
# A tibble: 84 x 6
seance_id name2 name1 name3 name5 name4
<chr> <list> <list> <list> <list> <list>
1 3133688 <chr [2]> <chr [2]> <chr [2]> <chr [1]> <NULL>
2 3145092 <chr [4]> <chr [4]> <chr [4]> <chr [1]> <chr [4]>
3 3143656 <chr [1]> <chr [1]> <chr [1]> <chr [1]> <chr [1]>
4 3145088 <chr [3]> <chr [3]> <chr [3]> <chr [1]> <chr [3]>
5 3145117 <chr [3]> <chr [3]> <chr [3]> <chr [1]> <chr [3]>
6 3148589 <chr [3]> <chr [3]> <chr [3]> <chr [1]> <chr [3]>
7 3135731 <chr [3]> <chr [3]> <chr [3]> <chr [1]> <chr [3]>
8 3145111 <chr [5]> <chr [5]> <chr [5]> <chr [1]> <chr [5]>
9 3149981 <chr [4]> <chr [4]> <chr [4]> <chr [1]> <chr [4]>
10 3150048 <chr [1]> <chr [1]> <chr [1]> <chr [1]> <chr [1]>
# ... with 74 more rows
Если к полученному результату применить функцию unnest(cols = everything()) или unchop с аналогичными атрибутами, то происходит ошибка:
Ошибка: Incompatible lengths: 4, 5.
Run `rlang::last_error()` to see where the error occurred.
То есть из-за разной длины вложенных векторов (а где-то данные и не вложены, а просто представлены в нормальном виде) функция не может "разложить" листы в ячейках.
Вопрос: как привести данные в нормальный табличный вид, пригодный для того, чтобы на их основании можно было построить регрессионные модели? Как пример "нормального" вида:
seance_id name1 name2
<dbl> <dbl> <dbl>
1 1 0.396 -0.379
2 1 -0.000982 0.160
3 2 -1.03 0.700
4 2 -1.06 0.208
5 2 0.320 -0.568
Возможно, есть другой способ представить такого типа данные для построения регрессионной модели? На английском сегменте SO я не нашел решения.
Ответы (1 шт):
наблюдения превращаются в список из-за того, что в желаемом вами представлении, где строками являются уникальные значения лишь первой переменной (а в самих данных уникальными являются значения пары переменных), получаются множественные наблюдения, которые надо поместить в одну ячейку.
посмотрите на данные. например, для наблюдения, где seance_id == "3133688", в столбец с именем name1 должны попасть и "7" и "6":
таблица <- readxl::read_xlsx("/tmp/rxl/original.xlsx")
таблица[таблица$seance_id == "3133688" & таблица$ind_name == "name1",]
#> # A tibble: 2 x 4
#> seance_id criteria ind_name criteria_answ
#> <chr> <chr> <chr> <chr>
#> 1 3133688 ind3_3 name1 7
#> 2 3133688 ind4_3 name1 6
собственно, сама функция pivot_wider() при таком использовании вам и подсказывает, что можно сделать:
таблица %>% pivot_wider(id_cols = seance_id, names_from = ind_name,
values_from = criteria_answ)
#> Warning: Values are not uniquely identified; output will contain list-cols.
#> * Use `values_fn = list` to suppress this warning.
#> * Use `values_fn = length` to identify where the duplicates arise
#> * Use `values_fn = {summary_fun}` to summarise duplicates
т.е., воспользоваться параметром values_fn, в котором можно передать функцию, которая и будет применена к таким наборам.
если передать название функции length(), то, как написано в предупреждении, можно будет увидеть длину получающихся списков с повторами:
таблица %>% pivot_wider(id_cols = seance_id, names_from = ind_name,
values_from = criteria_answ, values_fn = length)
#> # A tibble: 422 x 6
#> seance_id name2 name1 name3 name5 name4
#> <chr> <int> <int> <int> <int> <int>
#> 1 3133688 2 2 2 1 NA
#> 2 3145092 4 4 4 1 4
#> 3 3143656 1 1 1 1 1
#> 4 3145088 3 3 3 1 3
#> 5 3145117 3 3 3 1 3
#> 6 3148589 3 3 3 1 3
#> 7 3135731 3 3 3 1 3
#> 8 3145111 5 5 5 1 5
#> 9 3149981 4 4 4 1 4
#> 10 3150048 1 1 1 1 1
#> # … with 412 more rows
как видим, встречаются списки даже из пяти «повторов».
какую именно функцию следует применить — зависит уже от смысла ваших данных и цели, стоящей перед вами. например, можете взять среднее из этих значений (только предварительно придётся преобразовать последнюю переменную из строки в число, например, с помощью вызова mutate() и as.numeric()):
таблица %>% mutate(criteria_answ = as.numeric(criteria_answ))
%>% pivot_wider(id_cols = seance_id, names_from = ind_name,
values_from = criteria_answ, values_fn=mean)
#> # A tibble: 422 x 6
#> seance_id name2 name1 name3 name5 name4
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 3133688 6.5 6.5 6.5 5 NA
#> 2 3145092 5.5 6 5.75 3 6
#> 3 3143656 10 10 10 10 10
#> 4 3145088 9 8.67 8.67 8 9.67
#> 5 3145117 5.67 7.33 7.33 6 8.33
#> 6 3148589 9 8.33 7.33 9 9
#> 7 3135731 8.67 7.67 8 8 8.67
#> 8 3145111 7.6 9.2 8 4 8.4
#> 9 3149981 8 8.25 8 9 8.5
#> 10 3150048 9 10 10 10 9
#> # … with 412 more rows
Created on 2021-03-17 by the reprex package (v0.3.0)