¿Cómo transformar valores negativos en logaritmos?

12

Me gustaría saber cómo transformar valores negativos Log(), ya que tengo datos heteroscedasticos. Leí que funciona con la fórmula, Log(x+1)pero esto no funciona con mi base de datos y sigo obteniendo NaNs como resultado. Por ejemplo, recibo este mensaje de Advertencia (no puse mi base de datos completa porque creo que con uno de mis valores negativos es suficiente para mostrar un ejemplo):

> log(-1.27+1)
[1] NaN
Warning message:
In log(-1.27 + 1) : NaNs produced
> 

Gracias por adelantado

ACTUALIZAR:

Aquí hay un histograma de mis datos. Estoy trabajando con series de tiempo de paleontología de mediciones químicas, por ejemplo, la diferencia entre variables como Ca y Zn es demasiado grande, entonces necesito algún tipo de estandarización de datos, por eso estoy probando la log()función. ingrese la descripción de la imagen aquí

Esta es mi información en bruto

PC Darwin
fuente
2
El logaritmo solo se define para números positivos, y generalmente se usa como una transformación estadística en datos positivos para que un modelo conserve esta positividad. La log(x+1)voluntad de transformación solo se define para x > -1, ya que entonces x + 1es positiva. Sería bueno saber su razón para querer registrar la transformación de sus datos.
Matthew Drury
3
Cuéntanos más sobre los datos, incluido el rango, la media, las frecuencias de valores negativos, cero y positivos. Podría ser que un modelo lineal generalizado con enlace de registro tenga más sentido para los datos siempre que sea razonable pensar que la respuesta media es positiva. Puede ser que no debas transformarte en absoluto.
Nick Cox
66
Gracias por agregar detalles. Para tales datos 0 tiene un significado (¡igualdad!) Que debe ser respetado, de hecho preservado . Por esa y otras razones, usaría raíces cúbicas. En la práctica, necesitará alguna variación sign(x) * (abs(x))^(1/3); los detalles dependerán de la sintaxis del software. Para obtener más información sobre las raíces cúbicas, consulte, por ejemplo, stata-journal.com/sjpdf.html?articlenum=st0223 (consulte especialmente las págs. 152-3). Utilizamos raíces cúbicas para ayudar a visualizar una variable de respuesta que puede ser de naturaleza
Nick Cox
8
¿Por qué no estás transformando las variables originales en lugar de las diferencias?
whuber
44
log(x+4)x>45

Respuestas:

14

Como el logaritmo solo se define para números positivos, no puede tomar el logaritmo de los valores negativos. Sin embargo, si desea obtener una mejor distribución de sus datos, puede aplicar la siguiente transformación.

Supongamos que tiene datos negativos sesgados:

x <- rlnorm(n = 1e2, meanlog = 0, sdlog = 1)
x <- x - 5
plot(density(x))

(1,1)

z <- (x - min(x)) / (max(x) - min(x)) * 2 - 1
z <- z[-min(z)]
z <- z[-max(z)]
min(z); max(z)

y finalmente aplica la tangente hiperbólica inversa:

t <- atanh(z)
plot(density(t))

Ahora, sus datos se ven aproximadamente distribuidos normalmente. Esto también se llama transformación de Fisher.

Stochazesthai
fuente
99
atanh[(xmin(x))/(max(x)min(x))]
2
@ NickCox Tienes toda la razón. Tal vez si el OP agrega más detalles sobre su problema, ¡podríamos encontrar una solución alternativa!
stochazesthai
El argumento interno en mi primer comentario no es lo que se está transformando, pero creo que el espíritu de mi comentario no se ve afectado.
Nick Cox
Estimado @stochazesthai, gracias por su explicación detallada, pero no puedo aplicar su código a mis datos. Actualicé mi pregunta con un enlace de mis datos en bruto al final.
Darwin PC
Las declaraciones z <- z[-max(z)]y se z <- z[-min(z)]reducen inapropiadamente za un solo valor. También la función general atanh(((x - min(x)) / (max(x) - min(x))))produce Infpara los valores mínimo y máximo de x.
Max Ghenis
-1

Para transformarlo en una escala logarítmica, primero encuentre el registro del número positivo y luego multiplíquelo por su signo, el siguiente código debería hacer eso.

transform_to_log_scale <- function(x){
    if(x==0){
        y <- 1
    } else {
        y <- (sign(x)) * (log(abs(x)))
    }
        y 
    }

Usando el ejemplo anterior, podemos trazar la siguiente distribución sesgada

x <- rlnorm(n = 1e2, meanlog = 0, sdlog = 1)
x <- x - 5
plot(density(x))

ingrese la descripción de la imagen aquí

Después de usar la función de transformación de la siguiente manera, obtenemos una distribución que se ve más 'normal'

plot(density(sapply(x,FUN=transform_logs_scale)))

ingrese la descripción de la imagen aquí

yosemite_k
fuente
3
(1) La mayoría de los lenguajes de programación ( Rincluidos) implementan la función signum (que devuelve -1 para números negativos, 1 para números positivos y 0 para cero). Usarlo sería más expresivo y más rápido. (2) ¡Su propuesta es pobre para analizar datos como los ilustrados, porque tiene una gran discontinuidad en cero!
whuber
gracias por signum, no lo sabía, me pregunto cómo se implementa
yosemite_k
3
y <- 1x=0