1
votes

Remodeler les données du format long au format large

Je recherche un moyen rapide de remodeler les données du format long au format large. En ce moment, j'ai essayé un code avec des boucles nest for, bien que le travail soit fait, cela prend beaucoup de temps pour générer la sortie.

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
  }
}

La sortie attendue est comme ci-dessous

XXX

actuellement, le code ci-dessous fait le travail. Je suis sûr qu'il existe un moyen efficace et propre de le faire.

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


2 commentaires

Il semble que vos ensembles s'excluent mutuellement, par exemple, regular = {P, Q, R, S} mais P, Q, R et S ne font partie d'aucun autre «ensemble». Cela sera-t-il toujours vrai? "A" pourrait-il jamais faire partie de la régularité et de l'économie? La méthode appropriée pour élargir ces données dépendra de votre réponse.


économie = {P, Q, R, S} peut également apparaître en économie, mais pour une donnée P et S, nous n'aurons qu'un seul chemin et non plusieurs chemins.


3 Réponses :


0
votes

Une option consiste à créer une séquence unique en utilisant rleid de data.table , rassembler le dataframe au format long, supprimer les doublons de chaque groupe, attribuez des noms de colonne et étalez -les au format large.

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    


0 commentaires

0
votes

Nous pouvons utiliser data.table . Convertissez le 'data.frame' en 'dat.table' ( setDT (df1) , groupé par rleid sur le 'Service_tier', changez la valeur de 'SN' en premier élément groupé par 'grp', puis groupé par 'Service_tier', 'SN', obtenez l'élément unique du sous-ensemble de Data.table et dcast code> du format "long" au format "large"

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))

données

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     


0 commentaires

0
votes

Le point crucial ici est d'identifier quelles lignes appartiennent à quel groupe. Les réponses de Ronak et akrun les deux utilisent rleid (Service_tier) en supposant qu'un changement dans Service_tier indique le début d'un nouveau groupe.

Cela peut être suggéré par l'exemple d'ensemble de données mais ne peut être considéré comme garanti. IMHO, Service_tier est plutôt un attribut qu'une clé. En fait, l'OP teste NN == EE dans son extrait de code pour passer à un nouveau groupe.

Dans les solutions data.table ci-dessous, le regroupement est déterminé par cumsum (shift (NN == EE, fill = TRUE)) qui teste l'égalité pour NN et EE , retarde le résultat à la ligne suivante où commence le groupe suivant, et énumère les groupes en comptant TRUE en utilisant cumsum().

Dans la version simplifiée (sans remodelage) , les sauts sont agrégés par la fonction toString () :

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")
   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

Pour le remodelage du format long au format large, dcast () est utilisé:

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       hops Service_tier
1:   1  A       B, C      economy
2:   2  P    Q, S, R      regular
3:   3  H I, J, K, L      economy

setcolorder () est utilisé pour réorganiser les colonnes dans l'ordre attendu par l'OP. Cela se fait sur place , c'est-à-dire sans copier tout l'objet de données.

Données

library(data.table)
setDT(d)[, .(SN = first(SN), hops = toString(NN), Service_tier = first(Service_tier)), 
  by = .(grp = cumsum(shift(NN == EE, fill = TRUE)))][]


5 commentaires

J'obtiens une erreur ... Erreur dans [.data.frame (x,. (SN = first (SN), hops = toString (NN), Service_tier = first (Service_tier)), : argument non utilisé (par =. (grp = cumsum (shift (NN == EE, fill = TRUE))))


@VasukiRao Il semble que j'aie oublié de forcer d à data.table en utilisant setDT (d) . J'ai modifié le code. S'il vous plaît, plateau à nouveau. Et merci pour le rapport.


lorsque j'exécute le code, erreur dans ncol (w): objet 'w' introuvable


Ma faute. Une autre erreur de copier-coller. Veuillez consulter le code modifié.


super, fonctionne parfaitement, chaque solution intéressante par rapport à la boucle for