Horizon plot: Help!

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Anthony Sturbois
Messages : 38
Enregistré le : 07 Nov 2019, 07:49

Horizon plot: Help!

Messagepar Anthony Sturbois » 17 Mar 2021, 18:33

Bonjour à toutes et à tous,
Je souhaite représenter des patterns de direction en fonction de plusieurs années
Mon jeu de donnée ressemble à ça

Code : Tout sélectionner

direction<-c(rep(90,50),rep(100,75),rep(120,200),rep(150,80),rep(270,50),rep(290,75),rep(300,200),rep(320,80))
année<-c(rep("2015",50),rep("2015",75),rep("2015",200),rep("2015",80),rep("2016",50),rep("2016",75),rep("2016",200),rep("2016",80))
df<-as.data.frame(cbind(direction,année))
range<-c("0-45","45-90","90-135","135-180","180-225","225-270","270-315","315-360")                                                                                                                                                                         


Je souhaite utiliser le code de ce lien pour produire le même type d'Horizon map
https://yonicd.github.io/ggalt/articles/horizon.html

Code : Tout sélectionner

library(hrbrthemes)
library(ggalt)
library(readr)
library(dplyr)

#PREPARATION DATA
sports <- read_tsv("https://github.com/halhen/viz-pub/raw/master/sports-time-of-day/activity.tsv")

sports %>%
  group_by(activity) %>%
  filter(max(p) > 3e-04,
         !grepl('n\\.e\\.c', activity)) %>%
  arrange(time) %>%
  mutate(p_peak = p / max(p),
         p_smooth = (lag(p_peak) + p_peak + lead(p_peak)) / 3,
         p_smooth = coalesce(p_smooth, p_peak)) %>%
  ungroup() %>%
  do({
    rbind(.,
          filter(., time == 0) %>%
            mutate(time = 24*60))
  }) %>%
  mutate(time = ifelse(time < 3 * 60, time + 24 * 60, time)) %>%
  mutate(activity = reorder(activity, p_peak, FUN=which.max)) %>%
  arrange(activity) %>%
  mutate(activity.f = reorder(as.character(activity), desc(activity))) -> sports

sports <- mutate(sports, time2 = time/60)

#GRAPHIQUE
ggplot(sports, aes(time2, p_smooth)) +
  geom_horizon(bandwidth=0.1) +
  facet_grid(activity.f~.) +
  scale_x_continuous(expand=c(0,0), breaks=seq(from = 3, to = 27, by = 3), labels = function(x) {sprintf("%02d:00", as.integer(x %% 24))}) +
  viridis::scale_fill_viridis(name = "Activity relative to peak", discrete=TRUE,
                              labels=scales::percent(seq(0, 1, 0.1)+0.1)) +
  labs(x=NULL, y=NULL, title="Peak time of day for sports and leisure",
       subtitle="Number of participants throughout the day compared to peak popularity.\nNote the morning-and-evening everyday workouts, the midday hobbies,\nand the evenings/late nights out.") +
  theme_ipsum_rc(grid="") +
  theme(panel.spacing.y=unit(-0.05, "lines")) +
  theme(strip.text.y = element_text(hjust=0, angle=360)) +
  theme(axis.text.y=element_blank())


Par rapport au graph du lien et du script je souhaiterai avoir les ranges de direction en X à la place des horaires et mes dates en Y à la place des sports.

N'étant pas familier avec cette grammaire et ayant un jeu de donnée différent, je n'arrive pas à transformer mes données et à générer les variables nécessaires à la réalisation de ce graph

Merci d'avance pour votre aide

Anthony

Facundo Muñoz
Messages : 156
Enregistré le : 04 Juil 2019, 09:58
Contact :

Re: Horizon plot: Help!

Messagepar Facundo Muñoz » 17 Mar 2021, 20:24

Bonsoir,

Il vous manque une variable pour faire ce genre de graphiques.
Vous avez la direction dans l'axe x, l'anée dans l'axe y, et puis il vous faut la variable à représenter par les couleurs (p_smooth, dans l'exemple des sports).

En outre, la variable direction dans votre objet `df` a été convertie en `character` car vous avez utilisé `cbind()` pour la construction du data.frame. C'est pas une bonne idée, car `cbind()` retourne une matrice, un objet qui ne peut être que d'un seul type de données. Et puisque le caractère es plus général que le numérique, vous avez transformé direction en caractère.

C'est mieux de construire le data.frame directement (sans passer par une matrice) comme ceci, par exemple :

Code : Tout sélectionner

