Преобразование данных из длинного в широкий формат

Я ищу быстрый способ преобразования данных из длинного в широкий формат. Прямо сейчас я попробовал код с гнездом для циклов, хотя работа выполнена, для создания вывода требуется много времени.

SN NN EE Service_tier
A  B  C  economy
B  C  C  economy
P  Q  R  regular
Q  S  R  regular
S  R  R  regular
H  I  L  economy
I  J  L  economy
J  K  L  economy
K  L  L  economy

Ожидаемый результат, как показано ниже

SN hop1 hop2 hop3 hop4 service_tier
A   B    C              economy
P   Q    S    R         regular
H   I    J    K    L    economy

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

for (i in 1:lasrow){
  sn <- raw_d[i,1]
  nn <- raw_d[i,2]
  en <- raw_d[i,3]

  lc <- 1

  if (nn == en){
    d[lr,lc]<-sn
    d[lr,lc+1]<-nn
    d[lr,lc+2]<-en
    lr <- lr+1
  }
  else{
    while(nn!=en){
      d[lr,lc]<-sn
      lc <- lc+1
      next_d <- filter(raw_d,raw_d$SN==sn,raw_d$EN==en)
      if (dim(next_d)[1]==0){
        d[lr,lc]<-"broken bf"
        lc <- lc+1
        break
      }else{
        sn <- next_d$NN
        nn <- next_d$NN
        }
      }
    d[lr,lc]<-en
    lr<-lr+1
  }
}

Кажется, что ваши наборы являются взаимоисключающими, например, регулярный = {P, Q, R, S}, но P, Q, R и S не являются частью никакого другого «набора». Всегда ли это будет правдой? Может ли «А» когда-либо быть частью обычного и эконом-класса? Правильный метод расширения этих данных будет зависеть от вашего ответа.

Marian Minar 30.05.2019 06:20

экономика = {P, Q, R, S} может появиться и в экономике, но для заданных P и S у нас будет только один путь, а не несколько путей.

Vasuki Rao 30.05.2019 07:47
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
194
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Один из вариантов — создать уникальную последовательность, используя rleid из data.table, gather фрейм данных в длинном формате, удалить дубликаты из каждой группы, назначить имена столбцов и spread вернуть их в широкий формат.

library(dplyr)
library(tidyr)

df %>%
  mutate(row = data.table::rleid(Service_tier)) %>%
  gather(key, value, -Service_tier, -row) %>%
  group_by(row) %>%
  filter(!duplicated(value)) %>%
  mutate(key = c("SN", paste0("hop", 1:(n() - 1)))) %>%
  spread(key, value) %>%
  ungroup() %>%
  select(-row) %>%
  select(SN, starts_with("hop"), Service_tier)

# A tibble: 3 x 6
#  SN    hop1  hop2  hop3  hop4  Service_tier
#  <chr> <chr> <chr> <chr> <chr> <fct>       
#1  A     B     C     NA    NA    economy     
#2  H     I     J     K     L     economy     
#3  P     Q     S     R     NA    regular    

