如果可能,寻找更有效的方法来实现此 R 代码

问题描述 投票:0回答:1

我有以下 R 代码,可以运行,但速度很慢。我想根据 R 数据框中现有列的值创建一个新列。但有一个问题/复杂性,我需要访问和更改一个全局环境变量,该变量保存观察值之间的比较值。 我使用 APPLY 和数据框行上的函数来完成此操作。该函数可以写入和读取外部变量。这有效但很慢。有什么办法可以加快这个过程吗?

第一次观察中药物的值是起始BASE_VALUE。 我想做的是标记与 BASE_VALUE 不同且不是 BASE_VALUE 的子字符串的观察结果(药物值)。然后,该观察结果的药物值将成为当前的 BASE_VALUE,并且该过程将继续。

可重现的代码如下:

base_value <- ""
char_vector <- c("applesauce", "apple", "orangeutan", "orange", "orange", "banana", "applepie") 

#change char_vector to a dataframe, the lastone column isn't completely necessary
df = data.frame(drug = char_vector) %>% 
mutate(lastone = lag(drug))

test_func <- function(row, output){
if (is.na(row[2])){
   #this is the first observation - set the drug value as BASE_VALUE
   base_value <<- row[1]
   return("Y")
 }else if (!is.na(row[2]) & row[1] != base_value & !grepl(row[1], base_value, fixed = TRUE)) {
   base_value <<- row[1]
   return("Y")
 }else {
   return("N")
 }
}


switches <- apply(df, 1, test_func)
cbind(df, switches = switches)

上面试过了,有效。但想加快速度

r performance processing-efficiency
1个回答
2
投票

你让生活变得太复杂了。

lag
str_detect
的明智组合可以为您提供所需的内容,而无需循环。

通过修改示例的最后一行来获取一些测试数据:

original <- cbind(df, switches = switches)

解决问题

library(tidyverse)

suggested <- df %>% 
  mutate(
    switches = ifelse(
      row_number() == 1, 
      "Y", 
      ifelse(
        str_detect(
          lag(drug), 
          drug
        ), 
        "N", 
        "Y"
      )
    )
  )
identical(suggested$switches, original$switches)
[1] TRUE

您的示例不够大,不足以使基准测试变得有意义,但这可能比循环更快。基础 R 解决方案可能会更快。 (不过,恕我直言,以牺牲可读性为代价。)您应该在现实生活中的数据集上进行测试,以确定哪个可能在生产中最好。

对于基准测试,请考虑

microbenchmark

© www.soinside.com 2019 - 2024. All rights reserved.