【问题标题】:How to: make my code more efficient in R by not creating new dataframes repeatedly?如何:通过不重复创建新数据框使我的代码在 R 中更高效?
【发布时间】:2020-09-22 13:33:21
【问题描述】:

问题:

首先,我才刚刚开始。虽然我为我的代码感到自豪,但我已经意识到它返回到它并在不同的变量上使用它是多么的低效和不可复制。特别是,#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, precipitation, 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

【问题讨论】:

    标签: r dplyr apply text-mining


    【解决方案1】:

    我通常所做的是将所有 ETL 代码放在一个 ETL 函数中,即使我只打算在整个脚本上运行一次。

    为什么?

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

    因此,我的脚本倾向于 20% 设置参数和库 60% 的函数和 20% 运行这些函数的代码

    您的最终代码应如下所示:

    f4_raincount <- funcName(raincount)
    

    在 funcName 中自然包含所有其他杂乱的代码

    至于实际代码,我需要一个实际示例(数据表和库),因为在我看来,您只是添加了可以使用 dplyr 的 mutate 函数完成的计数列。如果确实如此,那么您面前有很多优化:P。但不知道是什么cloud:thunderstorm 很难给你更多的反馈。

    编辑:

    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","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","A","B","B","B"),
                Value = c(1,3,1,4,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 #### 非常有用,因为我可以在不处理它们时隐藏代码块

    这也是我在数百或数千行代码中找到组织的方式。我们每个人都必须确定自己的风格,我相信我们都同意的唯一一点就是一致性是关键。

    不过,我有点紧张,使用此包装函数的关键思想是您定义的其他表保留在函数环境中并在之后被删除。最好实际编辑代码以不首先创建它们,但至少您可以将此方法用作绷带,因为清理这些变量几乎不需要时间或技能(我不必了解您的发这篇文章的代码)

    【讨论】:

    • 非常感谢您的反馈@user13900375! 3. 我意识到我犯了一个很大的错误,即没有创建辅助变量,一旦函数调用结束就会自动删除 - 现在不知道如何解决这个问题。这些是库:
    • 1.请问ETL函数是什么,我猜它对应于'funcName'?图书馆(dplyr)图书馆(tidyverse)图书馆(这里)云到雷暴是由1067个词典中这些单词的计数组成的列。在代码中,我将排除标准应用于单词样本,将 16 个单词减少到 13 个并消除数据框中的行。这是数据框的外观(上面包含变量):id、cloud、clouds、drizzle、hail、mist、monsoon、rain、rainbow、rainbow、rains、sleet、storm、relaystorm、dictsize
    • @n.baes 我已经编辑了我的答案。它现在大了很多,但我的意思也应该很清楚
    猜你喜欢
    • 2021-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-10
    • 2018-05-10
    • 1970-01-01
    • 2018-08-31
    • 1970-01-01
    相关资源
    最近更新 更多