2013-02-26 10 views
9

questa domanda è in qualche modo correlata a questo one, tuttavia voglio creare un indice utilizzando una combinazione unica di due colonne data.frame. Così la mia struttura di dati sembra per esempio come questo (dput):Creare un indice di una combinazione di colonne data.frame in R

structure(list(avg = c(0.246985988921473, 0.481522354272779, 
0.575400762275067, 0.14651009243539, 0.489308880181752, 0.523678968337178 
), i_ID = c("H", "H", "C", "C", "H", "S"), j_ID = c("P", "P", 
"P", "P", "P", "P")), .Names = c("avg", "i_ID", "j_ID"), row.names = 7:12, class = "data.frame") 

L'indice creato per la struttura di cui sopra dovrebbe quindi apparire così

1 
1 
2 
2 
1 
3 

Nei dati esempio la colonna j_ID ha sempre il valore P, ma questo non è sempre il caso. Inoltre le combinazioni vice-versa (S-P o P-S) dovrebbero risultare nello stesso indice.

Qualcuno conosce un buon modo per farlo? Posso farlo con molti comandi for-loops e if-else, ma questo non è molto elegante.

risposta

5

La funzione interaction funzionerà correttamente.

foo = structure(list(avg = c(0.246985988921473, 0.481522354272779, 0.575400762275067, 0.14651009243539, 0.489308880181752, 0.523678968337178), i_ID = c("H", "H", "C", "C", "H", "S"), j_ID = c("P", "P", "P", "P", "P", "P")), .Names = c("avg", "i_ID", "j_ID"), row.names = 7:12, class = "data.frame") 

foo$idx <- as.integer(interaction(foo$i_ID, foo$j_ID)) 

> foo 
     avg i_ID j_ID idx 
7 0.2469860 H P 2 
8 0.4815224 H P 2 
9 0.5754008 C P 1 
10 0.1465101 C P 1 
11 0.4893089 H P 2 
12 0.5236790 S P 3 

Ah, non ho letto con sufficiente attenzione. C'è probabilmente una soluzione più elegante, ma è possibile utilizzare la funzione outer e triangoli superiore ed inferiore:

# lets assign some test values 
x <- c('a', 'b', 'c') 
foo$idx <- c('a b', 'b a', 'b c', 'c b', 'a a', 'b a') 

mat <- outer(x, x, FUN = 'paste') # gives all possible combinations 
uppr_ok <- mat[upper.tri(mat, diag=TRUE)] 
mat_ok <- mat 
mat_ok[lower.tri(mat)] <- mat[upper.tri(mat)] 

Quindi è possibile abbinare gli indici si trovano in mat con quelli trovati in mat_ok.

foo$idx <- mat_ok[match(foo$idx, mat)] 

Ma ... scommetto v'è una comoda funzione che mi manca ...

+0

> Inoltre viceversa (S-P o P-S) dovrebbe comportare lo stesso indice. – krlmlr

+1

Non vedo che rispetterà l'altro vincolo che S-P e P-S hanno lo stesso indice. –

+0

Sì, in effetti funziona abbastanza bene, tuttavia, come ha detto Gavin, non fornisce lo stesso indice vice versa – Curlew

1

Questo dovrebbe essere un commento a @ risposta di Justin, ma è troppo lungo :)

se desiderare che gli indici conservino l'ordine dell'originale di i_ID, è possibile assegnare i risultati interaction() a una variabile e quindi a il numero levels.

x <- interaction(foo$i_ID, foo$j_ID) 
x <- factor(x, levels=levels(x)[order(unique(foo$i_ID))]) 

foo$idx <- as.integer(x) 

che assicura: combinazioni

> foo 
     avg i_ID j_ID idx 
7 0.2469860 H P 1 
8 0.4815224 H P 1 
9 0.5754008 C P 2 
10 0.1465101 C P 2 
11 0.4893089 H P 1 
12 0.5236790 S P 3 
Problemi correlati