2
votes

Comment puis-je générer la valeur maximale dans une plage de lignes dans un bloc de données?

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.


0 commentaires

5 Réponses :


2
votes

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


3 commentaires

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.



2
votes

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


1 commentaires

Ce code data.table me semble être de la pure magie. À un moment donné, j'ai vraiment besoin de l'examiner: D



1
votes

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)


0 commentaires

1
votes

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 .


0 commentaires

1
votes

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>


0 commentaires