在数据框中应用日志功能

时间:2017-12-19 10:43:22

标签: r function vectorization transformation logarithm

我尝试通过应用日志转换来更改R中数据框内的值。

我的数据框只包含数值。当我应用这个功能时

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

一切正常(即20列和20行数据帧将返回20列和20行新数据帧)。

然而,当我尝试用这个函数来计算零值时(我知道,它可能是一个丑陋的函数):

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

我有400列x 20行,零值被捕获为非零(返回-11而不是0)。

任何人都可以请解释这里发生的事情以及如何解决这个问题(即将零值和零值以及其他任何添加和记录的内容)?

2 个答案:

答案 0 :(得分:0)

如果你能提供一个例子,那就太好了。但是,如果我已经很好地理解了这个问题,那么data.frame会减少它的尺寸。根据我在下面放置的示例,不应该发生。第二个功能是正确的。我举一个如何应用它的例子,所以没有问题。希望有所帮助:

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)))

答案 1 :(得分:0)

+1 Rui Barradas&#39;回答上述问题 - 使用log1p

非常重要的是要注意 - 上面的解决方案仅返回log(x+1)初始分数为0,其余为log(x+1e-11)。这给你:

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

0比1更接近1e-10但是在转换之后,你对0的观察结果将远远高于你对1e-10的观察结果。我几乎可以肯定这不是你想要的。

使用一些虚拟数据:

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

当我运行log4Zero(df)时,它返回一个长度为400的列表,而不是数据帧。这是因为ifelse()已经过矢量化。因此,如果将整个数据帧传递给它,则不会将x作为数据帧的每个条目,而是每列。从维度rc的数据框,它将返回长度为r * c的列表,每个条目都是转换列(log10(x+0.00000000001))或单个值(log10(1)

如果您确实想使用ifelse()应用功能,请改用apply()

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