2013-08-05 8 views
8

consideri il seguente frame di dati:Impostare valore di colonna da una raccolta di altre colonne selezionate da una colonna selettore su una base fila per riga (eseguendo una ricerca)

TEST <- structure(list(Value = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), 
    Select = structure(c(2L, 1L, 3L, 2L, 2L, 1L, 1L, 
    2L, 1L, 1L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), 
    A = c(5L, 5L, 4L, 3L, 4L, 3L, 5L, 3L, 3L, 4L, 5L, 4L), 
    B = c(10L, 8L, 7L, 6L, 3L, 8L, 8L, 7L, 8L, 9L, 11L, 8L), 
    C = c(0L, 1L, 3L, 2L, 0L, 3L, 0L, 2L, 0L, 1L, 1L, 0L)), 
    .Names = c("Value", "Select", "A", "B", "C"), 
    row.names = c(NA, -12L), 
    class = "data.frame") 

voglio assegnare efficientemente Valore colonna, riga per riga, dal set di colonne A, B e C in base alla colonna Seleziona.

Ad esempio, nella riga 1 voglio che il valore sia uguale all'elemento nella colonna B - cioè il valore [1] = 10.

mio attuale metodo è quello di utilizzare un ciclo for:

for(idx in 1:nrow(TEST)) { 
    TEST$Value[idx] <- TEST[ idx, as.character(TEST$Select[idx]) ] 
} 

che si traduce in output desiderato:

 
    Value Select A B C 
1  10  B 5 10 0 
2  5  A 5 8 1 
3  3  C 4 7 3 
4  6  B 3 6 2 
5  3  B 4 3 0 
6  3  A 3 8 3 
7  5  A 5 8 0 
8  7  B 3 7 2 
9  3  A 3 8 0 
10  4  A 4 9 1 
11  1  C 5 11 1 
12  0  C 4 8 0 

C'è un modo più efficiente o alternativo di fare questo? Ritengo che si tratti di un'operazione di tipo merge() o join di tabella.

P.S. Non ero abbastanza sicuro di come descrivere questa operazione - anche i suggerimenti per una migliore domanda/descrizione sono ben accetti.

+0

RE: tuo PS, credo * ricerca * potrebbe essere il termine appropriato – flodel

risposta

7

Vorrei utilizzare indicizzazione matrice e match. Questo approccio è vettorializzare, e quindi molto più veloce di un ciclo for o apply darebbe:

L <- c("A", "B", "C") 
TEST$Value <- TEST[L][cbind(seq_len(nrow(TEST)), match(TEST$Select, L))] 

Se non si ha familiarità con la matrice di indicizzazione, è documentato all'interno ?"[":

Una terza forma di indicizzazione è tramite una matrice numerica con una colonna per ogni dimensione: ogni riga della matrice dell'indice seleziona quindi un singolo elemento dell'array, e il risultato è un vettore

+0

È incredibile, non ho mai usato l'indicizzazione della matrice prima d'ora. Il trucco nell'usare match() è anche molto intelligente, specialmente perché non fallisce se non c'è una colonna corrispondente. – Simon

Problemi correlati