问题描述
问题:
首先,我刚刚开始。当我为自己的代码感到骄傲时,我意识到了将代码重新用于其他变量上是多么的低效和不可复制。特别是,#3)在排除不太可重复的列(倾盆大雨,降水,雨水)时具有手动组件。有人可以建议吗? (如果您可以相信的话,情况看起来更糟)
代码:
# 1) filter for dictionaries containing 1,000 noun counts or more
f1_raincount <- raincount %>% filter(total_ncount >= 1000)
# 2) filter for dictionaries which contain 3 or more tokens from our set of rain-related tokens
f2_raincount <- f1_raincount
#compute rain-set count
f2_raincount$set_count <- f2_raincount %>% select(cloud:thunderstorm) %>% apply(1,function(x) sum(x != 0,values_drop_na=TRUE))
f2_raincount <- f2_raincount %>% filter(set_count >= 3)
# 3) Select for rain-related noun tokens with frequencies greater than 10 across dictionaries
#First,compute dictionary counts
f3_raincount <- f2_raincount
f3_dict_long <- f3_raincount %>% select(cloud:thunderstorm) %>% apply(2,function(x) sum(x !=0))
#Second,exclude those under 10: downpour,precipitation,rainwater
f3_raincount <- f3_raincount %>% select(-c(downpour,rainwater) )
# 4) given exclusion #3,compute rain set count and filter again
f4_raincount <- f3_raincount
f4_raincount$set_count2 <- f4_raincount %>% select(cloud:thunderstorm) %>% apply(1,function(x) sum(x != 0))
f4_raincount <- f4_raincount %>% filter(set_count2 >= 3) %>%
select(id:dictsize) #select final rain-set
解决方法
我通常要做的是将所有ETL代码都包含在ETL函数中,即使我只打算在整个脚本中运行一次它。
为什么?
- 如果调试出现错误,发现调试起来很容易
- 在调试主题上,调试也更容易,因为环境将仅包含使用的变量,而不包含其他所有变量
- 函数调用结束后,辅助变量将自动删除
- 更容易记录带有标题的那段代码
- 更具可重复性
因此,我的脚本通常是20%的设置参数和库 60%的功能和20%的代码可以运行这些功能
您的最终代码应如下所示:
f4_raincount <- funcName(raincount)
很自然地在funcName中包含了所有其他混乱的代码
对于实际的代码,我需要一个实际的示例(数据表和库),因为在我看来,您只是添加了可以用dplyr的mutate函数完成的计数列。如果确实如此,那么您:P就需要大量优化。但不知道是什么云:雷暴很难给您更多反馈。
编辑:
对我来说,ETL(提取转换负载)可能不是一个好主意,因为我们只是在转换数据,而不是提取或加载。
无论哪种方式,我都相信,如果我演示大量代码,那是最好的。 假设我们有一个数据框df.MyData,并想计算2个变量之间的比率乘以一定比率(正因为如此)
以下是解决这个简单问题的方法:
library(dplyr)
df.MyData <- data.frame(#this is of course a bad idea,But since a real world example would make this unreproducible code I went with it anyway.
Group = c("A","A","B","B"),Value = c(1,3,1,4,5)
)
n.Value_A <- sum(filter(df.MyData,Group == "A")$Value)
n.Value_B <- sum(filter(df.MyData,Group == "B")$Value)
n.Result <- n.Value_A / n.Value_B * pf.n.Ratio
这是我要怎么做:
# LIBRARY ####
library(dplyr)
# PARAMETERS ####
df.MyData <- data.frame(#this is of course a bad idea,But since a real world example would make this unreproducible code I went with it anyway.
Group = c("A",5)
)
# FUNCTIONS ####
fn.CalculateRatio <- function(pf.df.MyData = df.MyData,pf.n.Ratio = 2)
{
n.Value_A <- sum(filter(df.MyData,Group == "A")$Value)
n.Value_B <- sum(filter(df.MyData,Group == "B")$Value)
n.Result <- n.Value_A / n.Value_B * pf.n.Ratio
return(n.Result)
}
# PROCESS ####
fn.CalculateRatio()
我的方法显然具有更多的代码,因此很可能会被许多人忽略,但是我还是更喜欢它,因为我倾向于发现它在更大的代码段中更有条理。
您的示例如下所示:
fn.MyFunc <- function(pf.raincount = raincount){
# 1) filter for dictionaries containing 1,000 noun counts or more
f1_raincount <- pf.raincount %>% filter(total_ncount >= 1000)
.......[your code (excluding first 2 rows) goes here]
return(f4_raincount)
}
fn.MyFunc()
您自然可以加倍努力,并用其他变量代替对1000
和3
的提及(看起来像任意数字),并将其放在函数本身上。这样,如果您要更改它们,只需要明确提及要在运行函数时使用的值
fn.MyFunc(pf.raincount = NEWraincount)
或其他定义变量
我在所有变量上使用前缀来标识它们是什么fn
(对于函数),df
(对于数据帧),pf
(对于函数参数),n
(对于长度) 1个数字向量...列表非常广泛,我什至有一本规则手册,其中包含我用来在各个项目中保持一致的所有规则,但这也是另一回事了
最后,我发现# XXXXXX ####
非常有用,因为我可以在不使用它们时隐藏代码块
同样,这就是我在成百上千的代码行中找到组织的方式。我们每个人都必须确定自己的风格,我相信我们所有人都同意的唯一一件事就是一致性是关键。
不过,我在讲一些话题,使用此包装器函数的关键思想是,您定义的其他表将保留在函数环境中,并随后被删除。最好实际编辑代码以免一开始就创建它们,但是至少您可以将此方法用作绷带,因为清理这些变量几乎不需要时间或技巧(我不必了解您的撰写这篇文章的代码)