wake-up-neo.com

Schnelles Ersetzen von Werten in Dataframe in R

Ich habe ein Datenfeld von 150.000 Zeilen mit 2.000 Spalten, die Werte enthalten, von denen einige negative Werte sind. Ich ersetze diese negativen Werte durch 0, ist aber extrem langsam (~ 60min oder mehr). 

df[df < 0] = 0

wobei df[,1441:1453] so aussieht (alle Spalten/Werte numerisch):

  V1441 V1442 V1443 V1444 V1445 V1446 V1447 V1448 V1449 V1450 V1451 V1452 V1453
1     3     1     0     4     4    -2     0     3    12     5    17    34    27
2     0     1     0     7     0     0     0     1     0     0     0     0     0
3     0     2     0     1     2     3     6     1     2     1    -6     3     1
4     1     2     3     6     1     2     1    -6     3     1    -4     1     0
5     1     2     1    -6     3     1    -4     1     0     0     1     0     0
6     1     0     0     1     0     0     0     0     0     0     1     2     2

Gibt es eine Möglichkeit, diesen Prozess zu beschleunigen, z. B. ist meine Vorgehensweise extrem langsam, und es gibt einen schnelleren Ansatz dafür? Vielen Dank.

19
Benoit B.

Versuchen Sie, Ihre DF in eine Matrix umzuwandeln.

df <- data.frame(a=rnorm(1000),b=rnorm(1000))
m <- as.matrix(df)
m[m<0] <- 0
df <- as.data.frame(m)
30
Roland

Sowohl Ihr ursprünglicher Ansatz als auch die aktuelle Antwort erstellen ein Objekt mit derselben Größe wie m (oder df), wenn Sie m<0 erstellen (der Matrix-Ansatz ist schneller, da mit [<- weniger internes Kopieren erfolgt als mit [<-.data.frame

Sie können lapply und replace verwenden, dann betrachten Sie jedes Mal nur einen Vektor oder length (nrow(df)). Und nicht so viel

df <- as.data.frame(lapply(df, function(x){replace(x, x <0,0)})

Der obige Code sollte ziemlich effizient sein.

Wenn Sie data.table verwenden, wird der größte Teil der Ineffizienz des data.frame-Speichers (und der Zeit) beseitigt. Dies wäre ideal für eine große Datensituation wie die Ihre.

library(data.table)
# this really shouldn't be 
DT <- lapply(df, function(x){replace(x, x <0,0)})
# change to data.table
setattr(DT, 'class', c('data.table','data.frame'))
# or 
# DT <- as.data.table(df, function(x){replace(x, x <0,0)})

Sie können Schlüssel für alle Spalten festlegen und dann Schlüsselwerte unter 0 durch Referenz ersetzen

22
mnel

Eine andere Antwort auf data.table ist möglicherweise schneller und sollte auf jeden Fall weniger Speicherplatz beanspruchen. 

library(data.table)
set.seed(108)
d = data.table(a=rnorm(1000),b=rnorm(1000))
set.colwise = function(x, i, j, value) {
  replace_dot_j = function(e, j) {
    if (is.symbol(e) && identical(e, as.symbol(".j"))) return(j)
    if (is.call(e)) {
      if (e[[1L]] == ".j") e[[1L]] = j
      for (i in seq_along(e)[-1L]) if (!is.null(e[[i]])) e[[i]] = replace_dot_j(e[[i]], j)
    }
    e
  }
  for (jj in j) eval(substitute(
    set(x, .i, .j, value),
    list(
      .i=replace_dot_j(substitute(i), jj),
      .j=jj
    )
  ))
  invisible(x)
}
d
set.colwise(d, i = which(d[[.j]] < 0), j = c("a","b"), value = 0)
d

Das .j-Symbol, das im i-Argument verwendet wird, wird wiederholt und durch Spalten aus dem j-Argument ersetzt.

0
jangorecki