2 votes

Créer une table à partir des informations d'une autre table en R

J'ai un cadre de données CLIENTS avec : Numéro d'hôtel Nationalité Date d'arrivée Date de départ Quelque chose comme :

Client   Nationality   Hotel   Dateofarrive   DateofDeparture
Cl1          es         h1      21/07/2019    24/07/2019
Cl2          es         h1      23/07/2019    24/07/2019
Cl3          es         h1      06/07/2019    10/07/2019
Cl4          es         h2      05/07/2019    06/07/2019
Cl5          fr         h3      01/07/2019    02/07/2019
Cl6          pt         h1      07/07/2019    09/07/2019

Et je veux un dataframe Hôtel et pour chaque hôtel du dataframe je veux tous les clients qui sont de nationalité espagnole et toutes les nuits qu'ils ont dormi dans l'hôtel, la même chose pour la nationalité française et portugaise. Quelque chose comme :

Hotel    CliEspan  Nights  CliFrench Night CliPortug Night 
H1           3       8       0         0          1      2
H2           1       5       1         1          0      0

2voto

Ronak Shah Points 24715

Une option utilisant dplyr y tidyr . Nous convertissons Dateofarrive y DateofDeparture à l'objet Date réel, puis calculez la différence en soustrayant deux dates, group_by Hotel y Nationality y sum le nombre total de jours et le nombre total d'entrées dans chaque groupe. Convertir au format long, combiner les colonnes et spread en format large en remplissant les valeurs manquantes à 0.

library(dplyr)
library(tidyr)

df %>%
  mutate_at(vars(Dateofarrive, DateofDeparture), as.Date, "%d/%m/%Y") %>%
  mutate(days = as.integer(DateofDeparture - Dateofarrive)) %>%
  group_by(Hotel, Nationality) %>%
  summarise(total = sum(days), 
             n = n()) %>%
  gather(key, value, total, n) %>%
  unite(col, Nationality, key, sep = "_") %>%
  spread(col, value, fill = 0)

1voto

NelsonGon Points 11338

Je ne sais pas pourquoi nous avons 5 nuits pour l'hôtel h2 mais un autre dplyr possibilité(peut alors spread :

df %>% 
   group_by(Client,Hotel,Nationality) %>%
  mutate_at(vars(contains("Date")),list(~lubridate::dmy(.))) %>% 
   summarise(Time = DateofDeparture- Dateofarrive) %>% 
   ungroup() %>% 
   group_by(Hotel, Nationality) %>% 
   mutate(Nights= as.numeric(sum(Time))) %>% 
   tidyr::spread(Hotel, Nights, fill=0) %>% 
   rename_at(vars(contains("h")),list(~paste0(.,"_nights")))
# A tibble: 6 x 6
# Groups:   Nationality [3]
  Client Nationality Time   h1_nights h2_nights h3_nights
  <chr>  <chr>       <drtn>     <dbl>     <dbl>     <dbl>
1 Cl1    es          3 days         8         0         0
2 Cl2    es          1 days         8         0         0
3 Cl3    es          4 days         8         0         0
4 Cl4    es          1 days         0         1         0
5 Cl5    fr          1 days         0         0         1
6 Cl6    pt          2 days         2         0         0

0voto

RyanD Points 6857

Voici une option data.table utilisant dcast pour convertir les données en format large.

library(data.table)
setDT(df)
# convert to date and calculate nights
df[, Dateofarrive := as.Date(Dateofarrive, format = '%d/%m/%Y')]
df[, DateofDeparture := as.Date(DateofDeparture, format = '%d/%m/%Y')]
df[, nights := as.numeric(DateofDeparture - Dateofarrive)]

# dcast to wide format
new <- dcast(df, Hotel ~ Nationality, value.var = 'nights',
             fun.aggregate = list(sum, length))
names(new) <- gsub('nights_length', 'clients', names(new))

new
#    Hotel nights_sum_es nights_sum_fr nights_sum_pt clients_es clients_fr clients_pt
# 1:    h1             8             0             2          3          0          1
# 2:    h2             1             0             0          1          0          0
# 3:    h3             0             1             0          0          1          0

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