如何:通过不重复创建新的数据帧来提高我的代码在R中的效率?

问题描述

问题:

首先,我刚刚开始。当我为自己的代码感到骄傲时,我意识到了将代码重新用于其他变量上是多么的低效和不可复制。特别是,#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函数中,即使我只打算在整个脚本中运行一次它。

为什么?

  1. 如果调试出现错误,发现调试起来很容易
  2. 在调试主题上,调试也更容易,因为环境将仅包含使用的变量,而不包含其他所有变量
  3. 函数调用结束后,辅助变量将自动删除
  4. 更容易记录带有标题的那段代码
  5. 更具可重复性

因此,我的脚本通常是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()

您自然可以加倍努力,并用其他变量代替对10003的提及(看起来像任意数字),并将其放在函数本身上。这样,如果您要更改它们,只需要明确提及要在运行函数时使用的值

fn.MyFunc(pf.raincount = NEWraincount)

或其他定义变量

我在所有变量上使用前缀来标识它们是什么fn(对于函数),df(对于数据帧),pf(对于函数参数),n(对于长度) 1个数字向量...列表非常广泛,我什至有一本规则手册,其中包含我用来在各个项目中保持一致的所有规则,但这也是另一回事了 最后,我发现# XXXXXX ####非常有用,因为我可以在不使用它们时隐藏代码块

同样,这就是我在成百上千的代码行中找到组织的方式。我们每个人都必须确定自己的风格,我相信我们所有人都同意的唯一一件事就是一致性是关键。

不过,我在讲一些话题,使用此包装器函数的关键思想是,您定义的其他表将保留在函数环境中,并随后被删除。最好实际编辑代码以免一开始就创建它们,但是至少您可以将此方法用作绷带,因为清理这些变量几乎不需要时间或技巧(我不必了解您的撰写这篇文章的代码)