Domanda

Devo ammettere di essere completamente pazzo quando cerco di capire come le funzioni all'interno delle funzioni vengono definite e passate in R.Gli esempi presuppongono sempre che tu comprenda ogni sfumatura e non forniscono descrizioni del processo.Devo ancora imbattermi in una guida in inglese semplice e idiota che spiega il processo.Quindi la prima domanda è: ne conosci uno?

Adesso il mio problema fisico.
Ho un elenco di data.frames:fileData.
Voglio utilizzare la funzione rollapply() su colonne specifiche in ciascun data.frame.Voglio quindi che tutti i risultati (elenchi) siano combinati.Quindi, iniziando con uno dei data.frames utilizzando i dataframe mtcars integrati come esempio:

Ovviamente devo dire a rollapply() di utilizzare la funzione PPI() insieme ai parametri associati che sono le colonne.

PPI <- function(a, b){  
    value = (a + b)  
    PPI = sum(value)  
    return(PPI)  
}

Ho provato questo:

f <- function(x) PPI(x$mpg, x$disp)
fileData<- list(mtcars, mtcars, mtcars)
df <- fileData[[1]]

e mi sono fermato

rollapply(df, 20, f)
Error in x$mpg : $ operator is invalid for atomic vectors  

Penso che questo sia correlato allo Zoo che utilizza le matrici, ma altri numerosi tentativi non sono riusciti a risolvere il problema del rollapply.Quindi passiamo a ciò che credo sia il prossimo:

