Let's say I have a vector of some numbers, which can be < 1, but never <= 0.
> x = abs(rnorm(30))
> x
[1] 0.32590946 0.05018667 1.54354863 0.28925652 0.61712682 0.09444528
[7] 0.87951971 1.46243702 0.87099892 1.28553745 0.70360649 0.58973942
[13] 1.20054389 0.94429737 0.64038139 1.04173338 0.24249771 1.67273503
[19] 0.77546385 0.33547348 1.73480609 0.20757933 1.94491872 1.10547259
[25] 1.28570768 1.37621399 0.99389595 2.14107987 2.31719369 1.24458788
And when I log the entire vector I get negative values:
> log(x)
[1] -1.121135658 -2.992005742 0.434084070 -1.240441366 -0.482680726
[6] -2.359734671 -0.128379302 0.380104238 -0.138114546 0.251176883
[11] -0.351536037 -0.528074505 0.182774695 -0.057314153 -0.445691353
[16] 0.040886038 -1.416763021 0.514460030 -0.254293908 -1.092212359
[21] 0.550895644 -1.572241722 0.665220187 0.100272928 0.251309290
[26] 0.319336240 -0.006122756 0.761310314 0.840356837 0.218804452
Now the min of this vector is:
> min(x)
[1] 0.05018667
My question is this. I want to scale the data by 10^x
or by 2^x
(depends on log) so the log performed on this scaled set will produce only positive (or non-negative) numbers. How can I get the lowest exponent that will make it so?
CodePudding user response:
Maybe this fits your needs. The function scales the values such that the minimum value gets assigned to 1 and returns the exponent as well as the scaled vector as a list:
set.seed(123)
scale_log <- function(x, base = 2) {
y <- -log(min(x)) / log(base)
list(exp = y, scaled = base^y * x)
}
x <- abs(rnorm(5))
scale_log(x, 2)
#> $exp
#> [1] 3.826061
#>
#> $scaled
#> [1] 7.949063 3.264540 22.106706 1.000000 1.833650
log2(scale_log(x, 2)$scaled)
#> [1] 2.990785e 00 1.706880e 00 4.466412e 00 3.203427e-16 8.747185e-01
scale_log(x, 10)
#> $exp
#> [1] 1.151759
#>
#> $scaled
#> [1] 7.949063 3.264540 22.106706 1.000000 1.833650
log10(scale_log(x, 10)$scaled)
#> [1] 9.003159e-01 5.138220e-01 1.344524e 00 9.643275e-17 2.633165e-01