3 votes

Comment remplir toutes les colonnes possibles dans un dataframe avec r data.table ?

Supposons que nous commencions avec l'exemple ci-dessous data généré par le code situé juste en dessous :

> data
  ID Period_1 Period_2 Values State
1  1        1  2020-01      5    X0
2  1        2  2020-02     10    X1
3  1        3  2020-03     15    X0
4  2        1  2020-04      0    X0
5  2        2  2020-05      2    X2
6  2        3  2020-06      4    X0
7  3        1  2020-02      3    X2
8  3        2  2020-03      6    X1
9  3        3  2020-04      9    X0

data <- 
  data.frame(
    ID = c(1,1,1,2,2,2,3,3,3),
    Period_1 = c(1, 2, 3, 1, 2, 3, 1, 2, 3),
    Period_2 = c("2020-01","2020-02","2020-03","2020-04","2020-05","2020-06","2020-02","2020-03","2020-04"),
    Values = c(5, 10, 15, 0, 2, 4, 3, 6, 9),
    State = c("X0","X1","X0","X0","X2","X0", "X2","X1","X0")
  )

J'essaie d'apprendre à utiliser le package R data.table, et je voudrais l'utiliser pour compter les transitions d'un état donné (état "X0" dans l'exemple de code ci-dessous) vers un autre état, lors du déplacement ou de la "transition" d'une période à la suivante (dans ce cas, la mesure de la période est "Period_1"). J'obtiens les résultats suivants en exécutant le code data.table immédiatement inférieur :

   OutflowState 2 4
1:           X0 0 0
2:           X1 1 0
3:           X2 1 0

Code run:

library(data.table)

dcast(
  setDT(data)[, OutflowState := factor(shift(State, type = c("lead"))), by = ID]
  [, period_factor := lapply(.SD, factor), .SDcols = "Period_1"]
  [, period_factor := as.numeric(period_factor) + 1],
    OutflowState ~ period_factor, length, 
    value.var = "Values", subset = .(State == "X0"), drop = FALSE
)

Ce résultat est correct, mais je voudrais (a) ajouter des colonnes au résultat pour les périodes 1 et 3 (la période 1 sera toujours composée de tous les 0 et la période 3 devrait montrer tous les 0 dans le cas de ceci data car il n'y a pas d'état = X0 dans les périodes 2 ; et (b) supprimer de la sortie la colonne où Période_1 = 4, car il n'y a pas de période = 4, c'est juste une astuce utilisée dans le code ci-dessus. as.numeric(period_factor) + 1 afin de signaler la prochaine période de transition. Comment faire ?

J'obtiens la trame de données intermédiaire suivante lorsque j'exécute le segment de code présenté ci-dessous. Une solution consiste à supprimer toutes les lignes où OutflowState = NA (en éliminant toutes les périodes 4 fictives) mais je ne sais pas comment faire.

   ID Period_1 Period_2 Values State OutflowState period_factor
1:  1        1  2020-01      5    X0           X1             2
2:  1        2  2020-02     10    X1           X0             3
3:  1        3  2020-03     15    X0         <NA>             4
4:  2        1  2020-04      0    X0           X2             2
5:  2        2  2020-05      2    X2           X0             3
6:  2        3  2020-06      4    X0         <NA>             4
7:  3        1  2020-02      3    X2           X1             2
8:  3        2  2020-03      6    X1           X0             3
9:  3        3  2020-04      9    X0         <NA>             4

setDT(data)[, OutflowState := factor(shift(State, type = c("lead"))), by = ID][
  , period_factor := lapply(.SD, factor), .SDcols = "Period_1"][
  , period_factor := as.numeric(period_factor) + 1  
  ]
data

Cette question est un prolongement de Comment utiliser data.table pour construire un nouveau dataframe montrant les flux entrants dans un état de transition spécifié en fonction de la valeur d'un élément dans une ligne antérieure ? la prise en compte des flux entrants de transition. Notez que le code data.table ci-dessus permet les alternatives de définir l'horizon temporel comme Période_2 et d'additionner les transitions des Valeurs plutôt que de compter les transitions, et doit maintenir ces capacités.

L'image ci-dessous l'illustre mieux :

enter image description here

1voto

Gregor Points 6270

dcast con drop = FALSE créera des colonnes pour chaque niveau de facteur de period_factor donc si vous voulez des colonnes 1 y 3 mais pas 4 dans le résultat, nous devons définir le niveau de period_factor d'inclure 1 y 3 mais pas 4 (et le garder factor classe !). J'ai simplifié la création de period_factor aussi, lapply y .SDcols ne serait nécessaire que si nous l'appliquions à plusieurs colonnes :

dcast(
  setDT(data)[, OutflowState := factor(shift(State, type = c("lead"))), by = ID]
  [, period_factor := factor(Period_1 + 1, levels = seq(1, max(Period_1)))],
    OutflowState ~ period_factor, length, 
    value.var = "Values",
    subset = .(State == "X0" ),
    drop = FALSE
)
#    OutflowState 1 2 3
# 1:           X0 0 0 0
# 2:           X1 0 1 0
# 3:           X2 0 1 0

1voto

Uwe Points 21553

Nous pouvons prendre le state_inflow() de la fonction ma réponse à la question Comment utiliser data.table pour construire un nouveau dataframe montrant les flux entrants dans un état de transition spécifié en fonction de la valeur d'un élément dans une ligne antérieure ? et le transformer en un state_outflow() fonction :

state_inflow <- function(mydat, target_state) {
  dcast(
    setDT(mydat)[, Previous_State := shift(State, fill = target_state), by = ID],
    factor(Previous_State) ~ factor(Period_1), length, value.var = "Values",
    subset = .(State == target_state), drop = FALSE
  )
} 

par l'échange des rôles de State y Previous_State en dcast() :

state_outflow <- function(mydat, target_state) {
  dcast(
    setDT(mydat)[, Previous_State := shift(State), by = ID],
    factor(State) ~ factor(Period_1), length, value.var = "Values",
    subset = .(Previous_State == target_state), drop = FALSE
  )
}

En outre, aucune valeur de remplissage n'est fournie à la fonction shift() fonction. Ainsi, l'état précédent de la première période de chaque ID est NA .

L'appel de la fonction donne le résultat attendu :

state_outflow(data, "X0")
   State 1 2 3
1:    X0 0 0 0
2:    X1 0 1 0
3:    X2 0 1 0

Il n'est pas nécessaire de modifier les niveaux de facteurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X