2017-12-19 4 views
2

Ich versuche, die Werte innerhalb eines Datenrahmens in R zu ändern, indem ich eine Protokollumwandlung anwende.Anwenden einer Protokollfunktion in einem Datenrahmen

Mein Datenrahmen besteht nur aus numerischen Werten. Wenn ich diese Funktion anwenden

logFunct <- function(x) log10(x) 
dim(data.frame(logFunct(df)) 

alles gut funktioniert (das heißt 20 Spalten und 20 Zeilen von Datenrahmen werden als 20 Spalten werden zurückgegeben und 20 Zeilen neuer Datenrahmen).

Allerdings, wenn ich für Null-Werte mit dieser Funktion zu erklären versucht (ich weiß, es ist wahrscheinlich eine hässliche Funktion):

log4Zero <- function(x) ifelse(x!=0, log10(x+0.00000000001), log10(1)) 
dim(data.frame(log4Zero(df)) 

Ich habe 400 Spalten x 20 Zeilen und die Null-Werte wurden als nicht catched -zero (gab -11 statt 0 zurück).

Jeder kann bitte erklären, was hier passiert und wie kann ich das lösen (d. H. Nullwerte als Null erhalten und alles andere hinzugefügt und protokolliert)?

+0

warum verwenden nicht 'log (x + 1)' im allgemeinen? –

+0

meine Werte sind ziemlich niedrig, viele von ihnen sind wie unter 0,0001. Aber die Idee ist dieselbe, glaube ich. – kaka01

+1

Das ist nicht wirklich wichtig, wenn Sie die Ergebnisse nach Ihren Berechnungen zurücktransformieren –

Antwort

0

Wenn Sie ein Beispiel geben könnten, wäre es großartig. Wenn ich jedoch das Problem gut verstanden habe, reduziert Ihr data.frame seine Dimensionen. Nach dem Beispiel, das ich hier unten anführe, sollte das nicht passieren. Die zweite Funktion ist korrekt. Ich gebe Ihnen ein Beispiel, wie man es anwendet, damit es keine Probleme gibt. Hoffe das hilft:

library(tidyverse) 

set.seed(123) 

df <- as.data.frame(matrix(c(0, sample(0:14, size = 14)), ncol = 5)) 

df %>% 
    mutate_all(., ~ ifelse(.!=0, log10(.+0.00000000001), log10(1))) 
0

+1 für Rui Barradas 'Antwort oben verwenden log1p.

Sehr wichtig zu beachten - Ihre Lösung oben liefert log(x+1) nur für die ersten Ergebnisse von 0 und log(x+1e-11) für alles andere. Dies gibt Ihnen:

log4Zero(0) ~= log4Zero(1) 
log4Zero(0) >> log4Zero(1e-10) 

0 ist viel näher an 1e-10, als es auf 1 ist aber nach der Transformation Ihre Beobachtungen von genau 0 werden viel, viel höher ist als Ihre Beobachtungen von 1e-10. Ich bin mir fast sicher, dass das nicht das ist, was Sie wollen.

mit einigen Dummy-Daten:

df = data.frame(matrix(rnorm(400,5,1), nrow=20)) 
df[1,1] = 0 
df[2,1] = 1e-10 
log1p(df) 

Als ich log4Zero(df) laufen, wird eine Liste der Länge zurückgibt 400, kein Datenrahmen. Dies liegt daran, dass ifelse() bereits vektorisiert ist. Wenn Sie also einen ganzen Datenrahmen übergeben, wird nicht jeder Eintrag des Datenrahmens, sondern jede Spalte x sein. Von einem Datenrahmen von Dimensionen r von c, wird es eine Liste der Länge r * c, wobei jeder Eintrag zurückkehren entweder sein eine transformierte Spalte (log10(x+0.00000000001)) oder einen einzelnen Wert (log10(1))

Wenn Sie nicht möchten, eine Funktion anwenden mit ifelse() verwenden apply() statt:

logNew = function(x) ifelse(x!=0, log10(x), NA) 
apply(df, 2, logNew) 
Verwandte Themen