2011-11-23 2 views
6

Ho il seguente frame e vettore di dati.Come si applica una funzione multiparametrica in R?

> y 
    v1 v2 v3 
1 1 6 43 
2 4 7 5 
3 0 2 32 

> v 
[1] 1 2 3 

voglio applicare la seguente funzione di ogni ROW nel frame di dati in modo tale che v viene aggiunto ad ogni ROW di y:

x <- function(vector1,vector2) { 
    x <- vector1 + vector2 
} 

... per vedere Questi risultati:

v1 v2 v3 
1 2 8 46 
2 5 9 8 
3 1 4 35 

mapply applica la funzione di COLONNE:

> z <- mapply(x, y, MoreArgs=list(vector2=v)) 
> z 
    v1 v2 v3 
[1,] 2 7 44 
[2,] 6 9 7 
[3,] 3 5 35 

ho provato che recepisce il frame di dati in modo che la funzione sarà applicata alle righe e non le colonne, ma mapply mi dà risultati strani dopo la trasposizione:

> transposed <- t(y) 
> transposed 
    [,1] [,2] [,3] 
v1 1 4 0 
v2 6 7 2 
v3 43 5 32 

> z <- mapply(x, transposed, MoreArgs=list(vector2=v)) 
> z 
    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] 
[1,] 2 7 44 5 8 6 1 3 33 
[2,] 3 8 45 6 9 7 2 4 34 
[3,] 4 9 46 7 10 8 3 5 35 

... Aiuto?

############################ EDIT ################# ########

Grazie per tutte le risposte! Sto imparando tonnellate di nuove funzioni R che non ho mai visto prima, il che è fantastico.

Voglio chiarire un po 'la mia domanda precedente. Quello che sto chiedendo è una domanda molto più generale - come applicare una funzione multiparametrica a ogni riga in R (al momento, sono tentato di concludere che dovrei semplicemente usare un ciclo, ma mi piacerebbe capire se è possibile, solo per riferimento futuro ...) (Mi sono anche volutamente astenuto dal mostrare il codice con cui lavoro, dato che è un po 'disordinato).

Ho provato ad utilizzare la funzione di scansione come è stato suggerito, ma ottengo il seguente errore:

testsweep <- function(vector, z, n) { 
    testsweep <- z 
} 
> n <- names(Na_exp) 
> n 
[1] "NaCl.10000.2hr.AVG_Signal" "NaCl.10000.4hr.AVG_Signal" 


> t <- head(Li_fcs,n=1) 
> t 
    LiCl.1000.1hr.FoldChange LiCl.2000.1hr.FoldChange LiCl.5000.1hr.FoldChange 
[1,]    -0.05371838    -0.1010928    -0.01939986 
    LiCl.10000.1hr.FoldChange LiCl.1000.2hr.FoldChange 
[1,]     0.1275617    -0.107154 
    LiCl.2000.2hr.FoldChange LiCl.5000.2hr.FoldChange 
[1,]    -0.06760782    -0.09770226 
    LiCl.10000.2hr.FoldChange LiCl.1000.4hr.FoldChange 
[1,]    -0.1124188    -0.06140386 
    LiCl.2000.4hr.FoldChange LiCl.5000.4hr.FoldChange 
[1,]    -0.04323497    -0.04275953 
    LiCl.10000.4hr.FoldChange LiCl.1000.8hr.FoldChange 
[1,]    0.03633496    0.01879461 
    LiCl.2000.8hr.FoldChange LiCl.5000.8hr.FoldChange 
[1,]     0.257977    -0.06357423 
    LiCl.10000.8hr.FoldChange 
[1,]    0.07214176 


