2016-02-12 17 views
8

Non so come formulare la domanda in parole, ma come posso creare una colonna di indice per un data.table che per gruppo aumenta quando viene visualizzato un valore diverso?Valori univoci dell'indice in data.table

Ecco la MWE

library(data.table) 
in.data <- data.table(fruits=c(rep("banana", 4), rep("pear", 5)),vendor=c("a", "b", "b", "c", "d", "d", "e", "f", "f")) 

Ecco il risultato della R-codice dovrebbe generare

in.data[, wanted.column:=c(1,2,2,3,1,1,2,3,3)] 

# fruits vendor wanted.column 
# 1: banana  a    1 
# 2: banana  b    2 
# 3: banana  b    2 
# 4: banana  c    3 
# 5: pear  d    1 
# 6: pear  d    1 
# 7: pear  e    2 
# 8: pear  f    3 
# 9: pear  f    3 

Così etichette ogni fornitore 1, 2, 3, ... all'interno di ogni frutto. C'è probabilmente una soluzione molto semplice, ma sono bloccato.

+1

Ha funzionato! L'ho aggiunto in questo modo: in.data [, wanted.2: = in.data [, rleid (vendor), by = fruits] [, V1]]. Forse puoi scrivere una risposta così posso accettarla? – Chris

risposta

9

Ho qualche idea. È possibile utilizzare un contatore gruppo nidificato:

in.data[, w := setDT(list(v = vendor))[, g := .GRP, by=v]$g, by=fruits] 

In alternativa, fare una routine di identificazione, che dipende dati ordinati (grazie @eddi) e sembra uno spreco:

in.data[, w := rleid(vendor), by=fruits] 

L'approccio di base-R sarebbe probabilmente essere:

in.data[, w := match(vendor, unique(vendor)), by=fruits] 

# or in base R ... 

in.data$w = with(in.data, ave(vendor, fruits, FUN = function(x) match(x, unique(x)))) 
+1

Grazie! Non sarei mai stato in grado di risolverlo da solo. – Chris

+1

Vale la pena notare che la prima e la seconda opzione producono risultati diversi se si fa ad es. 'in.data [6, vendor: = 'f']'. Non sono sicuro quale sia il risultato desiderato. – eddi

+0

Buon punto; grazie @eddi – Frank

8

Un altro approccio potrebbe essere due fasi:

DT = data.table(fruits=c(rep("banana", 4), rep("pear", 5)),vendor=c("a", "b", "b", "c", "d", "d", "e", "f", "f")) 
DT 
    fruits vendor 
1: banana  a 
2: banana  b 
3: banana  b 
4: banana  c 
5: pear  d 
6: pear  d 
7: pear  e 
8: pear  f 
9: pear  f 
DT[, wanted:=.GRP, by="fruits,vendor"] # step 1 
DT 
    fruits vendor wanted 
1: banana  a  1 
2: banana  b  2 
3: banana  b  2 
4: banana  c  3 
5: pear  d  4 
6: pear  d  4 
7: pear  e  5 
8: pear  f  6 
9: pear  f  6 
DT[, wanted:=wanted-wanted[1]+1L, by="fruits"] # step 2 (adjust) 
DT 
    fruits vendor wanted 
1: banana  a  1 
2: banana  b  2 
3: banana  b  2 
4: banana  c  3 
5: pear  d  1 
6: pear  d  1 
7: pear  e  2 
8: pear  f  3 
9: pear  f  3 
> 

Il modo in cui vorrei commentare questo nel codice di produzione potrebbe essere:

DT[, wanted:=.GRP, by="fruits,vendor"]   # .GRP is simple group counter 
DT[, wanted:=wanted-wanted[1]+1L, by="fruits"] # reset vendor counter per fruit 
+0

Grazie. Uso R in produzione, quindi grazie per l'esempio. data.table è ancora magico per me, ma spero di capirlo alla fine. – Chris

+1

@Chris felice di ascoltare. Sembra che tu stia arrivando. Bello vedere un buon MRE. –

+2

@Chris Anche se il tuo MRE ha lasciato alcuni aspetti ambigui, che hanno causato confusione. MRE avrebbe potuto essere migliore includendo i gruppi che non sono contigui e affermando qual è il risultato desiderato. –

4

Se si desidera che l'indice sia la stessa per tutti i fornitori all'interno di una data di frutta, allora questa è un'altra opzione:

in.data[, wanted := as.integer(factor(vendor, levels = unique(vendor))), by = fruits] 

Altrimenti, se si desidera che si attivi ogni volta che il fornitore cambia, quindi, dalle risposte date finora, rleid è l'unico che funziona.

Problemi correlati