Мы можем использовать data.table. Преобразуйте «data.frame» в «dat.table» (setDT(df1), сгруппированный по rleid на «Service_tier», измените значение «SN» на first элемент, сгруппированный по «grp», затем сгруппированный по «Service_tier», «SN ', получить элемент unique Subset of Data.table и dcast из «длинного» в «широкий» формат

library(data.table)
dcast(setDT(df1)[, SN := first(SN), rleid(Service_tier)][, 
    unique(unlist(.SD)), .(SN, Service_tier)], 
    SN + Service_tier ~ paste0("hop", rowid(SN)), value.var = "V1", fill = "")
#  SN Service_tier hop1 hop2 hop3 hop4
#1:  A      economy    B    C          
#2:  H      economy    I    J    K    L
#3:  P      regular    Q    S    R     

данные

df1 <- structure(list(SN = c("A", "B", "P", "Q", "S", "H", "I", "J", 
"K"), NN = c("B", "C", "Q", "S", "R", "I", "J", "K", "L"), EE = c("C", 
"C", "R", "R", "R", "L", "L", "L", "L"), Service_tier = c("economy", 
"economy", "regular", "regular", "regular", "economy", "economy", 
"economy", "economy")), class = "data.frame", row.names = c(NA, 
-9L))
Ответ принят как подходящий

Важным моментом здесь является определение того, какие строки принадлежат к какой группе. В ответах Ронак и Акрун используется rleid(Service_tier), предполагая, что изменение Service_tier указывает на начало новой группы.

Это может быть предложено образцом набора данных, но не может считаться гарантированным. ИМХО, Service_tier скорее атрибут, чем ключ. На самом деле, ОП проверяет NN == EE в своем фрагменте кода, чтобы переключиться на новую группу.

В приведенных ниже решениях data.table группировка определяется cumsum(shift(NN == EE, fill = TRUE)), который проверяет равенство fo NN и EE, откладывает результат до следующей строки, где начинается следующая группа, и перечисляет группы путем подсчета TRUE с использованием cumsum().

В упрощенном варианте (без изменения формы) прыжки агрегируются функцией toString():

library(data.table)
setDT(d)[, .(SN = first(SN), hops = toString(NN), Service_tier = first(Service_tier)), 
  by = .(grp = cumsum(shift(NN == EE, fill = TRUE)))][]
   grp SN       hops Service_tier
1:   1  A       B, C      economy
2:   2  P    Q, S, R      regular
3:   3  H I, J, K, L      economy

Для преобразования длинного формата в широкий используется dcast():

library(data.table)
library(magrittr)   # piping used to improve readability
w <- setDT(d)[, .(SN = first(SN), hops = NN, Service_tier = first(Service_tier)), 
  by = .(grp = cumsum(shift(NN == EE, fill = TRUE)))] %>% 
  dcast(grp + ... ~ rowid(grp, prefix = "hop"), value.var = "hops", fill = "")  %>%  
  setcolorder(c(1:2, 4:ncol(.), 3))

w
   grp SN hop1 hop2 hop3 hop4 Service_tier
1:   1  A    B    C                economy
2:   2  P    Q    S    R           regular
3:   3  H    I    J    K    L      economy

setcolorder() используется для перестановки столбцов в порядке, ожидаемом OP. Это делается на месте, т.е. без копирования всего объекта данных.

Данные

library(data.table)

d <- fread("SN NN EE Service_tier
A  B  C  economy
B  C  C  economy
P  Q  R  regular
Q  S  R  regular
S  R  R  regular
H  I  L  economy
I  J  L  economy
J  K  L  economy
K  L  L  economy")

Я получаю сообщение об ошибке... Ошибка в [.data.frame(x, , .(SN = first(SN), hops = toString(NN), Service_tier = first(Service_tier)), : неиспользуемый аргумент (by = .(grp = cumsum (сдвиг (NN == EE, заполнение = ИСТИНА))))

Vasuki Rao 31.05.2019 12:51

@VasukiRao Кажется, я мог забыть принудить d к data.table с помощью setDT(d). Я изменил код. Пожалуйста, поднос еще раз. И спасибо за отчет.

Uwe 31.05.2019 12:54

когда я запускаю код, ошибка в ncol(w): объект 'w' не найден

Vasuki Rao 02.06.2019 16:29

Виноват. Еще одна ошибка копирования и вставки. Пожалуйста, смотрите измененный код.

Uwe 02.06.2019 16:32

отлично, работает безупречно, каждое интересное решение по сравнению с циклом for

Vasuki Rao 05.06.2019 04:44

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

Назначьте человека в наборе данных определенному состоянию на основе заранее определенных пропорций в R
Подсчитайте количество независимых наблюдений в группе с повторными измерениями
Функция R для выявления случаев, когда условие выполняется x раз в любом из n столбцов?
Как рассчитать разницу между последовательными наборами двух столбцов в диапазоне столбцов с помощью dplyr
Как заменить столбец в таблице другим вектором такой же длины, не меняя имя переменной?
Разделяйте столбцы по их строкам, если они отличаются
Множественные тесты с попарными комбинациями с использованием dplyr/tidyverse
Как применить несколько условных фильтров с группировкой по операции в R?
R dataframe - извлечь пару строк на основе двух переменных, затем объединить строки на основе пользовательской функции colwise
Зацикливание dplyr и создание нескольких фреймов данных