Tableau reproductible: J'ai une base de données similaire à celle illustrée ci-dessous. La différence étant que la base de données avec laquelle je travaille est beaucoup plus grande.
gender age age_partner max_age nrs n 1 female 18 22 60 42 0 2 female 18 22 60 42 1 3 female 18 22 60 42 2 4 female 18 22 60 42 3 5 female 18 22 60 42 4 38 female 18 22 60 42 37 39 female 18 22 60 42 38 40 female 18 22 60 42 39 41 female 18 22 60 42 40 42 female 18 22 60 42 41
general_tibble
donne:
general_binded <- bind_rows(general_list)Question:
Comment créer une nouvelle table à partir d'une table précédente, qui prend la valeur de nrs
, et crée une variable de colonne, appelée n
, qui va de 0 à la valeur dans nrs
?
Pour illustrer davantage, dans la ligne 1 de general_tibble
la colonne nrs
est égale à 42 donc la colonne serait aller de 0 à 42, dans la ligne 2 nrs
est égal à 41 donc la colonne passerait de 0 à 41, et de même pour la ligne 3.
J'utilise actuellement le code ci-dessous. Cela fonctionne, mais lorsque general_tibble
est trop gros, le code fonctionne très lentement.
general_list <- list() for(i in 1:NROW(general_tibble)){ general_list[[i]] <- data.frame(general_tibble[i, ], n = 0:general_tibble[[i, "nrs"]]) }
Ensuite, je bind_rows ()
general_list
pour obtenir general_binded
gender age age_partner max_age nrs 1 female 18 22 60 42 2 female 19 20 60 41 3 male 18 17 65 47
general_binded [c (1: 5, 38:42),]
donne:
general_tibble <- tibble(gender = c("female", "female", "male"), age = c(18, 19,18), age_partner = c(22,20,17), max_age = c(60, 60, 65), nrs =c(42,41,47))
PS: Dans la boucle for, j'utilise data.frame ()
à la place de tibble ()
parce que je veux recycler les lignes. Si vous avez une sorte de conseil impliquant des tibbles ou des dataframes, je suis heureux de le prendre.
5 Réponses :
Nous pouvons utiliser uncount
general_tibble %>% mutate(n = map(nrs+1, ~ seq(.x) - 1)) %>% unnest
Une autre option est unnest
library(tidyverse) general_tibble %>% mutate(grp = row_number(), nrsN = nrs + 1) %>% uncount(nrsN) %>% group_by(grp) %>% mutate(n = row_number() - 1) %>% ungroup %>% select(-grp) # A tibble: 133 x 6 # gender age age_partner max_age nrs n # <chr> <dbl> <dbl> <dbl> <dbl> <dbl> # 1 female 18 22 60 42 0 # 2 female 18 22 60 42 1 # 3 female 18 22 60 42 2 # 4 female 18 22 60 42 3 # 5 female 18 22 60 42 4 # 6 female 18 22 60 42 5 # 7 female 18 22 60 42 6 # 8 female 18 22 60 42 7 # 9 female 18 22 60 42 8 #10 female 18 22 60 42 9 # ⦠with 123 more rows
Un moyen avec la base R (moins le package tibble
).
Tout d'abord, divisé par le groupe nrs
. Ensuite, développez les lignes de chaque dataframe par la valeur nrs
. Troisièmement, créez une colonne id
qui représente 0: quel que soit le nombre de lignes. Quatrièmement, ramenez-le à une tibble
:
library(tibble) df <- tibble( gender = c("female", "female", "male"), age = c(18, 19, 18), age_partner = c(22, 20, 17), max_age = c(60, 60, 65), nrs = c(42, 41, 47) ) nrs_split <- split(df, df$nrs) df_list <- lapply(nrs_split, function(i) i[rep(seq_len(nrow(i)), each=i$nrs + 1), ]) df_renum <- lapply(df_list, function(i) {i$id <- 0:rle(i$nrs)$values; return(i)}) df <- do.call("rbind", df_renum) df #> # A tibble: 133 x 6 #> gender age age_partner max_age nrs id #> * <chr> <dbl> <dbl> <dbl> <dbl> <int> #> 1 female 19 20 60 41 0 #> 2 female 19 20 60 41 1 #> 3 female 19 20 60 41 2 #> 4 female 19 20 60 41 3 #> 5 female 19 20 60 41 4 #> 6 female 19 20 60 41 5 #> 7 female 19 20 60 41 6 #> 8 female 19 20 60 41 7 #> 9 female 19 20 60 41 8 #> 10 female 19 20 60 41 9 #> # ⦠with 123 more rows
L'approche la plus simple pour cela serait d'étendre la colonne general_tibble
sur nrs
en utilisant la fonction tidyr :: expand ()
:
expanded_vars <- do.call(rbind,lapply(general_tibble$nrs, function(x) expand.grid(x, 0:x))) names(expanded_vars) <- c("nrs", "n") merge(y = expanded_vars, x = general_tibble, by = "nrs", all = TRUE)
Salut, le group_by_all ()%>% expand ()
a très bien fonctionné. Cependant, je suis maintenant confronté au problème qu'il faut environ 15 minutes pour agrandir un tibble d'environ 600 000 lignes. Que suggérez-vous?
@DennisAguilar donne une chance à la solution data.table de Toucan, car data.table est généralement plus rapide. Une autre idée pour le moment est de diviser après le regroupement, l'expansion puis la reliure (je ne sais pas si cela aiderait).
Avec dplyr
et tidyr
, vous pouvez également faire:
general_tibble %>% group_by(rowid = row_number()) %>% mutate(n = nrs) %>% complete(n = seq(0, n, 1)) %>% fill(everything(), .direction = "up") %>% ungroup() %>% select(-rowid) n gender age age_partner max_age nrs <dbl> <chr> <dbl> <dbl> <dbl> <dbl> 1 0 female 18 22 60 42 2 1 female 18 22 60 42 3 2 female 18 22 60 42 4 3 female 18 22 60 42 5 4 female 18 22 60 42 6 5 female 18 22 60 42 7 6 female 18 22 60 42 8 7 female 18 22 60 42 9 8 female 18 22 60 42 10 9 female 18 22 60 42
Une bonne chose à propos de l'utilisation de data.table
par rapport à tidyverse
est que vous n'avez pas besoin de penser aux opérations pour savoir si ce que vous faites est un muter , développer
ou résumer
. Vous pouvez simplement mettre ce que vous voulez dans la partie j
de df [i, j, k]
et quel que soit le nombre de lignes à résoudre, c'est ce que vous obtenez.
library(data.table) setDT(general_tibble) general_tibble[, .(n = seq(0, nrs)) , by = names(general_tibble)] # gender age age_partner max_age nrs n # 1: female 18 22 60 42 0 # 2: female 18 22 60 42 1 # 3: female 18 22 60 42 2 # 4: female 18 22 60 42 3 # 5: female 18 22 60 42 4 # --- # 129: male 18 17 65 47 43 # 130: male 18 17 65 47 44 # 131: male 18 17 65 47 45 # 132: male 18 17 65 47 46 # 133: male 18 17 65 47 47
Semble lié Plus rapide équivalent à group_by%>% expand dans R
stackoverflow.com/questions/2894775/...