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 шт):

Автор решения: aleksandr barakin

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

посмотрите на данные. например, для наблюдения, где 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)

→ Ссылка