df <- data.frame(
  direction = c(
    rep(90, 50),
    rep(100, 75),
    rep(120, 200),
    rep(150, 80),
    rep(270, 50),
    rep(290, 75),
    rep(300, 200),
    rep(320, 80)
  ),
  annee = c(
    rep("2015", 50),
    rep("2015", 75),
    rep("2015", 200),
    rep("2015", 80),
    rep("2016", 50),
    rep("2016", 75),
    rep("2016", 200),
    rep("2016", 80)
  )
)


Cordialement,
ƒacu.-

Anthony Sturbois
Messages : 38
Enregistré le : 07 Nov 2019, 07:49

Re: Horizon plot: Help!

Messagepar Anthony Sturbois » 18 Mar 2021, 08:43

Bonjour,
Merci pour ce conseil. Ca me permettra d'être plus direct et d'avoir moins de manipulation dans la génération de mes df à l'avenir.
J'avais bien perçu qu'il me manquait la variable ps_mooth, mais c'est justement elle que je n'arrive pas à calculer.
Merci encore
Anthony

Facundo Muñoz
Messages : 156
Enregistré le : 04 Juil 2019, 09:58
Contact :

Re: Horizon plot: Help!

Messagepar Facundo Muñoz » 18 Mar 2021, 09:46

En supposant qu'on veut représenter la quantité d'observations dans chaque intervalle de directions, en on profitant de la "circularité" de la variable direction, je ferait peut-être quelque chose comme cela :

Code : Tout sélectionner

library(tidyverse)

df <- data.frame(
  direction = c(
    rep(90, 50),
    rep(100, 75),
    rep(120, 200),
    rep(150, 80),
    rep(270, 50),
    rep(290, 75),
    rep(300, 200),
    rep(320, 80)
  ),
  annee = c(
    rep(2015, 50),
    rep(2015, 75),
    rep(2015, 200),
    rep(2015, 80),
    rep(2016, 50),
    rep(2016, 75),
    rep(2016, 200),
    rep(2016, 80)
  )
) %>%
  mutate(
    range = cut(
      direction,
      breaks = seq(0, 360, by = 45),
      ordered_result = TRUE
    )
  )

(summary_df <-
  df %>%
  count(annee, range) %>%
  complete(range, annee, fill = list(n = 0)) %>%
  mutate(
    # Each range bin represents 12.5 % of the total circle
    fraction = .125
  )
)
#> # A tibble: 16 x 4
#>    range     annee     n fraction
#>    <ord>     <dbl> <dbl>    <dbl>
#>  1 (0,45]     2015     0    0.125
#>  2 (0,45]     2016     0    0.125
#>  3 (45,90]    2015    50    0.125
#>  4 (45,90]    2016     0    0.125
#>  5 (90,135]   2015   275    0.125
#>  6 (90,135]   2016     0    0.125
#>  7 (135,180]  2015    80    0.125
#>  8 (135,180]  2016     0    0.125
#>  9 (180,225]  2015     0    0.125
#> 10 (180,225]  2016     0    0.125
#> 11 (225,270]  2015     0    0.125
#> 12 (225,270]  2016    50    0.125
#> 13 (270,315]  2015     0    0.125
#> 14 (270,315]  2016   275    0.125
#> 15 (315,360]  2015     0    0.125
#> 16 (315,360]  2016    80    0.125

summary_df %>%
  ggplot(aes(annee)) +
  geom_bar(aes(y = fraction, fill = n), stat = "identity", width = .8) +
  geom_text(
    data = enframe(setNames(nm = c(2015, 2016))),
    aes(x = value + c(-1, 1), label = name), y = .125
  ) +
  xlim(c(2014, 2017)) +  # Used to make some internal space
  labs(fill = NULL) +
  scale_fill_viridis_c() +
  coord_polar(theta = "y", start = -pi/2, direction = -1) +
  theme_void()


Image
ƒacu.-

Anthony Sturbois
Messages : 38
Enregistré le : 07 Nov 2019, 07:49

Re: Horizon plot: Help!

Messagepar Anthony Sturbois » 18 Mar 2021, 14:04

Merci beaucoup,
Intéressant en effet.
Ayant 19 années à représenter, j'ai peur que l'agrandissement progressive des cercles ne traduisent pas visuellement la réalité des patterns de distribution.
cependant je garde cela en tête pour d'autres applications. merci.
Je viens de me tourner vers les heatmap qui me semble plus souple d'utilisation et plus facile à lire que les horizon plots.
il est par ailleurs possible de customiser les axes X et Y en périphérie en représentant la même variable ou une autre par des bar plot.
Merci encore
Anthony


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Google [Bot] et 1 invité