2013-08-13 2 views
10

Quando si utilizza apply su un data.frame, gli argomenti vengono convertiti (implicitamente) in caratteri. Un esempio:Come evitare la conversione implicita dei caratteri quando si utilizza apply su dataframe

df <- data.frame(v=1:10, t=1:10) 
df <- transform(df, t2 = as.POSIXlt(t, origin = "2013-08-13")) 
class(df$t2[1]) 
## [1] "POSIXct" "POSIXt" (correct) 

ma:

apply(df, 1, function(y) class(y["t2"])) 
## [1] "character" "character" "character" "character" "character" "character" 
## [7] "character" "character" "character" "character" 

C'è un modo per evitare questa conversione? O devo sempre riconvertire con lo as.POSIXlt(y["t2"])?

modificare
mio df ha 2 timestamp (diciamo, T2 e T3) e di alcuni altri settori (ad esempio, v1, v2). Per ogni riga con dato t2, voglio trovare k (ad esempio 3) righe con t3 più vicino a, ma inferiore a t2 (e lo stesso v1), e restituire una statistica su v2 da queste righe (ad esempio una media). Ho scritto una funzione f (t2, v1, df) e volevo semplicemente applicarla su tutte le righe usando apply(df, 1, function(x) f(y["t2"], y["v1"], df). C'è un modo migliore per fare cose del genere in R?

+5

La vera risposta è che non si dovrebbe usare 'apply' su un frame di dati. Cosa stai cercando di fare? – joran

+7

La * conversione * sta avvenendo perché il tuo 'data.frame' è forzato ad una' matrice '. –

+0

Per le tue modifiche hai davvero due domande diverse (IMO). Direi di porre la seconda domanda (la tua modifica) con un set di dati appropriato, ciò che hai provato e l'output desiderato. –

risposta

4

Diamo avvolgere più commenti in una spiegazione.

  1. l'uso di apply converte un data.frame ad un matrix. Questo significa che verrà utilizzata la classe meno restrittiva. Il minimo restrittivo in questo caso è carattere.
  2. Stai fornendo 1 a apply 's argomento MARGIN. Questo vale per lo per riga e ti rende ancora peggio poiché stai davvero mixando insieme le classi . In questo scenario stai utilizzando apply progettato per le matrici e data.frames su un vettore. Questo non è lo strumento giusto per il lavoro.
  3. In THS caso userei lapply o sapply come sottolinea RMK per afferrare le classi di colonna singola t2 come si vede qui sotto:

Codice:

df <- data.frame(v=1:10, t=1:10) 
df <- transform(df, t2 = as.POSIXlt(t, origin = "2013-08-13")) 

sapply(df[, "t2"], class) 
lapply(df[, "t2"], class) 

## [[1]] 
## [1] "POSIXct" "POSIXt" 
## 
## [[2]] 
## [1] "POSIXct" "POSIXt" 
## 
## [[3]] 
## [1] "POSIXct" "POSIXt" 
## 
## . 
## . 
## . 
## 
## [[9]] 
## [1] "POSIXct" "POSIXt" 
## 
## [[10]] 
## [1] "POSIXct" "POSIXt" 

In generale si sceglie la famiglia apply che si adatta al lavoro. Spesso utilizzo personalmente lo lapply o un ciclo for per agire su colonne specifiche o sottoinsieme delle colonne che voglio utilizzare l'indicizzazione ([, ]) e quindi procedere con apply. La risposta a questo problema si riduce in realtà alla determinazione di ciò che si desidera raggiungere, chiedendo è apply lo strumento più appropriato e procedere da lì.

Posso offrire questo blog post come un eccellente tutorial su ciò che fanno le diverse famiglie di funzioni apply.

+1

Il post sul blog è eccellente, ma penso che non risolva il mio problema. 'by' dovrebbe essere usato per i frame di dati, ma ho bisogno di qualcosa di più del semplice raggruppamento per v1. –

0

Prova:

sapply(df, function(y) class(y["t2"])) 

$v 
[1] "integer" 

$t 
[1] "integer" 

$t2 
[1] "POSIXct" "POSIXt" 
+1

Grazie, ma ho bisogno di applicare la mia funzione a ciascuna riga del frame di dati. Di conseguenza, voglio tante righe quante nel frame originale. –