2015-03-05 12 views
6

Ho visto un post simile su questo argomento, ma non sono riuscito a comprendere la soluzione. Essenzialmente ho una tabella dati (DT1) con punteggi e alcune NA. Ovunque ci sia un 'NA' mi piacerebbe un processo che faccia riferimento a un'altra tabella di dati (DT2) che abbia una colonna comune in entrambe le tabelle (tratto) e quindi aggiorni l'NA in DT1 con il valore della colonna del punteggio di DT2. Sto scegliendo una classe data table perché penso che sia un'opzione efficiente.Aggiornare una colonna di NA in una tabella di dati con il valore di una colonna in un'altra tabella di dati

DT1

  tract CreditScore  
1: 36107020401   635 
2: 36083052403   NA 
3: 36091062602   NA 
4: 36067013000   NA 
5: 36083052304   NA 

DT2

  tract CreditScore 
1: 36107020401   635 
2: 36083052403   650 
3: 36091062602   335 
4: 36067013000   777 
5: 36083052304   663 
+0

Se si utilizza il pacchetto 'data.table', è necessario chiarirlo nella domanda. Non mi è chiaro se intendi una struttura dati specifica per 'data.table' o la struttura di base' data.frame'. C'è un motivo (come problemi di dimensioni/memoria) non puoi semplicemente unire le due tabelle e usare 'ifelse()' per creare una nuova colonna che abbia il valore appropriato? –

+1

@Alex, sì, c'è. Poteva anche caricare i dati in Excel e fare un 'vlookup', vero? In particolare, 'data.table' può eseguire un join * binary * e aggiornare le colonne * per riferimento durante l'unione *. Ciò sarebbe più efficiente di "unire" + "ifelse" da diversi fattori su un grande insieme di dati. –

+0

Grazie per i vostri commenti. Sì, il motivo principale per cui scelgo di utilizzare il pacchetto data.table è la sua efficienza complessiva. Non volevo aggiungere un'altra colonna a DT1 se non ne avessi avuto bisogno. Proverò la risposta qui sotto e vedrò come funziona ..... grazie e grazie! – user3067851

risposta

9

Abbiamo creato nuovo (e più completo) HTML vignettes per alcuni dei concetti data.table. Date un'occhiata allo here per le altre vignette su cui stiamo lavorando. Sto lavorando a delle vignette per i join, che una volta terminate, si spera che chiariscano meglio questo tipo di problemi.


L'idea è di primo setkey() sul DT1 sulla colonna tract.

setkey(DT1, tract) 

In data.tables, un join della forma x[i] richiede chiave per x, ma non necessariamente per i. Ciò si traduce in due scenari:

  • Se i ha anche set di chiavi - la prima colonna chiave di i è confrontato prima colonna chiave di x, secondo contro la seconda e così via ..

  • Se i non dispone del set di chiavi - la prima colonna di i viene confrontato con il primo chiave colonna x, seconda colonna della i contro la seconda chiave colonna x e così via ..

In questo caso, poiché la vostra prima colonna i è anche tract, faremo saltare l'impostazione della chiave i.

Quindi, eseguiamo un join del modulo x[i]. In questo modo, per ogni i vengono calcolati gli indici di riga corrispondenti in x e quindi il risultato del join viene materializzato. Tuttavia, non vogliamo che l'intero risultato del join sia un nuovo data.table. Piuttosto, vogliamo aggiornare DT1 's CreditScore colonna con DT2' s su tali righe corrispondenti ..

In data.tables, possiamo eseguire tale operazione mentre unione, fornendo l'espressione in j, come segue:

DT1[DT2, CreditScore := i.CreditScore] 
#   tract CreditScore 
# 1: 36067013000   777 
# 2: 36083052304   663 
# 3: 36083052403   650 
# 4: 36091062602   335 
# 5: 36107020401   635 

DT1[DT2 parte rileva le righe corrispondenti in DT1 per ogni riga DT2. E se c'è una corrispondenza, vogliamo che il valore di DT2 sia aggiornato in DT1.Lo realizziamo usando i.CreditScore - si riferisce alla colonna DT2CreditScore (i. è un prefisso utilizzato per distinguere le colonne con nomi identici tra x e i data.tables).


Aggiornamento: Come sottolineato in commenti, la soluzione di cui sopra potrebbe anche aggiornare i valori non-NA in DT1. Quindi il modo per farlo sarebbe:

DT1[is.na(CreditScore), CreditScore := DT2[.(.SD), CreditScore]] 

Per questi righe dove CreditScore da DT1 è NA, sostituire CreditScore da DT1 con i valori da CreditScore ottenuta dal punto di giunzione di DT2[.(.SD)], dove .SD corrisponde al sottoinsieme dei dati .table che contiene tutte le righe in cui CreditScore è NA.

HTH

+0

Ho ragione che questo utilizza 'CreditScore' da' DT2' per ogni 'trattino' corrispondente? Come ho capito l'OP, il valore 'DT2' dovrebbe essere preso solo se è' NA' in 'DT1'. Nell'esempio fornito, non ha importanza in quanto è 635 in entrambe le tabelle per il record comune. Se erano diversi, come si poteva conservare il valore 'DT1'? – DaveTurek

+0

@DaveTurek, giusto, grazie. Aggiornato ora. – Arun

+1

Mi viene detto che '.SD' è bloccato quando si tenta di implementare questa soluzione. – MichaelChirico