2011-06-28 9 views
6

Definire:Creare una variabile catturare l'occorrenza più frequente dal gruppo

df1 <-data.frame(
id=c(rep(1,3),rep(2,3)), 
v1=as.character(c("a","b","b",rep("c",3))) 
) 

S.T.

> df1 
    id v1 
1 1 a 
2 1 b 
3 1 b 
4 2 c 
5 2 c 
6 2 c 

voglio creare una variabile terzo freq che contiene la più frequente osservazione v1 da id S.T.

> df2 
    id v1 freq 
1 1 a b 
2 1 b b 
3 1 b b 
4 2 c c 
5 2 c c 
6 2 c c 
+1

come si intende gestire i legami all'interno del gruppo ID? – Chase

+0

@Chase Nel mio caso sono sicuro che non ci siano vincoli. – Fred

+0

Buona domanda sui legami, prenderò nota su come la mia soluzione gestisce che ... – joran

risposta

3

È possibile farlo utilizzando ddply e una funzione personalizzata per scegliere il valore più frequente:

myFun <- function(x){ 
    tbl <- table(x$v1) 
    x$freq <- rep(names(tbl)[which.max(tbl)],nrow(x)) 
    x 
} 

ddply(df1,.(id),.fun=myFun) 

Nota che which.max restituirà la prima occorrenza del valore massimo, in caso di parità . Vedere ?? which.is.max nel pacchetto nnet per un'opzione che interrompe i legami in modo casuale.

+0

+1 Nice ........ – Andrie

1
mode <- function(x) names(table(x))[ which.max(table(x)) ] 
df1$freq <- ave(df1$v1, df1$id, FUN=mode) 
> df1 
    id v1 freq 
1 1 a b 
2 1 b b 
3 1 b b 
4 2 c c 
5 2 c c 
6 2 c c 
+0

Penso che 'df2' sia un errore di battitura, e quando eseguo questo ottengo 'NA's per' id' = 2. – joran

+0

Grazie Joran. corretto –

+0

L'errore di battitura è scomparso, ma continuo a non pensare che questo codice funzioni. Quando id = 2, max (table (x)) restituisce 3, ma table (x) ha solo 1 nome, quindi la modalità della funzione restituisce NA. – joran

1

Un altro modo consiste nell'usare tidyverse funzioni:

  • raggruppamento decrescente utilizzando group_by(), e contando il verificarsi della seconda variabile utilizzando tally()
  • disponendo per il numero di occorrenze di arrange()
  • riepilogando e selezionando la prima riga con summarize() e first()

Pertanto:

df1 %>% 
group_by(id, v1) %>% 
tally() %>% 
arrange(id, desc(n)) %>% 
summarize(freq = first(v1)) 

Questo vi darà solo la mappatura (che trovo più pulito):

# A tibble: 2 x 2 
    id freq 
    <dbl> <fctr> 
1  1  b 
2  2  c 

È quindi possibile left_join la cornice di dati originale con quella tabella.

+0

Mi piace questo approccio perché è possibile verificare e identificare i legami dopo 'tally()'. Questo potrebbe essere possibile anche con la grande funzione di @ joran, ma non così semplice come qui, almeno per me – Tjebo