> z <- colnames(Li_fcs) 
> z 
[1] "LiCl.1000.1hr.FoldChange" "LiCl.2000.1hr.FoldChange" 
[3] "LiCl.5000.1hr.FoldChange" "LiCl.10000.1hr.FoldChange" 
[5] "LiCl.1000.2hr.FoldChange" "LiCl.2000.2hr.FoldChange" 
[7] "LiCl.5000.2hr.FoldChange" "LiCl.10000.2hr.FoldChange" 
[9] "LiCl.1000.4hr.FoldChange" "LiCl.2000.4hr.FoldChange" 
[11] "LiCl.5000.4hr.FoldChange" "LiCl.10000.4hr.FoldChange" 
[13] "LiCl.1000.8hr.FoldChange" "LiCl.2000.8hr.FoldChange" 
[15] "LiCl.5000.8hr.FoldChange" "LiCl.10000.8hr.FoldChange" 

Ma quando provo ad applicare spazzata ...

> test <- sweep(t, 2, z, n, FUN="testsweep") 
Error in if (check.margin) { : argument is not interpretable as logical 
In addition: Warning message: 
In if (check.margin) { : 
    the condition has length > 1 and only the first element will be used 

quando rimuovo il n parametro da questo esempio di test, sweep funziona bene. Questo mi suggerisce che lo sweep non può essere usato a meno che tutti i parametri forniti per lo sweep siano lo stesso numero di colonne del vettore t, o della lunghezza 1. Per favore correggimi se mi sbaglio ...

risposta

0

applicare?

t(apply(y, 1, function(x) x + v)) 
    [,1] [,2] [,3] 
[1,] 2 8 46 
[2,] 5 9 8 
[3,] 1 4 35 

Non so perché applicare restituisce la riga come colonne, quindi deve essere trasposta.

+0

Vorrei dare un'occhiata a mdply forma il pacchetto plyr. Questo fa esattamente quello che chiedi. –

+0

Inutilmente dare un'occhiata a mdply forma il pacchetto plyr. Questo fa esattamente quello che chiedi. –

3

vi stiamo chiedendo di "spazzare" v attraverso le righe di y con la funzione "+":

sweep(y, 1, v, FUN="+") 
    v1 v2 v3 
1 2 7 44 
2 6 9 7 
3 3 5 35 
+0

Penso che 'MARGIN' deve essere 2 perché si desidera applicare' v' alle colonne di 'y'. –

+0

Sì. Anch'io ci ho pensato, ma abbiamo sbagliato entrambi. –

+0

Penso che lo sweep sia esattamente quello che stavo cercando. Il problema è in realtà più complesso del semplice aggiunta del vettore: l'ho usato solo come esempio poiché è stata la cosa più semplice che mi è venuta in mente. Quello che stavo davvero cercando era un modo per applicare facilmente e rapidamente una funzione multiparametrica a ogni riga - e sembra essere quello che fa lo sweep. Quindi grazie! –

2

non credo che avete bisogno di mapply qui.Basta usare t() direttamente o è possibile utilizzare rep() a fare la partita riciclaggio come si desidera:

> set.seed(1) 
> mat <- matrix(sample(1:100, 9, TRUE), ncol = 3) 
> vec <- 1:3 
> 
> mat 
    [,1] [,2] [,3] 
[1,] 27 91 95 
[2,] 38 21 67 
[3,] 58 90 63 
#Approach 1 using t() 
> ans1 <- t(t(mat) + vec) 
#Approach 2 using rep() 
> ans2 <- mat + rep(vec, each = nrow(mat)) 
#Are they the same? 
> identical(ans1, ans2) 
[1] TRUE 
#Hurray! 
> ans1 
    [,1] [,2] [,3] 
[1,] 28 93 98 
[2,] 39 23 70 
[3,] 59 92 66 
+0

+1 per il riciclaggio manuale tramite 'rep' con' each = '. –

2

Se il problema reale è in realtà non è più complicato di così, è possibile usufruire delle norme sul riciclaggio di R. È necessario trasporre prima y, quindi aggiungere, quindi trasporre il risultato perché le matrici R sono memorizzate in column-major order.

t(t(y)+v) 
    v1 v2 v3 
1 2 8 46 
2 5 9 8 
3 1 4 35 
0

Darei senz'altro un'occhiata al pacchetto pphr mdply. Questo fa esattamente quello che vuoi fare:

mdply(data.frame(mean = 1:5, sd = 1:5), rnorm, n = 2)