1
votes

R - Créer une nouvelle colonne et remplir en fonction de la valeur de la cellule entre deux délimiteurs

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


0 commentaires

3 Réponses :


2
votes
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

0 commentaires

1
votes

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


1 commentaires

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



0
votes

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


0 commentaires