1
votes

Réduire les quasi-doublons et ajouter une différence en tant que nouvelle colonne dans R?

J'ai un data.frame appelé people qui décrit des employés uniques. Le fait est que le parcours des rôles de travail d'un employé est exprimé par une nouvelle ligne pour chaque nouveau rôle, où toutes les variables restent les mêmes à l'exception de Job_history.

  employee_ID    name Job_role  Job_history Job_history2 
1           1    Adam  Manager Web designer          N/A
2           2     Ben      CSO     Graduate       Intern      
3           3   Chris  Manager          N/A          N/A
4           4     Dan      CTO      Manager          N/A

Pour continuer à traiter mes données, je dois réduire ces doublons tout en préservant l'historique des tâches. Je voudrais mettre les valeurs de Job_history qui sont actuellement en lignes dans de nouvelles colonnes, et ne pas avoir le travail en cours répété dans la colonne Job_history. Pour visualiser, je veux que le data.frame ressemble à ceci:

employee_ID <- c('1','1','2','2','2','3','4','4')
name <- c('Adam','Adam','Ben','Ben','Ben','Chris','Dan','Dan')
Job_role <- c('Manager','Manager', 'CSO', 'CSO', 'CSO','Manager', 'CTO', 'CTO')
Job_history <- c('Manager', 'Web designer', 'CSO', 'Graduate', 'Intern', '0', 'CTO', 'Manager')

people.data <- data.frame(employee_ID, name, Job_role, Job_history)

  employee_ID    name Job_role  Job_history
1           1    Adam  Manager      Manager
2           1    Adam  Manager Web designer
3           2     Ben      CSO          CSO
4           2     Ben      CSO     Graduate
5           2     Ben      CSO       Intern
6           3   Chris  Manager      Manager
7           4     Dan      CTO          CTO
8           4     Dan      CTO      Manager

Comment dois-je procéder s'il vous plaît? J'ai essayé d'utiliser duplicate () ou unique () mais j'ai du mal à obtenir les valeurs dans les nouvelles colonnes, et dans le bon ordre (de bas en haut devient de gauche à droite pour chaque employé).

Toute aide est grandement appréciée!

r

0 commentaires

3 Réponses :


0
votes

Pour obtenir le nombre de colonnes, vous devez ajouter, c'est une bonne idée d'interroger automatiquement le nombre de lignes par nom pour connaître la profondeur de l'historique des tâches:

employee_ID <- c('1','1','2','2','2','3','4','4')
name <- c('Adam','Adam','Ben','Ben','Ben','Chris','Dan','Dan')
Job_role <- c('Manager','Manager', 'CSO', 'CSO', 'CSO','Manager', 'CTO', 'CTO')
Job_history <- c('Manager', 'Web designer', 'CSO', 'Graduate', 'Intern', '0', 'CTO', 'Manager')

people.data <- data.frame(employee_ID, name, Job_role, Job_history)

#install required packages  
install.packages("tidyquery")
library(tidyquery)
install.packages("dplyr")
library(dplyr)

#get maximum entries per name to automatically get the columns need to be attached
maxrowcount <- query(people.data, "Select count(*) as 'Number', name GROUP BY name")
maxrowcount <- max(maxrowcount$Number, na.rm = TRUE)
maxrowcount


0 commentaires

1
votes

Vous devez d'abord créer un nouveau champ dans votre bloc de données qui contiendra le futur nom de la colonne (Job_history1, Job_history2, etc.). Nous attribuons un numéro séquentiel (1, 2, ...) à chaque enregistrement, groupé par employee_ID, de sorte que le séquentiel commence à 1 pour chaque employé.

# Scalable solution
people.data <- data.frame(employee_ID, name, Job_role, Job_history)

people.data <-
  people.data %>%
  group_by(employee_ID) %>%
  mutate(seq = row_number()) %>%
  ungroup()

seq_digits <- nchar(as.character(max(people.data$seq)))

people.data <-
  people.data %>%
  mutate(column_name = sprintf("Job_history%0*d", seq_digits, seq)) %>%
  select(-c(seq))

people.data <-
  people.data %>%
  pivot_wider(names_from = column_name, values_from = Job_history)

Résultat:

XXX

Il ne nous reste plus qu'à appliquer une opération de pivot pour transposer les valeurs des champs souhaités sur de nouvelles colonnes.

# A tibble: 4 x 6
  employee_ID name  Job_role Job_history1 Job_history2 Job_history3
  <fct>       <fct> <fct>    <fct>        <fct>        <fct>       
1 1           Adam  Manager  Manager      Web designer NA          
2 2           Ben   CSO      CSO          Graduate     Intern      
3 3           Chris Manager  0            NA           NA          
4 4           Dan   CTO      CTO          Manager      NA       

Résultat:

library(tidyr)

people.data <-
  people.data %>%
  pivot_wider(names_from = column_name, values_from = Job_history)

print(people.data)

Une amélioration intéressante se produit si vous pensez qu'un employé peut avoir plus de 10 entrées d'historique ou plus. Parce que dans ce cas, les colonnes seront placées par ordre alphabétique: Job_history1, Job_history10, Job_history2, etc. ce qui n'est pas ce que nous voulons. Nous devons donc utiliser deux chiffres à la place pour formater les noms des colonnes: Job_history01, Job_history02, etc. Dans un cas extrême, nous pouvons même avoir plus de 99 entrées, donc 3 chiffres seraient nécessaires, et ainsi de suite. Nous voulons réduire au minimum le nombre de chiffres et rendre la solution évolutive. Ce que nous devons faire est de récupérer le numéro séquentiel le plus élevé attribué et de déterminer le nombre de chiffres dont il aura besoin.

# A tibble: 8 x 5
  employee_ID name  Job_role Job_history  column_name 
  <fct>       <fct> <fct>    <fct>        <chr>       
1 1           Adam  Manager  Manager      Job_history1
2 1           Adam  Manager  Web designer Job_history2
3 2           Ben   CSO      CSO          Job_history1
4 2           Ben   CSO      Graduate     Job_history2
5 2           Ben   CSO      Intern       Job_history3
6 3           Chris Manager  0            Job_history1
7 4           Dan   CTO      CTO          Job_history1
8 4           Dan   CTO      Manager      Job_history2


0 commentaires

0
votes

Une autre façon consiste à utiliser dplyr dans tidyverse:

# A tibble: 4 x 6
  employee_ID name  job_role job_history1 job_history2 job_history3
  <fct>       <fct> <fct>    <fct>        <fct>        <fct>       
1 1           Adam  Manager  Web designer NA           NA          
2 2           Ben   CSO      Graduate     CSO          Intern      
3 3           Chris Manager  0            NA           NA          
4 4           Dan   CTO      Manager      NA           NA   

conduisant à:

people.data %>% 
pivot_longer(cols = starts_with("Job"), names_to = "Job", names_prefix = "job", values_to = "role") %>% 
group_by(employee_ID, name) %>% 
mutate(rn = cumsum(role != lag(role, default = first(role))), roles = if_else(rn == 0, "role", paste0("history", rn))) %>% 
ungroup() %>% 
select(-Job) %>% 
distinct() %>% 
pivot_wider(id_cols = c("employee_ID", "name"), names_from = roles, names_prefix = "job_", values_from = role)


0 commentaires