Supposons que je dispose des données et du bloc de données suivants:
sample_data sample_data2 1 1 <NA> 2 2 <NA> 3 3 <NA> 4 4 break 5 5 <NA> 6 6 <NA> 7 7 break 8 8 <NA> 9 9 <NA> 10 10 <NA> 11 11 <NA> 12 12 <NA> 13 13 <NA> 14 14 break
Lorsque j'imprime ce bloc de données, les résultats sont les suivants:
sample_data <- c(1:14) sample_data2 <- c(NA,NA,NA, "break", NA, NA, "break", NA,NA,NA,NA,NA,NA,"break") sample_df <- as.data.frame(sample_data) sample_df$sample_data2 <- sample_data2
Comment pourrais-je le programmer pour qu'à chaque "pause", il produise le maximum de cette ligne? Par exemple, je voudrais que le code produise l'ensemble de (4,7,14). De plus, je voudrais qu'il ne trouve que la valeur maximale entre le prochain intervalle de "pause". Je m'excuse à l'avance si j'ai utilisé une nomenclature incorrecte.
5 Réponses :
Je crée les groupes à la recherche du mot "break", puis je déplace les résultats d'une ligne vers le haut. Ensuite, quelques commandes dplyr
pour obtenir le maximum de chaque groupe.
library(dplyr) sample_df_new <- sample_df %>% mutate(group = c(1, cumsum(grepl("break", sample_data2)) + 1)[1:length(sample_data2)]) %>% group_by(group) %>% summarise(group_max = max(sample_data)) > sample_df_new # A tibble: 3 x 2 group group_max <dbl> <dbl> 1 1 4 2 2 7 3 3 14
Dans la deuxième ligne, si je voulais ajouter une deuxième variable (à part "break") qui ferait la même fonction, comment ferais-je cela? J'ai essayé de saisir || puis deuxième variable, mais cela n'a pas fonctionné.
Désolé, je ne sais pas ce que tu veux dire. Comment cette deuxième variable déterminerait-elle le groupe? Un nouveau groupe démarre-t-il lorsque l'un ou l'autre est pris en charge? Je pense qu'il pourrait être plus facile de poser une question distincte à ce sujet et d'ajouter les données.
Cela pourrait également fonctionner: cumsum (grepl ("break", sample_data2) + grepl ("break2", second_variable)) + 1)
. Mais encore une fois, je ne sais pas à quoi cela ressemblerait.
J'ai une réponse en utilisant data.table
:
sample_data sample_data2 group 1: 1 NA 0 2: 2 NA 0 3: 3 NA 0 4: 4 break 0 5: 5 NA 1 6: 6 NA 1 7: 7 break 1 8: 8 NA 2 9: 9 NA 2 10: 10 NA 2 11: 11 NA 2 12: 12 NA 2 13: 13 NA 2 14: 14 break 2
La partie délicate est (rleid (sample_data2) -0.5)% /% 2 :
rleid
crée un index croissant à chaque changement:
sample_data sample_data2 rleid 1: 1 NA 1 2: 2 NA 1 3: 3 NA 1 4: 4 break 2 5: 5 NA 3 6: 6 NA 3 7: 7 break 4 8: 8 NA 5 9: 9 NA 5 10: 10 NA 5 11: 11 NA 5 12: 12 NA 5 13: 13 NA 5 14: 14 break 6
Si vous conservez toute la partie de cet index - 0.5, vous avez un index constant pour les lignes que vous voulez, que vous pouvez utiliser pour l'opération de regroupement:
library(data.table) sample_df <- setDT(sample_df) sample_df[,group := (rleid(sample_data2)-0.5)%/%2] sample_df[,.(maxvalues = max(sample_data)),by = group] group maxvalues 1: 0 4 2: 1 7 3: 2 14
Ensuite, il s'agit simplement de prendre le maximum pour chaque groupe. Vous pouvez facilement le traduire en dplyr
si c'est plus facile pour vous
Ce code data.table
me semble être de la pure magie. À un moment donné, j'ai vraiment besoin de l'examiner: D
Voici 2 façons avec la base R. L'astuce consiste à définir une variable de regroupement, grp
.
sample_data <- 1:14 sample_data2 <- c(NA,NA,NA, "break", NA, NA, "break", NA,NA,NA,NA,NA,NA,"break") sample_df <- data.frame(sample_data, sample_data2)
Données. Il s'agit d'un code de création de données simplifié.
grp <- !is.na(sample_df$sample_data2) & sample_df$sample_data2 == "break" grp <- rev(cumsum(rev(grp))) grp <- -1*grp + max(grp) tapply(sample_df$sample_data, grp, max, na.rm = TRUE) aggregate(sample_data ~ grp, sample_df, max, na.rm = TRUE)
On dirait qu'il existe de nombreuses façons de procéder. Voici comment j'ai procédé:
rows <- which(sample_data2 == "break") #Get the row indices for where "break" appears findmax <- function(maxrow) { max(sample_data[1:maxrow]) } #Create a function that returns the max "up to" a given row sapply(rows, findmax) #apply it for each of your rows ### [1] 4 7 14
Notez que cela fonctionne "jusqu'à" la ligne donnée. Obtenir la valeur maximale entre les deux sauts serait probablement plus facile avec l'une des autres solutions, mais vous pouvez également le faire en regardant la ligne j-1 à la jième ligne à partir de l'objet lignes
.
Selon que vous souhaitez évaluer le nombre maximum de "sample_data" entre tous les "sample_data2" == break, y compris (par exemple, ligne 1 à ligne 4) ou en excluant (par exemple, ligne 1 à ligne 3) le "sample_data2" == break row, vous pouvez faire quelque chose comme ceci avec tidyverse
:
En excluant les lignes de rupture:
sample_df %>% group_by(sample_data2) %>% mutate(temp = ifelse(is.na(sample_data2), NA_character_, paste0(gl(length(sample_data2), 1)))) %>% ungroup() %>% fill(temp, .direction = "up") %>% group_by(temp) %>% summarise(res = max(sample_data)) temp res <chr> <dbl> 1 1 4. 2 2 7. 3 3 14.
En incluant les lignes de rupture:
sample_df %>% group_by(sample_data2) %>% mutate(temp = ifelse(is.na(sample_data2), NA_character_, paste0(gl(length(sample_data2), 1)))) %>% ungroup() %>% fill(temp, .direction = "up") %>% filter(is.na(sample_data2)) %>% group_by(temp) %>% summarise(res = max(sample_data)) temp res <chr> <dbl> 1 1 3. 2 2 6. 3 3 13.
Les deux codes créent une variable d'ID appelée "temp" en utilisant gl ()
pour "sample_data2" == break, puis remplissez les lignes NA avec cela ID. Ensuite, le premier code filtre les lignes "sample_data2" == break et évalue les valeurs "sample_data" maximales par groupe, tandis que le second évalue les valeurs "sample_data" maximum par groupe, y compris les "sample_data2" == break rows. p>