Paramètres

J’ai mis les données sur Github afin de pouvoir répliquer le notebook facilement.

Le code ci dessous importe la data, formate les variables dates et arrange les variables stock et markingdate par ordre croissant.

library(tidyverse)
## ── Attaching packages ────────────────────────────────── tidyverse 1.2.1 ──
## ✔ ggplot2 3.0.0     ✔ purrr   0.3.2
## ✔ tibble  2.1.3     ✔ dplyr   0.8.1
## ✔ tidyr   0.8.3     ✔ stringr 1.3.1
## ✔ readr   1.1.1     ✔ forcats 0.3.0
## ── Conflicts ───────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
library(lubridate)
## 
## Attaching package: 'lubridate'
## The following object is masked from 'package:base':
## 
##     date
nbStart <- dmy('01/01/2018')
nbEnd <- dmy('31/12/2018')

PATH <- "https://raw.githubusercontent.com/thomaspernet/data_csv_r/master/data/CSAV_data.csv"
####
df <-  read.csv(PATH, sep = ';') %>%
  mutate(MarkingDate = dmy(MarkingDate),
         DateDiv = dmy(DateDiv),
         PayDate = dmy(PayDate)) %>%
  filter(MarkingDate >=nbStart &  MarkingDate <=nbEnd) %>%
  arrange(Stock, MarkingDate)
head(df)

1- Bonus Create Bucket

Ici, on souhaite créer une variable bucket, qui est un index si la MarkingDate est entre deux dates. Pour cela, on va utiliser la fonction findInterval.

C’est assez simple, il suffit de créer un vecteur de date qui va spliter la columne MarkingDate. Par exemple, on souhaite créer un bucket index pour un intervalle tous les trois mois. On créer un vecteur de date:

date_bucket <- c(ymd("2018-03-01"), ymd("2018-06-01"), ymd("2018-09-01"))

Note que j’utilise lubridate pour créer les dates, cela facilite la manipulation. Ensuite, je vais grouper les MarkingDate selon si elles sont dans les intervalles. Par exemple, si une date est entre le premier intervalle, alors le bucket est 0, si la date est entre le deuxième intervalle, alors bucket est égale a 1 et ainsi de suite. Toutes les dates au delà du dernier intervalle vont avoir un index max + 1. Dans notre example, il y a 3 intervalles, toutes les dates au delà du dernier intervalle auront la valeur 3

Attention, il faut que les date soient dans un ordre croissant, c’est pour cela que j’utilise arrange()

Pour pus d’info sur la fonction, ici

date_bucket <- c(ymd("2018-03-01"), ymd("2018-06-01"), ymd("2018-09-01"))

df <- df %>% arrange(MarkingDate) %>%
  mutate(bucket = findInterval(MarkingDate, 
                                  date_bucket)
                )
df

1- nb de markind dates sur une periode (01/01/18 à 31/12/18)

On extrait uniquement les valeurs uniques par groupe

df %>% 
  group_by(Stock) %>%
  select(Stock, MarkingDate) %>%
  unique()

Intervalle

  • Intervalle max entre deux dates de marking consécutives +
  • intervalle aux limites entre a- (01/01/18 et 1ere date de arking) et
  • b- entre (dernière date de marking et 31/12/18) + les cas où il n’y a pas d’observation

on prend seulement le lag

#### No upper/lower bounds
df %>% group_by(Stock) %>%
select(Stock, MarkingDate) %>%
mutate(diff_days = MarkingDate - lag(MarkingDate, 1))

On séléctionne par groupe uniquement la première et dernière date

#### Upper/lower bounds   

df %>% group_by(Stock) %>%
  select(Stock, MarkingDate) %>%
  filter(row_number() %in% c(1, n())) %>%
  mutate(diff_days_limits = ifelse(row_number() == 1,
                                   MarkingDate - nbStart,
                                   nbEnd - MarkingDate))

intervalle avec nombre d’obs

  • Intervalle max contenant 4 observations

On souhaite avoir les dates non pas en lag mais en forward; Pour aller vers l’avant, on utilise lead

df %>% group_by(Stock) %>%
  select(Stock, MarkingDate) %>%
  mutate(diff_days =lead(MarkingDate, 4) - MarkingDate)
  • intervalle aux limites entre (01/01/18 et les 5 ères dates de marking)

On séléctionne uniquement les 5 premières valeurs par groupe

df %>% group_by(Stock) %>%
  select(Stock, MarkingDate) %>%
  filter(row_number() %in% c(seq(1,5))) %>%
  mutate(diff_days = MarkingDate - nbStart)
  • entre (4 dernières dates de marking et 31/12/18)

On séléctionne les 4 dernières valeurs par groupe

df %>% group_by(Stock) %>%
  select(Stock, MarkingDate) %>%
  filter(row_number() %in% c(seq(n() - 3, n()))) %>%
  mutate(diff_days = nbEnd- MarkingDate)
  • cas ou il y a exactement 4 observations + le cas ou il y a moins de 4 observations
    • Je ne comprends pas très bien

Exclure duplicates

Faire les memes KPI que ci-dessus mais cette fois on ne conservant que les marking dates pour lesquelles les valeurs ont bougé (nos fameux carrés).

L’idée est de séléctionner les index des observations qui ont des duplicates ie valeurs identiques. Ensuite, on peut filtrer la data en séléctionnant uniquement les indexes non duplicates

Attention, j’ai crée à la main des valeurs identiques pour faire un test.

PATH2 <- "https://raw.githubusercontent.com/thomaspernet/data_csv_r/master/data/CSAV_data_square.csv"
##### Ci dessous, test avec 2018-01-19 & 2018-01-27 & 2018-08-03 & 2018-08-27 complétements identiques
df_s <-  read.csv(PATH2, sep = ';') %>%
  mutate(MarkingDate = dmy(MarkingDate),
         DateDiv = dmy(DateDiv),
         PayDate = dmy(PayDate)) %>%
  filter(MarkingDate >=nbStart &  MarkingDate <=nbEnd) %>%
  arrange(Stock, MarkingDate)

Juste pour info, voici les duplicates

### For the record: the duplicates
df_s %>% 
  rownames_to_column() %>%
  group_by(Stock, DateDiv,Amount,Yield,PayDate) %>%
  filter(n() > 1)

Premièrement, on extrait les duplicated indexes

##### Extract index duplicates
index_duplicates <- df_s %>% 
  rownames_to_column() %>%
  group_by(Stock, DateDiv,Amount,Yield,PayDate) %>%
  filter(n() > 1) %>% 
  ungroup()%>%
  select(rowname) %>%
  mutate(rowname = as.integer(rowname))

index_duplicates$rowname
##  [1]  1  2  3  4  5  6  7  8  9 10 15 16 17 18

Ensuite, on filtre la data de base

###### Extract row index of non duplicates
df_s %>%
  filter(!row_number() %in% index_duplicates$rowname)