Seite 1 von 1

Effizientes Programmieren

Verfasst: So Mai 23, 2021 3:46 pm
von TopProtet
Ich habe folgende Aufgabe bekommen und komme aktuell nicht weiter:

Schreiben Sie eine Funktion sillyzv( ), welche die folgenden Argumente hat:
• n: Skalar, der die Anzahl der Beobachtungen pro Variable angibt.
• k: Skalar, der die Anzahl der Variablen angibt.
• mean: Vektor der Länge k (oder geeignet wiederholbar), der die Mittelwerte der Variablen enthält.
• sd: Vektor der Länge k (oder geeignet wiederholbar), der die Standardabweichung der Variablen enthält.

Die Funktion soll entsprechend Beobachtungen aus der Normalverteilung ziehen und eine Matrix zurückgeben, die n Zeilen fu ̈r die Beobachtungen und k Spalten für die Variablen hat. Die Mittelwerte und Standardabweichungen in den Spalten variieren je nach mean und sd.

Dies soll ich im ersten Schritt möglichst ineffizient gestalten indem ich die Ergebnismatrix für jede Variable spaltenweise dynamisch erweitere. Ich soll dabei jedoch keine unnötigen Dinge tun und die n Beobachtungen pro Variable mit einem Aufruf erzeugen.

Danach soll ich, smartzv() möglichst effizient programmieren, d.h. die Ergebnismatrix möglichst mit einem vektorwertigen Aufruf erzeugen.

Meine erste Funktion sieht folgendermaßen aus (wobei ich mir sehr unsicher bin):

Code: Alles auswählen

sillyzv <- function(n,k,mean,sd){
  
  m<-matrix("numeric",nrow = n,ncol=k)
  for (i in 1:k) {
    assign(paste("x", i,sep = ""),rnorm(n = n,mean = mean[i],sd = sd[i]))
    m[,i]<-cbind(get(paste("x",i,sep="")))
  }
  return (m)
}

Die "effiziente" Methode hab ich folgendermaßen probiert, leider stimmen die Ergebnisse nicht überein:

Code: Alles auswählen

smartzv <- function(n,k,mean,sd){

  m<-matrix("numeric",nrow = n,ncol=k)
  m[,1:k]<-rnorm(n = n,mean = mean[1:k],sd[1:k] = sd)
  return(m)
}
Könnte mir jemand Tipps geben bezüglich der beiden Funktionen bzw. was ich falsch gemacht habe?
Vielen Dank!

Re: Effizientes Programmieren

Verfasst: So Mai 23, 2021 10:16 pm
von EDi
Idee:

Alles in einem Aufwasch aus einer multivariaten Normalverteilung ziehen.

Geht mit mvtnorm::rmvnorm https://www.rdocumentation.org/packages ... ics/Mvnorm

n ist klar,
k kann man weglassen (weil gleich länge mean)
mean kann 1:1 übernommen werden (oder halt k-mal wiederholen.
sigma ist eine matrix mit sd^2 auf der Diagonalen und sonst 0 (geht mit ?diag), damit man unabhängige Variablen hat.

Sollte recht performant sein - weiß aber nicht ob es schneller ist also jede variablen einzeln aus der univariaten Normalverteilung zu ziehen.

Re: Effizientes Programmieren

Verfasst: So Mai 23, 2021 10:49 pm
von EDi
Habs überprüft. Mapply ist schneller (weil mvtnorm noch die Kovarianzmatrix zerlegen muss).
Am schnellsten ist es aber nur einen rnorm aufruf zu haben und dann in eine Matrix zu packen.

Code: Alles auswählen

library(mvtnorm)
library(bench)

mv <- function(n = 10000, mean = c(10, 0), sd = c(1, 0.1)) {
  mvtnorm::rmvnorm(n, mean = mean, sigma = diag(sd^2), method = "chol")
}
mv()

individual <- function(n = 10000, mean = c(10, 0), sd = c(1, 0.1)) {
  mapply(rnorm, mean = mean, sd = sd, MoreArgs = list(n = n))
}
individual()

direct <- function(n = 10000, mean = c(10, 0), sd = c(1, 0.1)) {
  k <- length(mean)
  v <- rnorm(n * k, mean = mean, sd = sd)
  matrix(v, ncol = k, byrow = TRUE)
}
direct()

check <- function(mat) {
  list(means = apply(mat, 2, mean),
       sds = apply(mat, 2, sd))
}

check(mv())
check(individual())
check(direct())


bench::mark(mv(n = 10), individual(n = 10), direct(n = 10), check = FALSE)
bench::mark(mv(n = 10000), individual(n = 10000), direct(n = 10000), check = FALSE)
bench::mark(mv(n = 100000), individual(n = 100000), direct(100000), check = FALSE)



Zu deinem Code:
möglichst ineffizient gestalten indem ich die Ergebnismatrix für jede Variable spaltenweise dynamisch erweitere.
Macht das denn dein Code? Für mich sieht das so aus, dass du die Matrix schon vorher in ihrer Endgröße erstellst, oder?
Die "effiziente" Methode hab ich folgendermaßen probiert, leider stimmen die Ergebnisse nicht überein:
Ich bekomme da einen Fehler:

Code: Alles auswählen

Error: unexpected '=' in "rnorm(n = n,mean = mean[1:k],sd[1:k] ="
Kann also gar nicht die Ergebnisse vergleichen?!

Vermutlich wegen dem "sd[1:k] =". rnorm hat kein Argument "sd[1:k]", nur "sd". Hast du hier was verdreht? Ansonsten ist das ähnlich zu meiner direct() Function, außer dass ich die matrix erst danach erstelle.