lapply(fileData, function(x) rollapply ......

Sembra un miglio di distanza.Alcune indicazioni e soluzioni sarebbero molto gradite.
Grazie.

È stato utile?

Soluzione 3

Ho sudato via e ho impiegato un po 'di tempo per capire lentamente come abbattere il processo e il protocollo di chiamare una funzione con argomenti da un'altra funzione.Un ottimo sito che ha aiutato era avanzato r daL'unico e unico Hadley Wickham, di nuovo!Le immagini che mostrano la rottura del processo sono vicine all'ideale.Anche se avevo ancora bisogno del mio tappo di pensiero per alcuni dettagli.

Ecco un esempio completo con le note.Speriamo che qualcun altro lo trovi utile.

library(zoo)

#Create a list of dataframes for the example.
listOfDataFrames<- list(mtcars, mtcars, mtcars)
#Give each element a name.
names(listOfDataFrames) <- c("A", "B", "C")

#This is a simple function just for the example!
#I want to perform this function on column 'col' of matrix 'm'.
#Of course to make the whole task worthwhile, this function is usually something more complex.
fApplyFunction <- function(m,col){
    mean(m[,col])
}

#This function is called from lapply() and does 'something' to the dataframe that is passed.
#I created this function to keep lapply() very simply.
#The something is to apply the function fApplyFunction(), wich requires an argument 'thisCol'. 
fOnEachElement <- function(thisDF, thisCol){
    #Convert to matrix for zoo library.
    thisMatrix <- as.matrix(thisDF)
    rollapply(thisMatrix, 5, fApplyFunction, thisCol, partial = FALSE, by.column = FALSE)
}

#This is where the program really starts!
#
#Apply a function to each element of list.
#The list is 'fileData', with each element being a dataframe.
#The function to apply to each element is 'fOnEachElement'
#The additional argument for 'fOnEachElement' is "vs", which is the name of the column I want the function performed on.
#lapply() returns each result as an element of a list.
listResults <- lapply(listOfDataFrames, fOnEachElement, "vs")


#Combine all elements of the list into one dataframe.
combinedResults <- do.call(cbind, listResults)

#Now that I understand the argument passing, I could call rollapply() directly from lapply()...
#Note that ONLY the additional arguments of rollapply() are passed. The primary argurment is passed automatically by lapply().
listResults2 <- lapply(listOfDataFrames, rollapply, 5, fApplyFunction, "vs", partial = FALSE, by.column = FALSE)
.

Risultati:

> combinedResults
        A   B   C
 [1,] 0.4 0.4 0.4
 [2,] 0.6 0.6 0.6
 [3,] 0.6 0.6 0.6
 [4,] 0.6 0.6 0.6
 [5,] 0.6 0.6 0.6
 [6,] 0.8 0.8 0.8
 [7,] 0.8 0.8 0.8
 [8,] 0.8 0.8 0.8
 [9,] 0.6 0.6 0.6
[10,] 0.4 0.4 0.4
[11,] 0.2 0.2 0.2
[12,] 0.0 0.0 0.0
[13,] 0.0 0.0 0.0
[14,] 0.2 0.2 0.2
[15,] 0.4 0.4 0.4
[16,] 0.6 0.6 0.6
[17,] 0.8 0.8 0.8
[18,] 0.8 0.8 0.8
[19,] 0.6 0.6 0.6
[20,] 0.4 0.4 0.4
[21,] 0.2 0.2 0.2
[22,] 0.2 0.2 0.2
[23,] 0.2 0.2 0.2
[24,] 0.4 0.4 0.4
[25,] 0.4 0.4 0.4
[26,] 0.4 0.4 0.4
[27,] 0.2 0.2 0.2
[28,] 0.4 0.4 0.4
> listResults
$A
 [1] 0.4 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 0.8 0.6
[20] 0.4 0.2 0.2 0.2 0.4 0.4 0.4 0.2 0.4

$B
 [1] 0.4 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 0.8 0.6
[20] 0.4 0.2 0.2 0.2 0.4 0.4 0.4 0.2 0.4

$C
 [1] 0.4 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 0.8 0.6
[20] 0.4 0.2 0.2 0.2 0.4 0.4 0.4 0.2 0.4

> listResults2
$A
 [1] 0.4 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 0.8 0.6
[20] 0.4 0.2 0.2 0.2 0.4 0.4 0.4 0.2 0.4

$B
 [1] 0.4 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 0.8 0.6
[20] 0.4 0.2 0.2 0.2 0.4 0.4 0.4 0.2 0.4

$C
 [1] 0.4 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 0.8 0.6
[20] 0.4 0.2 0.2 0.2 0.4 0.4 0.4 0.2 0.4
.

Altri suggerimenti

Proverò ad aiutarti e mostrare come puoi eseguire il debug del problema. Un trucco che è molto utile in r è quello di imparare come eseguire il debug. Greelly sto usando la funzione browser.

Problema:

Qui sto cambiando per funzionare f aggiungendo una riga:

f <- function(x) {
  browser()
  PPI(x$changeFactor_A, x$changeFactor_B)
}
.

Ora quando corri:

rollapply(df, 1, f)
.

Il debugger si arresta e puoi ispezionare il valore dell'argomento X:

Browse[1]> x
 [1,] 
1e+05 
.

Come vedi è un valore scalare, quindi non è possibile applicare l'operatore $ su di esso, quindi ottieni l'errore:

Error in x$changeFactor_A : $ operator is invalid for atomic vectors 
.

Guide generali

Ora spiegherò come dovresti farlo.

    .
  • O si modifica la funzione PPI, per avere un singolo parametro excees: in modo da fare la sottrazione al di fuori di esso (più facile)
  • o si utilizza mapply per ottenere una soluzione generalizzata. (Più difficile ma più generale e molto utile)
  • Evita di utilizzare $ all'interno delle funzioni. Personalmente, lo uso solo sulla console r.

Soluzione completa:

Suppongo che tu sia dati. I fotogrammi (Zoo Objects) hanno ChangeFactor_A e ChangeFactor_b colonne.

sapply(fileData,function(dat){
  dat <- transform(dat,excess= changeFactor_A-changeFactor_B)
  rollapply(dat[,'excess'],2,sum)
}
.

o più Generalmente:

sapply(fileData,function(dat){
  excess <- get_excess(dat,'changeFactor_A','changeFactor_B')
  rollapply(excess,2,sum)
}
.

dove

   get_excess <- 
     function(data,colA,colB){
          ### do whatever you want here
          ### return a vector
          excess
     }
.

Consulta la sezione "Utilizzo" della pagina della guida ?rollapply.Devo ammettere che le pagine della guida di R non sono facili da analizzare e vedo come ti sei confuso.

Il problema è che rollapply può affrontare ts, zoo o generale numeric vettori, ma solo una singola serie.Gli stai alimentando una funzione che richiede due argomenti, asset E benchmark.Certo, il tuo f E PPI può essere banalmente vettorizzato, ma rollapply semplicemente non è fatto per quello.

Soluzione:calcola il tuo excess al di fuori rollapply (excess è facilmente calcolato vettorialmente e non comporta alcun calcolo rolling), e solo allora rollapply la tua funzione:

> mtcars$excess <- mtcars$mpg-mtcars$disp
> rollapply(mtcars$excess, 3, sum)
 [1]  -363.2  -460.8  -663.1  -784.8  -893.9 ...

Potrebbe interessarti mapply, che vettorizza una funzione per multiplo argomenti, in modo simile a apply e amici, su cui lavorare separare argomenti.Tuttavia, non conosco alcun analogo di mapply con rotolamento finestre.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top