J'ai un dataframe qui ressemble à
structure(list(V1 = structure(c(9L, 1L, 2L, 3L, 10L, 4L, 5L, 6L, 7L, 11L, 8L), .Label = c("1234", "1235", "1236", "1237","1238", "1239", "1240", "1241", "Q 1", "Q 2", "Q 3"), class = "factor"),
V2 = structure(c(1L, 2L, 4L, 5L, 1L, 6L, 7L, 8L, 9L, 1L, 3L), .Label = c("", "data1", "data10", "data2", "data3","data5", "data6", "data7", "data8"), class = "factor")), class = "data.frame", row.names = c(NA,-11L))
Dans cet exemple, la valeur Q correspond à un type d'en-tête pour les identifiants et les données en dessous. Je veux mettre toutes les valeurs Q dans une nouvelle colonne, en faisant correspondre le Q "en-tête" aux ID respectifs. comme ça
Q 1 1234 data1 Q 1 1235 data2 Q 1 1236 data3 Q 2 1237 data5 Q 2 1238 data6 Q 2 1239 data7 Q 2 1240 data8 Q 3 1241 data10
Exemple
Q 1 1234 data1 1235 data2 1236 data3 Q 2 1237 data5 1238 data6 1239 data7 1240 data8 Q 3 1241 data10
3 Réponses :
subset(transform(d, Id = d$V1[which(d$V2 == "")[cumsum(d$V2 == "")]]), V2 != "") # V1 V2 Id #2 1234 data1 Q 1 #3 1235 data2 Q 1 #4 1236 data3 Q 1 #6 1237 data5 Q 2 #7 1238 data6 Q 2 #8 1239 data7 Q 2 #9 1240 data8 Q 2 #11 1241 data10 Q 3
Nous pouvons créer une nouvelle colonne ( V3 ) où nous copions les valeurs de V1 et a NA pour les valeurs qui ne commencent pas par "Q" . Nous remplaçons ces NA s par tidyr :: fill et supprimons les lignes des données où V1 commence par "Q" .
df %>%
mutate(V3 = stringr::str_extract(V1, "Q \\d")) %>%
tidyr::fill(V3) %>%
filter(!grepl("^Q", V1))
Comme @camille l'a mentionné, nous pouvons également extraire "Q \\ d" de V1 puis utiliser remplir .
library(dplyr) df %>% mutate_all(as.character) %>% mutate(V3 = replace(V1, !startsWith(V1, "Q"), NA)) %>% tidyr::fill(V3) %>% filter(!startsWith(V1, "Q")) # V1 V2 V3 #1 1234 data1 Q 1 #2 1235 data2 Q 1 #3 1236 data3 Q 1 #4 1237 data5 Q 2 #5 1238 data6 Q 2 #6 1239 data7 Q 2 #7 1240 data8 Q 2 #8 1241 data10 Q 3
Le deuxième appel mutate pourrait être plus simple si vous utilisez simplement regex pour extraire les chaînes "Q \\ d" , puisque vous obtiendrez NA là où cela ne se produit pas. Pourrait aussi vous laisser sauter la première mutation
Vous pouvez utiliser rle et rep pour cbind l'en-tête aux lignes de données.
i <- x$V2 == ""
#i <- grepl("^Q", x$V1) #Alternative
cbind(header=rep(x$V1[i], rle(i)$lengths[c(FALSE,TRUE)]), x[!i,])
# header V1 V2
#2 Q 1 1234 data1
#3 Q 1 1235 data2
#4 Q 1 1236 data3
#6 Q 2 1237 data5
#7 Q 2 1238 data6
#8 Q 2 1239 data7
#9 Q 2 1240 data8
#11 Q 3 1241 data10