4
votes

Combinaison de 2 données Cadre ayant des structures différentes

Je recherche une méthode efficace pour combiner ces 2 data.frames: L'un avec les questions et leurs réponses et points associés (questions organisées par lignes)

result_research <- data.frame(cand = c("can1","can2","can3"), 
                              X01 = c(1,1,0),
                              X02 = c(0,2,2),
                              X03 = c(1,1,1),
                              X04 = c(0.5,0.5,0))

   cand X01 X02 X03 X04
   can1   1   0   1 0.5
   can2   1   2   1 0.5
   can3   0   2   1 0.0

et l'autre avec le nombre de candidats et leur réponse (questions organisées par colonnes)

extract <- data.frame(cand = c("can1","can2","can3"), 
                      X01 = c("A","A","B"),
                      X02 = c("B","C","C"),
                      X03 = c("B","B","B"),
                      X04 = c("C","C","A"))

 cand X01 X02 X03 X04
 can1   A   B   B   C
 can2   A   C   B   C
 can3   B   C   B   A

Comment accéder au prochain résultat? Un bloc de données avec la même dimension que le second mais au lieu des réponses, nous trouverions les points situés dans le bloc de données réponse.

Sortie souhaitée:

answer <- data.frame(num_question = c("X01","X02","X03","X04"), 
                     ans = c("A","C","B","C"),
                     point = c(1,2,1,0.5))

num_question ans point
X01          A   1.0
X02          C   2.0
X03          B   1.0
X04          C   0.5


0 commentaires

5 Réponses :


1
votes
library(tidyverse)

tmp <- extract %>% 
  gather(num_question, can_ans, -cand) %>%  # turn the extract data.frame into long format
  left_join(answer, by="num_question") %>% #merge extract by question number into a single data.frame
  mutate(correct = (can_ans == ans)+0) %>% # is candidate answer the same as the correct answer (1 = TRUE, 0 = FALSE)
  mutate(result = correct*point) # multiply correct answer (1) with points given

#turn the data.frame into wide format
tmp %>% 
  select(cand, num_question, result) %>% 
  spread(num_question,result) 

#   cand X01 X02 X03 X04
# 1 can1   1   0   1 0.5
# 2 can2   1   2   1 0.5
# 3 can3   0   2   1 0.0

0 commentaires

0
votes
cand X01 X02 X03 X04
1 can1   1   0   1 0.5
2 can2   1   2   1 0.5
3 can3   0   2   1 0.0

0 commentaires

0
votes

Nous pouvons utiliser dplyr et tidyr pour collecter des données au format long, left_join sur num_question et ans , remplacez les NA s par 0 et répartissez les données en grand format.

library(dplyr)
library(tidyr)

extract %>%
  gather(key, value, -cand) %>%
  left_join(answer, by = c("key" = "num_question", "value" = "ans")) %>%
  replace_na(list(point = 0)) %>%
  select(-value) %>%
  spread(key, point)

#  cand X01 X02 X03 X04
#1 can1   1   0   1 0.5
#2 can2   1   2   1 0.5
#3 can3   0   2   1 0.0


0 commentaires

1
votes

Voici une approche de base R avec stack et unstack , c'est-à-dire

d1 <- stack(extract[-1])
d1$values <- answer$point[match(do.call(paste, d1), paste(answer$ans, answer$num_question))]
d1$values <- replace(d1$values, is.na(d1$values), 0)
cbind.data.frame(cand = extract$cand, unstack(d1))

#  cand X01 X02 X03 X04
#1 can1   1   0   1 0.5
#2 can2   1   2   1 0.5
#3 can3   0   2   1 0.0


2 commentaires

Où puis-je trouver la fonction de pile? dans le paquet utils?


C'est une fonction de base R



1
votes

Cela peut également être fait avec la base R en utilisant apply:

answer <- answer[match(answer$num_question, names(extract)[-1]), ]
extract[, -1] <- t((t(extract[, -1]) == answer$ans) * answer$point)

extract
#>   cand X01 X02 X03 X04
#> 1 can1   1   0   1 0.5
#> 2 can2   1   2   1 0.5
#> 3 can3   0   2   1 0.0

Pour chaque ligne de extract (c'est-à-dire chaque candidat) correspond les numéros de question entre data.frames en utilisant match . Si la réponse donnée coïncide avec la bonne réponse, renvoyez le point associé, sinon renvoyez zéro.


Ou sans appliquer en utilisant uniquement des opérations vectorisées:

extract[, -1] <- t(apply(extract[, -1], 1, function(x) 
     ifelse(x[match(names(x), answer$num_question)] == answer$ans, answer$point, 0)
    ))

extract
#>   cand X01 X02 X03 X04
#> 1 can1   1   0   1 0.5
#> 2 can2   1   2   1 0.5
#> 3 can3   0   2   1 0.0


0 commentaires