Je suis surpris de ne pas trouver de question sur ce site Web qui répondrait à la mienne.
Je souhaite créer 24 variables factices pour chaque heure de la journée (la valeur est 1 si l'heure est cette heure du jour et 0 dans le cas contraire). Une (très) petite partie des données ressemble à ceci:
19 20 21
1: 1 0 0
2: 1 0 0
3: 0 1 0
4: 0 0 1
Je veux que la sortie soit comme ceci:
df <- as.POSIXct(c("08-01-2018 19:46", "08-01-2018 19:50", "08-01-
2018 20:46", "09-01-2018 21:17"), format = "%d-%m-%Y %H:%M")
[1] "2018-01-08 19:46:00 CET" "2018-01-08 19:50:00 CET" "2018-01-08
20:46:00 CET" "2018-01-09 21:17:00 CET"
J'ai déjà regardé cette question: Création d'un variable factice pour certaines heures de la journée
Le seul problème que j'ai avec la réponse à mon problème est que je dois écrire 24 instructions ifelse pour chaque cas.
Je me demandais s'il existe un moyen plus élégant d'obtenir cette sortie sans avoir à écrire 24 instructions ifelse.
Si cette question est un double, merci de me le faire savoir! p>
Merci d'avance,
RC
4 Réponses :
Est-ce que ça va? Vous pouvez utiliser as.data.frame sur la sortie si vous en avez besoin comme data.frame
library(lubridate) hours <- as.factor(lubridate::hour(df)) # with intercept model.matrix(~hours) # without intercept - (+0) model.matrix(~hours+0)
lecture supplémentaire: p>
S'il est possible que toutes les heures ne soient pas représentées, mais que vous souhaitez garantir les 24 variables factices, ajoutez , levels = 0: 23 à l'appel à factor .
Merci @Jonny Phelps, cela fonctionne comme un charme. Merci également à Greg Snow pour cet excellent ajout!
Utilisation de tidyverse (édition avec suppression NA):
df <- tibble::tibble(time = as.POSIXct(c("08-01-2018 19:46", "08-01-2018 19:50", "08-01-2018 20:46", "09-01-2018 21:17"), format = "%d-%m-%Y %H:%M")
)
suppressPackageStartupMessages(library(dplyr))
df_dummy <- df %>%
mutate(
hours = lubridate::hour(time),
dummy = 1)
tidyr::pivot_wider(data = df_dummy, names_from = hours, values_from = dummy, values_fill = list(dummy = 0))
#> # A tibble: 4 x 4
#> time `19` `20` `21`
#> <dttm> <dbl> <dbl> <dbl>
#> 1 2018-01-08 19:46:00 1 0 0
#> 2 2018-01-08 19:50:00 1 0 0
#> 3 2018-01-08 20:46:00 0 1 0
#> 4 2018-01-09 21:17:00 0 0 1
Ce problème peut être résolu en utilisant le package lubridate.
Solution utilisant une boucle for
hour () code> nous donne l'heure d'un objet POSIXct . En créant un vecteur des heures d'intérêt et en les laissant courir sur les points dans le temps que vous avez fournis, on peut faire ce qui suit:
df <- as.POSIXct(c("08-01-2018 19:46", "08-01-2018 19:50", "08-01-2018 20:46", "09-01-2018 21:17"), format = "%d-%m-%Y %H:%M")
Résultat
df1 <- as.data.frame(do.call(rbind,list)) V1 V2 V3 1 1 0 0 2 1 0 0 3 0 1 0 4 0 0 1
# hours, storage vector and list for building the dataframe
hourv <- c(19:21)
storage <- c()
list <- list()
# the loop over the desired hours and points in time
for(k in 1:4){
for(i in 1:3){
if(hourv[i] == hour(df[k])){
storage[i] <- 1
}
else{
storage[i] <- 0
}
}
list[[k]] <- storage
}
en utilisant la base R, vous pourriez faire:
model.matrix(~a-1,data.frame(a=factor(as.POSIXlt(df)$h))) a19 a20 a21 1 1 0 0 2 1 0 0 3 0 1 0 4 0 0 1 attr(,"assign") [1] 1 1 1 attr(,"contrasts") attr(,"contrasts")$a [1] "contr.treatment"