我的任务是编写一个函数,该函数旨在通过声明的变量(with ...
, new as (select 'i' as src ...),
, old as (select 'd' as src ...),
, combined as (select * from new union all select * from old)
select
Id, Col
min(case when src = 'i' then Change end) as newVal,
min(case when src = 'd' then Change end) as oldVal,
from combined
group by Id, Col;
的级别计算给定数据集(vars
)中给定变量(dset
)的对数。 )。如果给定级别byvar
的给定变量的最小值大于0,则计算简单的自然对数。否则,给定段的给定变量的新值计算为:
byvar
为了达到这个目的,我编写了这样一个代码(对于一个可重现的例子):
new.value = log(old.value + 1 + abs(min.value.of.given.var.for.given.level)
然而,它的可读性存在明显的问题。另外,我想知道它的性能是否会得到提升。最后但同样重要的是,目标是保持数据集中观察的顺序。任何形式的帮助/建议将不胜感激
答案 0 :(得分:2)
将我的评论转到答案:
不要重新发明轮子。有很好的方法可以按照组和#34;在base
(tapply
和ave
),data.table
,plyr
和dplyr
中。您不必提供以下功能:
my_log = function(x) {
m = min(x)
if (m > 0) return(log(x))
return(log1p(x - m))
}
以上实现了您描述的日志。由于您希望在多个列的相同分组上运行此功能,dplyr::mutate_each
可以让我们的生活轻松:
library(dplyr)
iris %>% group_by(Species) %>%
mutate_each(funs = funs(logged = my_log))
# Source: local data frame [150 x 11]
# Groups: Species [3]
#
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species random Sepal.Length_logged
# <dbl> <dbl> <dbl> <dbl> <fctr> <dbl> <dbl>
# 1 5.1 3.5 1.4 0.2 setosa 0.156703769 1.629241
# 2 4.9 3.0 1.4 0.2 setosa 1.373811191 1.589235
# 3 4.7 3.2 1.3 0.2 setosa 0.730670244 1.547563
# 4 4.6 3.1 1.5 0.2 setosa -1.350800927 1.526056
# 5 5.0 3.6 1.4 0.2 setosa -0.008514961 1.609438
# 6 5.4 3.9 1.7 0.4 setosa 0.320981863 1.686399
# 7 4.6 3.4 1.4 0.3 setosa -1.778148409 1.526056
# 8 5.0 3.4 1.5 0.2 setosa 0.909503835 1.609438
# 9 4.4 2.9 1.4 0.2 setosa -0.919404336 1.481605
# 10 4.9 3.1 1.5 0.1 setosa -0.157714831 1.589235
# # ... with 140 more rows, and 4 more variables: Sepal.Width_logged <dbl>, Petal.Length_logged <dbl>,
# # Petal.Width_logged <dbl>, random_logged <dbl>
这就是它的全部!这似乎很好,简洁,可读。如果你想&#34;功能化&#34;更重要的是,你可以将它包装成一个函数,如下所示,同样的结果:
log_vars = function(data, vars, byvar) {
data %>% group_by_(byvar) %>%
mutate_each_(funs = funs(logged = my_log), vars = vars) %>%
return
}
log_vars(iris, vars = c("Sepal.Width", "random"), byvar = "Species")
关于你的三个要求:
%>%
管道的情况下重写。