matrix comandi - Tutti i livelli di un fattore in una matrice modello in R




manuale con (8)

model.matrix(~ First + Second + Third + Fourth + Fifth - 1, data=testFrame)

o

model.matrix(~ First + Second + Third + Fourth + Fifth + 0, data=testFrame)

dovrebbe essere il più diretto

F

Ho un data.frame costituito da variabili numeriche e fattoriali come visto di seguito.

testFrame <- data.frame(First=sample(1:10, 20, replace=T),
           Second=sample(1:20, 20, replace=T), Third=sample(1:10, 20, replace=T),
           Fourth=rep(c("Alice","Bob","Charlie","David"), 5),
           Fifth=rep(c("Edward","Frank","Georgia","Hank","Isaac"),4))

Voglio costruire una matrix che assegni le variabili dummy al fattore e lasci da solo le variabili numeriche.

model.matrix(~ First + Second + Third + Fourth + Fifth, data=testFrame)

Come previsto quando si esegue lm questo lascia un livello di ciascun fattore come livello di riferimento. Tuttavia, voglio costruire una matrix con una variabile dummy / indicatore per ogni livello di tutti i fattori. Sto costruendo questa matrice per glmnet quindi non sono preoccupato per la multicollinearità.

C'è un modo per avere model.matrix creare il manichino per ogni livello del fattore?


È necessario ripristinare i contrasts per le variabili fattore:

model.matrix(~ Fourth + Fifth, data=testFrame, 
        contrasts.arg=list(Fourth=contrasts(testFrame$Fourth, contrasts=F), 
                Fifth=contrasts(testFrame$Fifth, contrasts=F)))

o, con un po 'meno di battitura e senza i nomi propri:

model.matrix(~ Fourth + Fifth, data=testFrame, 
    contrasts.arg=list(Fourth=diag(nlevels(testFrame$Fourth)), 
            Fifth=diag(nlevels(testFrame$Fifth))))

Ok. Basta leggere quanto sopra e mettere tutto insieme. Supponiamo di volere la matrice, ad esempio "X.factors", che si moltiplica per il vettore del coefficiente per ottenere il predittore lineare. Ci sono ancora un paio di passaggi aggiuntivi:

X.factors = 
  model.matrix( ~ ., data=X, contrasts.arg = 
    lapply(data.frame(X[,sapply(data.frame(X), is.factor)]),
                                             contrasts, contrasts = FALSE))

(Notare che è necessario trasformare X [*] di nuovo in un frame di dati nel caso in cui si disponga di una sola colonna del fattore.)

Quindi dì che ottieni qualcosa del genere:

attr(X.factors,"assign")
[1]  0  1  **2**  2  **3**  3  3  **4**  4  4  5  6  7  8  9 10 #emphasis added

Vogliamo sbarazzarci dei ** ** livelli di riferimento di ciascun fattore

att = attr(X.factors,"assign")
factor.columns = unique(att[duplicated(att)])
unwanted.columns = match(factor.columns,att)
X.factors = X.factors[,-unwanted.columns]
X.factors = (data.matrix(X.factors))


Utilizzo del pacchetto R "CatEncoders"

library(CatEncoders)
testFrame <- data.frame(First=sample(1:10, 20, replace=T),
           Second=sample(1:20, 20, replace=T), Third=sample(1:10, 20, replace=T),
           Fourth=rep(c("Alice","Bob","Charlie","David"), 5),
           Fifth=rep(c("Edward","Frank","Georgia","Hank","Isaac"),4))

fit <- OneHotEncoder.fit(testFrame)

z <- transform(fit,testFrame,sparse=TRUE) # give the sparse output
z <- transform(fit,testFrame,sparse=FALSE) # give the dense output

(Cercando di riscattarmi ...) In risposta al commento di Jared sulla risposta di @Fabians sull'automazione, si noti che tutto ciò che è necessario fornire è una lista nominata di matrici di contrasto. contrasts() prende un vettore / fattore e produce la matrice di contrasti da esso. Per questo quindi possiamo usare lapply() per eseguire contrasts() su ogni fattore nel nostro set di dati, ad esempio per l'esempio testFrame fornito:

> lapply(testFrame[,4:5], contrasts, contrasts = FALSE)
$Fourth
        Alice Bob Charlie David
Alice       1   0       0     0
Bob         0   1       0     0
Charlie     0   0       1     0
David       0   0       0     1

$Fifth
        Edward Frank Georgia Hank Isaac
Edward       1     0       0    0     0
Frank        0     1       0    0     0
Georgia      0     0       1    0     0
Hank         0     0       0    1     0
Isaac        0     0       0    0     1

Quale slot ben inserito nella risposta di @fabians:

model.matrix(~ ., data=testFrame, 
             contrasts.arg = lapply(testFrame[,4:5], contrasts, contrasts=FALSE))

caret implementato una bella funzione dummyVars per ottenere questo risultato con 2 linee:

library(caret) dmy <- dummyVars(" ~ .", data = testFrame) testFrame2 <- data.frame(predict(dmy, newdata = testFrame))

Controllo delle colonne finali:

colnames(testFrame2)

"First"  "Second"         "Third"          "Fourth.Alice"   "Fourth.Bob"     "Fourth.Charlie" "Fourth.David"   "Fifth.Edward"   "Fifth.Frank"   "Fifth.Georgia"  "Fifth.Hank"     "Fifth.Isaac"   

Il punto più bello qui è ottenere il frame di dati originale, oltre alle variabili dummy che hanno escluso quelle originali utilizzate per la trasformazione.

Maggiori informazioni: http://amunategui.github.io/dummyVar-Walkthrough/


Tutto ciò che è logico aziendale appartiene a un modello, sia che si tratti di una query di database, di calcoli, di una chiamata REST, ecc.

Puoi avere l'accesso ai dati nel modello stesso, il pattern MVC non ti impedisce di farlo. Puoi rivestirlo di zucchero con servizi, mappatori e cosa no, ma la definizione attuale di un modello è un livello che gestisce la logica di business, niente di più, niente di meno. Può essere una classe, una funzione o un modulo completo con un oggetto di miliardi se è quello che vuoi.

È sempre più semplice avere un oggetto separato che esegua effettivamente le query del database anziché eseguirle direttamente nel modello: questo sarà particolarmente utile quando si esegue il test delle unità (a causa della facilità di iniettare una dipendenza del database fittizio nel modello):

class Database {
   protected $_conn;

   public function __construct($connection) {
       $this->_conn = $connection;
   }

   public function ExecuteObject($sql, $data) {
       // stuff
   }
}

abstract class Model {
   protected $_db;

   public function __construct(Database $db) {
       $this->_db = $db;
   }
}

class User extends Model {
   public function CheckUsername($username) {
       // ...
       $sql = "SELECT Username FROM" . $this->usersTableName . " WHERE ...";
       return $this->_db->ExecuteObject($sql, $data);
   }
}

$db = new Database($conn);
$model = new User($db);
$model->CheckUsername('foo');

Inoltre, in PHP, raramente devi catturare / rilanciare le eccezioni perché il backtrace è preservato, specialmente in un caso come il tuo esempio. Fai in modo che l'eccezione sia lanciata e catturala nel controller.





r matrix model indicator