2015-02-04 4 views
8

dire che abbiamo questi dati:Riassumere (conteggio/frequenza) in base al tipo di trattamento in cui gli individui possono ricevere entrambi i trattamenti

dat<-data.frame(id=c(1,1,2,2,3,4,4,5,6,6),Rx=c(1,2,1,2,1,1,1,2,2,2)) 

    id Rx 
1 1 1 
2 1 2 
3 2 1 
4 2 2 
5 3 1 
6 4 1 
7 4 1 
8 5 2 
9 6 2 
10 6 2 

dove ID è il soggetto id, e Rx è il trattamento che hanno ricevuto. Quindi, ci sono osservazioni ripetute e il trattamento può o non può essere coerente per soggetto.

Voglio essere in grado di riassumere quanti soggetti ha ricevuto solo Rx 1, ha ricevuto solo Rx 2, e quanti hanno ricevuto Rx 1 e 2.

Preferirei una soluzione dplyr, ma data.table e base R sarebbe va bene anche tu Ho pensato qualcosa di simile:

dat %>% 
    group_by(id,Rx) %>% 
    unique() %>% 
    ...something 

Il risultato finale dovrebbe essere qualcosa di simile:

Rx Count 
    1  2 
    2  2 
Both  2 

Grazie!

+0

Vuoi che la soluzione si generalizzi a più di due tipi di trattamenti? – davechilders

+0

Il vero problema ha solo due trattamenti quindi non è terribile che si generalizzi, ma come esperienza di apprendimento e per un'applicazione successiva sarebbe apprezzato se generalizzato a> 2 trattamenti. –

risposta

5

Ecco un'altra soluzione generalizzata

library(dplyr) 
dat %>% 
    group_by(id) %>% 
    summarise(indx = toString(sort(unique(Rx)))) %>% 
    ungroup() %>% 
    count(indx) 

# Source: local data table [3 x 2] 
# 
# indx n 
# 1 1, 2 2 
# 2 1 2 
# 3 2 2 

Con data.table, simile

library(data.table) 
setDT(dat)[, .(indx = toString(sort(unique(Rx)))), id][ , .N, indx] 
3

Questa soluzione fa non generalizzare bene a più di 2 trattamenti:

library(dplyr) 

dat %>% 
    distinct(id, Rx) %>% 
    group_by(id) %>% 
    mutate(
    trt1 = setequal(1, Rx), # change due to comment from @Marat Talipov 
    trt2 = setequal(2, Rx), 
    both = setequal(1:2, Rx) 
    ) %>% 
    ungroup() %>% 
    distinct(id) %>% 
    summarise_each(funs(sum), trt1:both) 

Questa soluzione è più breve e non generalizzare a più di un trattamento:

library(stringr) 

dat %>% 
    group_by(id) %>% 
    mutate(
    rx_list = str_c(sort(unique(Rx)), collapse = ",") 
    ) %>% 
    distinct(id) %>% 
    count(rx_list) 
+1

Re prima soluzione: puoi usare 'setequal (XXX, dat $ Rx)' (XXX potrebbe essere 1, 2 o c (1,2)) invece di '% in%' –

+0

Questo non è completamente corretto se il trattamento l'ordine non era lo stesso Cioè per questo set di dati fornirà un duplicato 'dat <-data.frame (id = c (1,1,2,2,3,4,4,5,6,6), Rx = c (2,1, 1,2,1,1,1,2,2,2)) " –

+0

@DMC, per la seconda soluzione, se l'ordine va da 1,2 a 2,1, si formano gruppi separati. Funziona se si modifica 'rx_list' in' rx_list = str_c (sort (Rx), collapse = ",") ' –

2

Non esattamente l'output è stato indicato, ma è di base R, one-liner e generale:

table(do.call(function(...) paste(...,sep="_"),as.data.frame(table(dat)>0))) 
#FALSE_TRUE TRUE_FALSE TRUE_TRUE 
    2   2   2 

Se i trattamenti sono più di due, hanno indicato tutte le possibili combinazioni.

+0

Oppure, per una tabella di output leggermente diversa (interazione (come.data.frame (tabella (dat)> 0))) ' –