Разделение свернутого столбца на несколько строк с сохранением информации о группировке

У меня есть беспорядочная таблица, которую я считываю в фрейм данных, похожий на следующую упрощенную таблицу, которую я хочу проанализировать.

mydf <- data.frame(group=LETTERS[1:5], code=101:105, ids=c('g1:id1,id2,id3\ng2:id4,id5',
                                                           'id6,id7,id8,id9',
                                                           'g1:id10,id11\ng3:id12',
                                                           'g2:id13,id14',
                                                           'id15'))

Это выглядит так:

> mydf
  group code                        ids
1     A  101 g1:id1,id2,id3\ng2:id4,id5
2     B  102            id6,id7,id8,id9
3     C  103      g1:id10,id11\ng3:id12
4     D  104               g2:id13,id14
5     E  105                       id15

Мне нужно разделить свернутый столбец ids на несколько строк, чтобы получить окончательный фрейм данных в длинном формате.

Для этого я бы обычно применял separate_rows из tidyr, но в этом случае есть дополнительная проблема: некоторые из свернутых ids сгруппированы в подгруппы.

Думаю, мне следует сначала разделить эти подгруппы на разные столбцы идентификаторов, а затем применить separate_rows или separate_longer_delim к этим столбцам... Я не знаю, как это сделать.

Окончательный фрейм данных, как я ожидаю, будет таким, в длинном формате, с информацией subgroup в дополнительном столбце:

> mydf_new
   group code   id subgroup
1      A  101  id1       g1
2      A  101  id2       g1
3      A  101  id3       g1
4      A  101  id4       g2
5      A  101  id5       g2
6      B  102  id6     <NA>
7      B  102  id7     <NA>
8      B  102  id8     <NA>
9      B  102  id9     <NA>
10     C  103 id10       g1
11     C  103 id11       g1
12     C  103 id12       g3
13     D  104 id13       g2
14     D  104 id14       g2
15     E  105 id15     <NA>
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Один из способов — разделить шире/длиннее на несколько шагов:

library(tidyr)
library(dplyr)

mydf |> 
  separate_longer_delim(ids, "\n") |> 
  separate_wider_delim(ids, ":", names = c("subgroup", "id"), too_few = "align_end") |> 
  separate_longer_delim(id, ",") |> 
  relocate(subgroup, .after = last_col())

# A tibble: 15 × 4
   group  code id    subgroup
   <chr> <int> <chr> <chr>   
 1 A       101 id1   g1      
 2 A       101 id2   g1      
 3 A       101 id3   g1      
 4 A       101 id4   g2      
 5 A       101 id5   g2      
 6 B       102 id6   NA      
 7 B       102 id7   NA      
 8 B       102 id8   NA      
 9 B       102 id9   NA      
10 C       103 id10  g1      
11 C       103 id11  g1      
12 C       103 id12  g3      
13 D       104 id13  g2      
14 D       104 id14  g2      
15 E       105 id15  NA    

это идеально спасибо!

DaniCee 30.08.2024 03:56

Это может включать в себя некоторые настройки, которые вы можете использовать для разработки более краткой базовой версии R, если хотите:

id = read.table(text=mydf$ids, sep = "\n", header=FALSE)
g = sub("\\:.*", "", id$V1); g[nchar(g)>2L]=NA
cbind(mydf[-3L][rep(seq(nrow(mydf)), sapply(mydf$ids, \(x) sum(utf8ToInt(x)==utf8ToInt("i")))), ], 
      id=unlist(i<-strsplit(sub(".*\\:", "", id$V1), ",")), 
      subgroup=rep(g, lengths(i)))

предоставление

    group code   id subgroup
1       A  101  id1       g1
1.1     A  101  id2       g1
1.2     A  101  id3       g1
1.3     A  101  id4       g2
1.4     A  101  id5       g2
2       B  102  id6     <NA>
2.1     B  102  id7     <NA>
2.2     B  102  id8     <NA>
2.3     B  102  id9     <NA>
3       C  103 id10       g1
3.1     C  103 id11       g1
3.2     C  103 id12       g3
4       D  104 id13       g2
4.1     D  104 id14       g2
5       E  105 id15     <NA>

Другие вопросы по теме