2016-12-08 4 views
0

J'ai une trame de données avec deux colonnes (ident et valeur). Je voudrais créer un compteur qui redémarre chaque fois que la valeur d'identité change et aussi quand la valeur dans chaque ident change. Voici un exemple pour le rendre clair.Créer un compteur avec plusieurs variables qui redémarrent dans chaque sous-groupe

# ident value counter 
#-------------------- 
# 1  0  1 
# 1  0  2 
# 1  1  1 
# 1  1  2 
# 1  1  3 
# 1  0  1 
# 1  1  1 
# 1  1  2 
# 2  1  1 
# 2  0  1 
# 2  0  2 
# 2  0  3 

J'ai essayé le paquet plyr

ddply(mydf, .(ident, value), transform, .id = seq_along(ident)) 

Même résultat avec le package data.frame.

+1

Ce ne traitera pas la duplication du groupe (1,1) sur la 7ème ligne. Il sera compté comme 4,5 – OmaymaS

Répondre

1

Nous pouvons paste les deux valeurs ensemble et utiliser l'attribut length de rle pour obtenir la longueur des nombres consécutifs. Nous utilisons ensuite sequence pour générer le compteur.

df$counter <- sequence(rle(paste0(df$dent, df$value))$lengths) 
df 
# dent value counter 
#1  1  0  1 
#2  1  0  2 
#3  1  1  1 
#4  1  1  2 
#5  1  1  3 
#6  1  0  1 
#7  1  1  1 
#8  1  1  2 
#9  2  1  1 
#10 2  0  1 
#11 2  0  2 
#12 2  0  3 
+0

Thx, ça fonctionne parfaitement! – Maxgrav

2

A data.table variante à l'utilisation des fonctions rleid/rowid. Avec rleid, vous créez un numéro de série pour les valeurs consécutives pouvant être utilisées en tant que groupe. 1:.N ou rowid peut être utilisé pour créer le compteur. Le code:

library(data.table) 
# option 1: 
setDT(d)[, counter := 1:.N, by = .(ident,rleid(value))] 
# option 2: 
setDT(d)[, counter := rowid(ident, rleid(value))] 

qui donnent à la fois:

> d 
    ident value counter 
1:  1  0  1 
2:  1  0  2 
3:  1  1  1 
4:  1  1  2 
5:  1  1  3 
6:  1  0  1 
7:  1  1  1 
8:  1  1  2 
9:  2  1  1 
10:  2  0  1 
11:  2  0  2 
12:  2  0  3 

Avec dplyr il est un peu moins simple:

library(dplyr) 
d %>% 
    group_by(ident, val.gr = cumsum(value != lag(value, default = first(value)))) %>% 
    mutate(counter = row_number()) %>% 
    ungroup() %>% 
    select(-val.gr) 

Comme alternative à l'cumsum -fonction vous pourriez also use rleid à partir de data.table.


données occasion:

d <- structure(list(ident = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), 
        value = c(0L, 0L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 0L, 0L, 0L)), 
       .Names = c("ident", "value"), class = "data.frame", row.names = c(NA, -12L)) 
+0

Thx vous, ça marche aussi sur mes données! – Maxgrav