我尝试通过应用日志转换来更改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)。
任何人都可以请解释这里发生的事情以及如何解决这个问题(即将零值和零值以及其他任何添加和记录的内容)?
答案 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
作为数据帧的每个条目,而是每列。从维度r
到c
的数据框,它将返回长度为r * c
的列表,每个条目都是转换列(log10(x+0.00000000001)
)或单个值(log10(1)
)
如果您确实想使用ifelse()
应用功能,请改用apply()
:
logNew = function(x) ifelse(x!=0, log10(x), NA)
apply(df, 2, logNew)